test-segmentLandmark.C

Go to the documentation of this file.
00001 /*! @file Landmark/test-segmentLandmark.C [put description here] */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2002   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; filed July 23, 2001, following provisional applications     //
00013 // No. 60/274,674 filed March 8, 2001 and 60/288,724 filed May 4, 2001).//
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Vidhya Navalpakkam <navalpak@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Landmark/test-segmentLandmark.C $
00035 // $Id: test-segmentLandmark.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 
00039 #include "Image/ColorOps.H"
00040 #include "Image/FilterOps.H"
00041 #include "Image/Image.H"
00042 #include "Image/ImageSet.H"
00043 #include "Image/ImageSetOps.H"
00044 #include "Image/MathOps.H"    // for binaryReverse()
00045 #include "Image/Pixels.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Image/Transforms.H" // for learningCoeff()
00048 #include "Image/fancynorm.H"
00049 #include "Landmark/Tree.H"
00050 #include "Landmark/density.H"
00051 #include "Raster/Raster.H"
00052 #include "Util/Timer.H"
00053 #include "Util/log.H"
00054 
00055 #include <cstdio>
00056 #include <iostream>
00057 #include <map>
00058 #include <vector>
00059 
00060 int countClusters(Image<float> input, float thresh)
00061 {
00062   // get image details
00063   int w = input.getWidth();
00064   int h = input.getHeight();
00065 
00066   int count = 0;
00067   for(int i = 0; i < w; i++)
00068     for(int j = 0; j < h; j++)
00069       {
00070         if(input.getVal(i,j) > thresh)
00071           {
00072             // flood starting at seed upto thresh
00073             Image<float> output;
00074             flood(input, output, Point2D<int>(i,j), thresh, 255.0f);
00075             input -= output;
00076             inplaceClamp(input, 0.0f, 255.0f);
00077             count++;
00078           }
00079       }
00080   return count;
00081 }
00082 
00083 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00084 
00085 int main (int argc, char **argv)
00086 {
00087   if (argc != 3)
00088     {
00089       std::cerr << "usage: test-segmentLandmark <option> <weight>\n\n \
00090                     where <option> is f (flat) or h (heirarchy)\n \
00091                     where <weight> is y (weight maps) or n (use all maps)\n";
00092       exit(2);
00093     }
00094   std::map<int, Object*> list;              // list of all objects
00095 
00096   // to initialise the edges, invoke density once
00097   Image<byte> img = density("feature1.input", list);
00098   int global_edge[list.size()][list.size()];       // clique of objects
00099   for(uint i = 0; i < list.size(); i++)
00100     for(uint j = 0; j < list.size(); j++)
00101       global_edge[i][j] = 0;
00102 
00103   int edge[list.size()][list.size()][42];
00104   for(uint i = 0; i < list.size(); i++)
00105     for(uint j = 0; j < list.size(); j++)
00106       for(uint k = 0; k < 42; k++)
00107         edge[i][j][k] = 0;
00108 
00109   //################### FIND CLUSTERS IN ALL FEATURES ###################
00110 
00111   for(int features = 1; features < 42; features++)
00112     {
00113       char filename[256];
00114       sprintf(filename, "feature%d.input", features);
00115       list.clear();
00116       Image<byte> img = density(filename, list);
00117       Raster::WriteGray(img, sformat("density_%d.pgm",features));
00118 
00119       Image<float> input = (Image<float>)(img);
00120       input = lowPass9(input);
00121       PixRGB<float> color(1, 0, 0);
00122       Raster::WriteRGB( stain(input, color),"input.ppm");
00123 
00124       //inplaceNormalize(input, 0.0f, 255.0f);
00125       int targets = countClusters(input, 0.0f);
00126       LDEBUG("# of targets = %d", targets);
00127 
00128       // statistics of the input image
00129       const int w = input.getWidth();
00130       const int h = input.getHeight();
00131       float min, max;
00132       getMinMax(input, min, max);
00133 
00134       // analyze the options
00135       bool flat = false, heirarchy = false;
00136       if(strcmp(argv[1],"f") == 0)
00137         {
00138           flat = true;
00139           std::cout<<"just get the members of each cluster"<<std::endl;
00140         }
00141       else if(strcmp(argv[1], "h") == 0)
00142         {
00143           heirarchy = true;
00144           std::cout<<"get the complete heirarchy"<<std::endl;
00145         }
00146       else
00147         std::cout<<"unrecognized option!";
00148 
00149       //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00150 
00151       // maintain the forest of trees or islands
00152       std::multimap<float, Tree*, std::greater<float> > forest;
00153 
00154 
00155       //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00156 
00157       // find the local maxima and store in a map (val, locn)
00158 
00159       std::multimap<float, Point2D<int>, std::greater<float> > maxima;
00160       int lm_num = 0;  // num of local maxima or peaks
00161 
00162       // we want to detect quickly local maxes, but avoid getting local mins
00163       float thresh = (min + (max - min) / 10.0);
00164       // this is a 1d image
00165       for (int index = 1; index < w - 1; index ++)
00166         {
00167           float val = input.getVal(index, 0);
00168           if (val >= thresh &&
00169               val >= input.getVal(index - 1 , 0) &&
00170               val >= input.getVal(index + 1, 0))
00171             {
00172               // insert into map
00173               Point2D<int> p(index, 0);
00174               maxima.insert(std::pair<float, Point2D<int> >(val, p));
00175               lm_num ++;
00176             }
00177         }
00178 
00179       LDEBUG(" # of local maxima = %"ZU"", maxima.size());
00180 
00181       if(maxima.size() == 0)
00182         {
00183           LERROR(" there r no maxima in this image!");
00184           break;
00185         }
00186       // to consider every peak above the ground level, insert a new member
00187       std::multimap<float, Point2D<int>, std::greater<float> >::iterator
00188         min_peak = maxima.end();
00189       min_peak --;
00190       maxima.insert(std::pair<float, Point2D<int> >(min_peak->first / 2,
00191                                               Point2D<int>(0, 0)));
00192 
00193 
00194       //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00195 
00196       // choose one local maxima at a time and flood upto the next local maxima
00197 
00198       std::multimap<float, Point2D<int>, std::greater<float> >::iterator itr;
00199 
00200       int iter = 0;
00201       Image< PixRGB<float> > cat;
00202       for( itr = maxima.begin(); itr != maxima.end(); iter++)
00203         {
00204           float thresh;
00205 
00206           if(heirarchy)
00207             {
00208               thresh = itr->first;
00209             }
00210 
00211           else if(flat)
00212             {
00213               // add all members to the forest except the last
00214               std::multimap<float, Point2D<int>, std::greater<float> >::iterator
00215                 last = maxima.end();
00216               last --;
00217               while( itr != last)
00218                 {
00219                   Tree* new_peak = new Tree(itr->second, itr->first);
00220                   forest.insert(std::pair<float, Tree*>(itr->first, new_peak));
00221                   itr++;
00222                 }
00223               // set thresh to the height of the last member
00224               thresh = last->first;
00225             }
00226 
00227           else break;
00228 
00229           Image<float> output = highThresh( input, thresh, 255.0f);
00230 
00231           // consider the maxima that are equal;
00232           // advance to the next lowest maxima
00233           while (itr != maxima.end() && itr->first == thresh )
00234             {
00235               // this peak is the start of a potential island: add a new tree
00236               Tree* new_peak = new Tree(itr->second, itr->first);
00237               forest.insert(std::pair<float, Tree*>(thresh, new_peak));
00238               itr++;
00239 
00240             }
00241 
00242           // recompute clusters: brute force
00243 
00244           cat.clear(PixRGB<float>(0.0f)); // an image containing all clusters
00245           int count = 0;
00246 
00247           // ################## FIND CLUSTERS ############################
00248           // now find all the connected components in the forest
00249 
00250           std::multimap<float, Tree*, std::greater<float> >::iterator tree,
00251             curr_peak;
00252           for(tree = forest.begin(); tree != forest.end(); )
00253             {
00254               Tree* current = tree->second;
00255 
00256               Image<float> output;
00257               Point2D<int> seed = current->node->loc;
00258               LDEBUG("current peak ======== (%d, %d)",
00259                      seed.i, seed.j);
00260               flood(input, output, seed, thresh, -255.0f);
00261 
00262               // find all member peaks of the current cluster
00263               std::vector<Tree* > to_merge;
00264               std::multimap<float, Tree*, std::greater<float> >::iterator
00265                 member = forest.begin();
00266               while(member != forest.end())
00267                 {
00268                   for(member = forest.begin(); member != forest.end();
00269                       member++)
00270                     {
00271                       if(output.getVal(member->second->node->loc) == -255.0f &&
00272                          member->second->node->loc != seed)
00273                         {
00274                           // this peak belongs to the cluster
00275                           to_merge.push_back(member->second);
00276                           /* erase it from the forest since it will be part of
00277                              the new merged tree
00278                           */
00279                           LDEBUG(" --------- (%d, %d)",
00280                                  member->second->node->loc.i,
00281                                  member->second->node->loc.j);
00282                           /*
00283                             FIXME: why does forest.erase give problems?
00284                           */
00285                           forest.erase(member);
00286                           break;
00287                         }
00288                     }
00289                 }
00290 
00291               if(to_merge.size() > 0)
00292                 {
00293                   // merge the current tree with this member of the forest
00294                   to_merge.push_back(current);
00295 
00296                   Tree* new_tree = new Tree(seed, current->node->height);
00297                   new_tree->mergeTrees(to_merge);
00298 
00299                   // erase the old tree
00300                   float height = tree->first;
00301                   forest.erase(tree);
00302 
00303                   // add the new merged tree to the forest
00304                   current = new_tree;
00305                   tree = forest.insert(std::pair<float, Tree*>
00306                                        (height, current));
00307                   tree++; // advance to the next tree in the forest
00308                 }
00309 
00310               else
00311                 {
00312                   // i am a loner:(
00313                   to_merge.push_back(current);
00314                   tree++; // advance to the next tree in the forest
00315                 }
00316 
00317               std::vector<Object*> siblings;
00318               // find objects that belong to this cluster
00319               for(uint l = 0; l < list.size(); l++)
00320                 {
00321                   if(output.getVal((int)list[l]->mu1, 0) == -255.0f)
00322                     {
00323                       siblings.push_back(list[l]);
00324                       //LDEBUG("sibling %s",list[l]->name.c_str());
00325                     }
00326 
00327                 }
00328 
00329               // set edge weights for siblings
00330               int size = siblings.size();
00331               for(int k = 0; k < size; k++)
00332                 for(int l = 0; l < size; l++)
00333                   {
00334                     edge[siblings[k]->tag][siblings[l]->tag][features]  += 1;
00335                     global_edge[siblings[k]->tag][siblings[l]->tag] += 1;
00336                     //LDEBUG("%d-%d :edge = %d, global_edge = %d",
00337                     //     siblings[k]->tag,siblings[l]->tag,
00338                     //     edge[siblings[k]->tag][siblings[l]->tag],
00339                     //     global_edge[siblings[k]->tag][siblings[l]->tag]);
00340                   }
00341               // reset the output (flooded image) to its normal state
00342               for(int k = 0; k < w; k ++)
00343                 for(int l = 0; l < h; l ++)
00344                   if(output.getVal(k,l) == -255.0f)
00345                     {
00346                       output.setVal(k, l, input.getVal(k, l));
00347                     }
00348 
00349               //LDEBUG(" size of cluster = %d", to_merge.size());
00350 
00351               // draw this cluster
00352               Image<PixRGB<float> > cluster;
00353               if(to_merge.size() > 0)
00354                 {
00355                   count++;
00356                   // generate colors of clusters
00357                   float red = 0.0f, green = 0.0f, blue = 0.0f;
00358 
00359                   if(count % 3 == 1)
00360                     {
00361                       red = 1.0f ; // / count;
00362                       green = 0.0f;
00363                       blue = 0.0f;
00364                       //LDEBUG("red....");
00365                     }
00366                   else if(count % 3 == 2)
00367                     {
00368                       green = 1.0f ; // / (count - 1);
00369                       blue = 0.0f;
00370                       red = 0.0f;
00371                       //LDEBUG("green...");
00372                     }
00373                   else if(count % 3 == 0)
00374                     {
00375                       blue = 1.0f ; // / (count - 2);
00376                       green = 0.0f;
00377                       red = 0.0f;
00378                       //LDEBUG("blue....");
00379                     }
00380 
00381                   PixRGB<float> color(red, green, blue);
00382                   //LDEBUG("color = (%f, %f, %f)", red, green, blue);
00383                   cluster =  stain(output, color);
00384 
00385                   if(cluster.initialized())
00386                     Raster::WriteRGB(cluster,sformat("clusters_%d.ppm", count-1));
00387                   else
00388                     LDEBUG("cluster not initialized!");
00389 
00390                   if(!cat.initialized())
00391                     cat = cluster;
00392                   else
00393                     cat += cluster;
00394                 }
00395 
00396               // FIXME
00397               //tree ++;
00398             }
00399 
00400           if(cat.initialized())
00401             Raster::WriteRGB((Image< PixRGB<byte> >)cat,
00402                              sformat("iter_%d_%d.ppm",
00403                                      iter,
00404                                      features));
00405           else
00406             LDEBUG("iter not initialized!");
00407           //LDEBUG(" # of clusters = %d", count);
00408           //LDEBUG("\n****************************************\n");
00409         }
00410 
00411 
00412       std::multimap<float, Tree*, std::greater<float> >::iterator tree;
00413       Image<PixRGB<byte> > plot = (Image< PixRGB<byte> >)cat;
00414       for(tree = forest.begin(); tree != forest.end(); tree++)
00415         tree->second->traverse(input, plot);
00416 
00417       Raster::WriteRGB(plot,"plot.ppm");
00418 
00419 
00420       // print out all the siblings
00421       // use law of transitivity :-)
00422       std::map<int, Object*>::iterator tr, jtr, start, stop;
00423       std::map<int, Object*> bak = list;
00424       for(tr = bak.begin(); tr != bak.end(); tr++)
00425         {
00426           start = tr;
00427           stop = bak.end();
00428           LINFO("%s", tr->second->name.c_str());
00429           for(jtr = tr ; jtr != stop; jtr ++)
00430             {
00431               if(edge[tr->second->tag][jtr->second->tag][features] == 1
00432                  && tr != jtr)
00433                 {
00434                   LINFO("%s", jtr->second->name.c_str());
00435                   bak.erase(jtr);
00436                 }
00437             }
00438           LINFO("---------------------------");
00439         }
00440 
00441     }
00442   if(strcmp(argv[2], "n") == 0)
00443     {
00444       // dont weight the maps; just add them uniformly
00445       std::map<int, Object*>::iterator tr, jtr, start, stop;
00446       for(int conf = 42; conf > 0; conf -- )
00447         {
00448           // evaluate the clusters with decreasing order of confidence
00449           LDEBUG("CONFIDENCE LEVEL = %d", conf);
00450           std::map<int, Object*> bak = list;
00451           for(tr = bak.begin(); tr != bak.end(); tr++)
00452             {
00453               start = tr;
00454               stop = bak.end();
00455               LINFO("%s", tr->second->name.c_str());
00456               for(jtr = tr ; jtr != stop; jtr ++)
00457                 {
00458                   if(global_edge[tr->second->tag][jtr->second->tag] >= conf
00459                      && tr != jtr)
00460                     {
00461                       LINFO("%s", jtr->second->name.c_str());
00462                       bak.erase(jtr);
00463                     }
00464                 }
00465               LINFO("---------------------------");
00466             }
00467           LINFO("################################################");
00468         }
00469     }
00470   else if(strcmp(argv[2], "y") == 0)
00471     {
00472       // weight the maps according to the channels
00473       for(uint i = 0; i < list.size(); i++)
00474         for(uint j = 0; j < list.size(); j++)
00475           {
00476             global_edge[i][j] = 0;
00477           }
00478       // use weighting
00479       for(uint i = 0; i < list.size(); i++)
00480         for(uint j = 0; j < list.size(); j++)
00481           {
00482             // color : 2 (rg and by)
00483             for(uint k = 0; k < 12; k++)
00484               global_edge[i][j] += edge[i][j][k];
00485             global_edge[i][j] /= 2;
00486 
00487             // intensity : 1
00488             for(uint k = 12; k < 18; k++)
00489               global_edge[i][j] += edge[i][j][k];
00490 
00491             // orientation: 4
00492             for(uint k = 18; k < 42; k++)
00493               global_edge[i][j] += edge[i][j][k];
00494             global_edge[i][j] /= 4;
00495           }
00496 
00497       // hence, max edge weight = 18
00498       std::map<int, Object*>::iterator tr, jtr, start, stop;
00499       for(int conf = 18; conf > 0; conf -- )
00500         {
00501           // evaluate the clusters with decreasing order of confidence
00502           LDEBUG("CONFIDENCE LEVEL = %d", conf);
00503           std::map<int, Object*> bak = list;
00504           for(tr = bak.begin(); tr != bak.end(); tr++)
00505             {
00506               start = tr;
00507               stop = bak.end();
00508               LINFO("%s", tr->second->name.c_str());
00509               for(jtr = tr ; jtr != stop; jtr ++)
00510                 {
00511                   if(global_edge[tr->second->tag][jtr->second->tag] >= conf
00512                      && tr != jtr)
00513                     {
00514                       LINFO("%s", jtr->second->name.c_str());
00515                       bak.erase(jtr);
00516                     }
00517                 }
00518               LINFO("---------------------------");
00519             }
00520           LINFO("################################################");
00521         }
00522     }
00523 
00524 }
00525 
00526 
00527 // ######################################################################
00528 /* So things look consistent in everyone's emacs... */
00529 /* Local Variables: */
00530 /* indent-tabs-mode: nil */
00531 /* End: */
Generated on Sun May 8 08:05:16 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3