GeometricHashing.C

00001 /*!@file SceneUnderstanding/GeometricHashing.C  Shape from shading */
00002 
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00006 // by the University of Southern California (USC) and the iLab at USC.  //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; application number 09/912,225 filed July 23, 2001; see      //
00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/FeatureMatching/GeometricHashing.C $
00036 // $Id: GeometricHashing.C 12962 2010-03-06 02:13:53Z irock $
00037 //
00038 
00039 #ifndef GeometricHashing_C_DEFINED
00040 #define GeometricHashing_C_DEFINED
00041 
00042 #include "FeatureMatching/GeometricHashing.H"
00043 #include "Image/DrawOps.H"
00044 #include "GUI/DebugWin.H"
00045 #include <fcntl.h>
00046 
00047 // ######################################################################
00048 GeometricHashing::GeometricHashing() :
00049   itsTableWidth(0.10),
00050   itsNumFeatures(0),
00051   itsNumBinEntries(0)
00052 {
00053   itsHashTable = Image<TableEntry>(32,32,ZEROS);
00054   itsTableWidth = 1/32.0;
00055 }
00056 
00057 // ######################################################################
00058 GeometricHashing::~GeometricHashing()
00059 {
00060 
00061 }
00062 
00063 //void GeometricHashing::addModel(const Model& model)
00064 //{
00065 //  itsModels.push_back(model);
00066 //
00067 //  //uint p1 = 0;
00068 //  //uint p2 = 1;
00069 //  for(uint p1 = 0; p1 < model.v.size(); p1++)
00070 //    for(uint p2 = p1; p2 < model.v.size(); p2++)
00071 //    {
00072 //      if (p1 == p2)
00073 //        continue;
00074 //      //Change basis
00075 //      std::vector<Point2D<float> > featureLoc = changeBasis(model.v, p1, p2);
00076 //
00077 //      //Add entries to hash table
00078 //      for(uint i=0; i<featureLoc.size(); i++)
00079 //      {
00080 //  //      LINFO("%i %fx%f",
00081 //  //          i, featureLoc[i].i, featureLoc[i].j);
00082 //        //Dont insert the basis points, since they are always at the same place
00083 //        if (i != p1 && i != p2)
00084 //          insertToHashTable(featureLoc[i], p1, p2, model.id, model.rot);
00085 //      }
00086 //    }
00087 //}
00088 
00089 void GeometricHashing::addModel(const Model& model)
00090 {
00091   itsModels.push_back(model);
00092 
00093   //Find the minimum bounding box
00094   Point2D<int> tl = model.v[0];
00095   Point2D<int> br = model.v[0];
00096   for(uint i=0; i<model.v.size(); i++)
00097   {
00098     if (br.i > model.v[i].i)
00099       br.i = model.v[i].i;
00100     if (br.j > model.v[i].j)
00101       br.j = model.v[i].j;
00102 
00103     if (tl.i < model.v[i].i)
00104       tl.i = model.v[i].i;
00105     if (tl.j < model.v[i].j)
00106       tl.j = model.v[i].j;
00107   }
00108 
00109   std::vector<Point2D<float> > featureLoc = changeBasis(model.v, tl, br);
00110   for(uint i=0; i<featureLoc.size(); i++)
00111     insertToHashTable(featureLoc[i], 0, 0, model.id, model.rot);
00112 
00113 }
00114 
00115 void GeometricHashing::insertToHashTable(const Point2D<float> loc,
00116     int p1, int p2, int modelId,
00117     Point3D<float> rot)
00118 {
00119 
00120   ModelTableEntry mte;
00121   mte.modelId = modelId;
00122   mte.rot = rot;
00123   mte.featureLoc = loc;
00124   mte.basisP1 = p1;
00125   mte.basisP2 = p2;
00126 
00127   Image<GeometricHashing::TableEntry>::iterator iter = findInHash(loc);
00128   if (iter != NULL)
00129     iter->modelEntries.push_back(mte);
00130 }
00131 
00132 
00133 Image<GeometricHashing::TableEntry>::iterator
00134   GeometricHashing::findInHash(const Point2D<float>& loc)
00135 {
00136   //Find the table location;
00137   int i = (itsHashTable.getWidth()/2) + int( floor(loc.i / itsTableWidth) );
00138   int j = (itsHashTable.getHeight()/2) + int( floor(loc.j / itsTableWidth) );
00139 
00140   Image<GeometricHashing::TableEntry>::iterator  iter = NULL;
00141 
00142   if (itsHashTable.coordsOk(i,j))
00143   {
00144     iter = itsHashTable.beginw();
00145     iter += (i + j*itsHashTable.getWidth());
00146   }
00147   return iter;
00148 }
00149 
00150 //std::vector<GeometricHashing::Acc> GeometricHashing::getVotes(std::vector<Point2D<int> >& input)
00151 //{
00152 //  std::vector<Acc> acc;
00153 //
00154 //  //Choose two points from the image to become the basis
00155 //  for(uint p1 = 0; p1 < input.size(); p1++)
00156 //    for(uint p2 = p1; p2 < input.size(); p2++)
00157 //    {
00158 //      if (p1 == p2)
00159 //        continue;
00160 //      //Change basis of input
00161 //      std::vector<Point2D<float> > newInput = changeBasis(input, p1, p2);
00162 //
00163 //      //For each input find the value in the hash table and count the votes
00164 //      for(uint i=0; i<newInput.size(); i++)
00165 //      {
00166 //        Image<GeometricHashing::TableEntry>::iterator iter =
00167 //          findInHash(newInput[i]);
00168 //        if (iter != NULL)
00169 //        {
00170 //          for(uint j=0; j<iter->modelEntries.size(); j++)
00171 //          {
00172 //            ModelTableEntry mte = iter->modelEntries[j];
00173 //
00174 //            //find the acc;
00175 //            bool found = false;
00176 //            for(uint i=0; i<acc.size(); i++)
00177 //            {
00178 //              if (acc[i].P1 == mte.basisP1 &&
00179 //                  acc[i].P2 == mte.basisP2 &&
00180 //                  acc[i].modelId == mte.modelId &&
00181 //                  acc[i].rot == mte.rot &&
00182 //                  acc[i].inputP1 == p1 &&
00183 //                  acc[i].inputP2 == p2)
00184 //              {
00185 //                found = true;
00186 //                acc[i].inputP1 = p1;
00187 //                acc[i].inputP2 = p2;
00188 //                acc[i].votes++;
00189 //              }
00190 //            }
00191 //
00192 //            if (!found)
00193 //            {
00194 //              Acc newAcc;
00195 //              newAcc.P1 = mte.basisP1;
00196 //              newAcc.P2 = mte.basisP2;
00197 //              newAcc.modelId = mte.modelId;
00198 //              newAcc.rot = mte.rot;
00199 //              newAcc.votes = 1;
00200 //              newAcc.inputP1 = p1;
00201 //              newAcc.inputP2 = p2;
00202 //              acc.push_back(newAcc);
00203 //            }
00204 //          }
00205 //        }
00206 //      }
00207 //    }
00208 //
00209 //  return acc;
00210 //}
00211 
00212 std::vector<GeometricHashing::Acc> GeometricHashing::getVotes(std::vector<Point2D<int> >& input)
00213 {
00214   std::vector<Acc> acc;
00215 
00216   if (input.size() <= 0)
00217     return acc;
00218 
00219   //Find the minimum bounding box
00220   Point2D<int> tl = input[0];
00221   Point2D<int> br = input[0];
00222   for(uint i=0; i<input.size(); i++)
00223   {
00224     if (br.i > input[i].i)
00225       br.i = input[i].i;
00226     if (br.j > input[i].j)
00227       br.j = input[i].j;
00228 
00229     if (tl.i < input[i].i)
00230       tl.i = input[i].i;
00231     if (tl.j < input[i].j)
00232       tl.j = input[i].j;
00233   }
00234 
00235   std::vector<Point2D<float> > newInput = changeBasis(input, tl, br);
00236 
00237   Point2D<float> center(tl.i+(br.i - tl.i)/2,
00238                         tl.j+(br.j - tl.j)/2);
00239 
00240 
00241   //For each input find the value in the hash table and count the votes
00242   for(uint i=0; i<newInput.size(); i++)
00243   {
00244     Image<GeometricHashing::TableEntry>::iterator iter =
00245       findInHash(newInput[i]);
00246     if (iter != NULL)
00247     {
00248       for(uint j=0; j<iter->modelEntries.size(); j++)
00249       {
00250         ModelTableEntry mte = iter->modelEntries[j];
00251 
00252         //find the acc;
00253         bool found = false;
00254         for(uint i=0; i<acc.size(); i++)
00255         {
00256           if (acc[i].modelId == mte.modelId &&
00257               acc[i].rot == mte.rot)
00258           {
00259             found = true;
00260             acc[i].votes++;
00261           }
00262         }
00263 
00264         if (!found)
00265         {
00266           Acc newAcc;
00267           newAcc.modelId = mte.modelId;
00268           newAcc.rot = mte.rot;
00269           newAcc.votes = 1;
00270           newAcc.center = center;
00271           acc.push_back(newAcc);
00272         }
00273       }
00274     }
00275   }
00276 
00277   return acc;
00278 }
00279 
00280 Image<PixRGB<byte> > GeometricHashing::getHashTableImage()
00281 {
00282 
00283   int binWidth = 10;
00284   Image<PixRGB<byte> > img(itsHashTable.getDims()*binWidth, ZEROS);
00285   drawGrid(img, binWidth, binWidth, 1, 1, PixRGB<byte>(0,0,255));
00286   drawLine(img, Point2D<int>(0, img.getHeight()/2),
00287                 Point2D<int>(img.getWidth(), img.getHeight()/2),
00288                 PixRGB<byte>(0,0,255),2);
00289   drawLine(img, Point2D<int>(img.getWidth()/2, 0),
00290                 Point2D<int>(img.getWidth()/2, img.getHeight()),
00291                 PixRGB<byte>(0,0,255),2);
00292 
00293   float scale = binWidth/itsTableWidth;
00294   for(uint i=0; i<itsHashTable.size(); i++)
00295   {
00296     TableEntry te = itsHashTable[i];
00297     for(uint j=0; j<te.modelEntries.size(); j++)
00298     {
00299       ModelTableEntry mte = te.modelEntries[j];
00300       int x = (img.getWidth()/2) + (int)(scale*mte.featureLoc.i);
00301       int y = (img.getHeight()/2) - (int)(scale*mte.featureLoc.j);
00302       drawCircle(img, Point2D<int>(x,y), 3, PixRGB<byte>(0,255,0));
00303     }
00304   }
00305 
00306   return img;
00307 
00308 }
00309 
00310 
00311 std::vector<Point2D<float> > GeometricHashing::changeBasis(
00312     const std::vector<Point2D<int> >& featureLoc,
00313     int p1, int p2)
00314 {
00315 
00316   std::vector<Point2D<float> > newFeatureLoc;
00317 
00318   float modelScale = 1/sqrt( squareOf(featureLoc[p2].i - featureLoc[p1].i) +
00319                              squareOf(featureLoc[p2].j - featureLoc[p1].j) );
00320 
00321   float ang = 0;
00322   if ((featureLoc[p2].i - featureLoc[p1].i) != 0)
00323     ang = -atan((featureLoc[p2].j - featureLoc[p1].j)/(featureLoc[p2].i - featureLoc[p1].i));
00324 
00325   //Rotate the model
00326   for(uint i=0; i<featureLoc.size(); i++)
00327   {
00328     float x = modelScale*(featureLoc[i].i);
00329     float y = modelScale*(featureLoc[i].j);
00330 
00331     newFeatureLoc.push_back(
00332         Point2D<float>((x * cos(ang) - y * sin(ang)),
00333                        (y * cos(ang) + x * sin(ang))));
00334   }
00335 
00336   //Offset so the midpoint is between points center
00337   Point2D<float> center(newFeatureLoc[p1].i+(newFeatureLoc[p2].i - newFeatureLoc[p1].i)/2,
00338                         newFeatureLoc[p1].j+(newFeatureLoc[p2].j - newFeatureLoc[p1].j)/2);
00339   for(uint i=0; i<newFeatureLoc.size(); i++)
00340     newFeatureLoc[i] -= center;
00341 
00342 
00343   return newFeatureLoc;
00344 }
00345 
00346 std::vector<Point2D<float> > GeometricHashing::changeBasis(
00347     const std::vector<Point2D<int> >& featureLoc,
00348     Point2D<int> tl,
00349     Point2D<int> br)
00350 {
00351 
00352   std::vector<Point2D<float> > newFeatureLoc;
00353 
00354   //Offset so the midpoint is between points center
00355   Point2D<float> center(tl.i+(br.i - tl.i)/2,
00356                         tl.j+(br.j - tl.j)/2);
00357 
00358   float modelScale = 1/sqrt( squareOf(br.i - tl.i) +
00359                              squareOf(br.j - tl.j) );
00360 
00361   //Transelate the model to 0,0 and scale it
00362   float ang = 0;
00363   for(uint i=0; i<featureLoc.size(); i++)
00364   {
00365     float x = modelScale*(featureLoc[i].i - center.i);
00366     float y = modelScale*(featureLoc[i].j - center.j);
00367 
00368     newFeatureLoc.push_back(
00369         Point2D<float>((x * cos(ang) - y * sin(ang)),
00370                        (y * cos(ang) + x * sin(ang))));
00371   }
00372 
00373   return newFeatureLoc;
00374 }
00375 
00376 void GeometricHashing::writeTable(const char* filename)
00377 {
00378   int fd;
00379 
00380   if ((fd = creat(filename, 0644)) == -1)
00381     LFATAL("Can not open %s for saving\n", filename);
00382 
00383   //Write the Dims of the table
00384   int ret;
00385   int width = itsHashTable.getWidth();
00386   int height = itsHashTable.getHeight();
00387   ret = write(fd, (char *) &width, sizeof(int));
00388   ret = write(fd, (char *) &height, sizeof(int));
00389 
00390   //Write each entry
00391   for(int j=0; j<height; j++)
00392     for(int i=0; i<width; i++)
00393     {
00394       GeometricHashing::TableEntry te = itsHashTable.getVal(i,j);
00395       //Write the size of the model entries
00396       size_t numEntries = te.modelEntries.size();
00397       ret = write(fd, (char *) &numEntries, sizeof(size_t));
00398       //Write the entries
00399       for(uint idx=0; idx<numEntries; idx++)
00400       {
00401         ModelTableEntry mte = te.modelEntries[idx];
00402         ret = write(fd, (char *) &mte, sizeof(ModelTableEntry));
00403       }
00404     }
00405 }
00406 
00407 void GeometricHashing::readTable(const char* filename)
00408 {
00409   int fd;
00410   if ((fd = open(filename, 0, 0644)) == -1) return;
00411 
00412   int ret;
00413   LINFO("Reading from %s", filename);
00414 
00415   //Write the Dims of the table
00416   int width;
00417   int height;
00418   ret = read(fd, (char *) &width, sizeof(int));
00419   ret = read(fd, (char *) &height, sizeof(int));
00420   LINFO("Width %i %i", width, height);
00421 
00422   itsHashTable = Image<TableEntry>(width,height,ZEROS);
00423 
00424   //Write each entry
00425   for(int j=0; j<height; j++)
00426     for(int i=0; i<width; i++)
00427     {
00428       //Write the size of the model entries
00429       size_t numEntries;
00430       ret = read(fd, (char *) &numEntries, sizeof(size_t));
00431 
00432       //Write the entries
00433       for(uint idx=0; idx<numEntries; idx++)
00434       {
00435         ModelTableEntry mte;
00436         ret = read(fd, (char *) &mte, sizeof(ModelTableEntry));
00437 
00438         Image<GeometricHashing::TableEntry>::iterator  iter = NULL;
00439         iter = itsHashTable.beginw();
00440         iter += (i + j*itsHashTable.getWidth());
00441         iter->modelEntries.push_back(mte);
00442       }
00443     }
00444 }
00445 
00446 // ######################################################################
00447 /* So things look consistent in everyone's emacs... */
00448 /* Local Variables: */
00449 /* indent-tabs-mode: nil */
00450 /* End: */
00451 
00452 #endif
00453 
Generated on Sun May 8 08:04:46 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3