OriChamferMatching.C

Go to the documentation of this file.
00001 /*!@file FeatureMatching/OriChamferMatching.C Oriented chamfer matching algs */
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: $
00036 // $Id: $
00037 //
00038 
00039 #ifndef ORICHAMFERMATCHING_C_DEFINED
00040 #define ORICHAMFERMATCHING_C_DEFINED
00041 
00042 #include "FeatureMatching/OriChamferMatching.H"
00043 #include "Image/DrawOps.H"
00044 #include "Image/MathOps.H"
00045 #include "GUI/DebugWin.H"
00046 #include "Util/FastMathFunctions.H"
00047 
00048 #include <stdio.h>
00049 
00050 // ######################################################################
00051 OriChamferMatching::OriChamferMatching() :
00052   itsUseOpenCV(false),
00053   itsMaxCost(100)
00054 {
00055 }
00056 
00057 // ######################################################################
00058 OriChamferMatching::OriChamferMatching(const std::vector<Line>& inLines,
00059     const int numDirections,
00060     const double oriCost,
00061     const Dims dims) :
00062   itsUseOpenCV(false),
00063   itsMaxCost(100)
00064 {
00065   setLines(inLines, numDirections, oriCost, dims);
00066 };
00067 
00068 // ######################################################################
00069 void OriChamferMatching::setLines(const std::vector<Line>& inLines,
00070     const int numDirections,
00071     const double oriCost,
00072     const Dims dims) 
00073 {
00074   itsLines = inLines;
00075   //Construct the distance transform image
00076 
00077   //Build an image set with all the lines that fall in the quantized region
00078   itsOriDistImages = ImageSet<float>(numDirections, dims);
00079 
00080   for(uint i=0; i<inLines.size(); i++)
00081   {
00082     Line l = inLines[i];
00083     l.quantize(numDirections);
00084 
00085     int oriIdx = l.getDirectionIdx();
00086     if (oriIdx < 0 || oriIdx > numDirections)
00087       LFATAL("OriIdx %i is out of range %i", oriIdx, numDirections);
00088     //drawLine(itsOriDistImages[oriIdx], (Point2D<int>)l.getP1(),
00089     //    (Point2D<int>)l.getP2(), (float)l.getLength());
00090     drawLine(itsOriDistImages[oriIdx], (Point2D<int>)l.getP1(),
00091         (Point2D<int>)l.getP2(), 255.0F);
00092   }
00093 
00094   //Construct the distance images
00095   for(int oriIdx = 0; oriIdx < numDirections; oriIdx++)
00096   {
00097     if (itsUseOpenCV)
00098     {
00099       Image<byte> linesImg = binaryReverse(itsOriDistImages[oriIdx], 255.0F);
00100       linesImg.deepcopy();
00101       cvDistTransform(img2ipl(linesImg), img2ipl(itsOriDistImages[oriIdx]), CV_DIST_L2, 5);
00102     } else {
00103       //itsOriDistImages[oriIdx] = saliencyChamfer34(itsOriDistImages[oriIdx]);
00104       itsOriDistImages[oriIdx] = chamfer34(itsOriDistImages[oriIdx]);
00105     }
00106 
00107   }
00108 
00109   //Update the orientation costs
00110   updateOriCost(oriCost);
00111   buildIntegralDistances();
00112   
00113   //for(int oriIdx = 0; oriIdx < numDirections; oriIdx++)
00114   //{
00115   //  LINFO("oriIdx %i", oriIdx);
00116   //  SHOWIMG(itsOriDistImages[oriIdx]);
00117   //}
00118 
00119 };
00120 
00121 void OriChamferMatching::updateOriCost(const double oriCost)
00122 {
00123   Dims d = itsOriDistImages[0].getDims();
00124 
00125   int size=d.w()*d.h();
00126   const int numDirections = itsOriDistImages.size();
00127 
00128   for(int k=0; k<size; k++) //For each pixel in the set
00129   {
00130     std::vector<float> costs(numDirections);
00131     //Assign the cost vector and Clamp all costs to maxCost
00132     for(uint i=0; i<costs.size(); i++)
00133     {
00134       costs[i] = itsOriDistImages[i][k];
00135       if (costs[i] > itsMaxCost)
00136         costs[i] = itsMaxCost;
00137     }
00138 
00139     //forward pass
00140     if (costs[0] > costs[numDirections-1] + oriCost)
00141       costs[0] = costs[numDirections-1] + oriCost;
00142 
00143     for (int i=1 ; i<numDirections; i++)
00144     {
00145       if (costs[i] > costs[i-1] + oriCost)
00146         costs[i] = costs[i-1] + oriCost;
00147     }
00148 
00149     if (costs[0] > costs[numDirections-1] + oriCost)
00150       costs[0] = costs[numDirections-1] + oriCost;
00151 
00152     for (int i=1 ; i<numDirections ; i++)
00153     {
00154       if (costs[i] > costs[i-1] + oriCost)
00155         costs[i] = costs[i-1] + oriCost;
00156       else
00157         break;
00158     }
00159 
00160     ////backward pass
00161     if (costs[numDirections-1] > costs[0] + oriCost)
00162       costs[numDirections-1] = costs[0] + oriCost;
00163     for (int i=numDirections-1 ; i>0 ; i--)
00164     {
00165       if (costs[i-1] > costs[i] + oriCost)
00166         costs[i-1] = costs[i] + oriCost;
00167     }
00168 
00169     if (costs[numDirections-1] > costs[0] + oriCost)
00170       costs[numDirections-1] = costs[0] + oriCost;
00171     for (int i=numDirections-1 ; i>0 ; i--)
00172     {
00173       if (costs[i-1] > costs[i] + oriCost)
00174         costs[i-1] = costs[i] + oriCost;
00175       else
00176         break;
00177     }
00178 
00179     //Assign the cost
00180     for (int i=0 ; i<numDirections ; i++)
00181       itsOriDistImages[i][k] = costs[i];
00182 
00183   }
00184 }
00185 
00186 
00187 void OriChamferMatching::buildIntegralDistances()
00188 {
00189   int numDirections = itsOriDistImages.size();
00190   itsOriIntDistImages.resize(numDirections);
00191 
00192   for(int i=0; i<numDirections; i++)
00193   {
00194                 double theta = (i*M_PI)/numDirections + M_PI/(2*numDirections);
00195     //printf("Theta %f\n", theta*180/M_PI);
00196 
00197     itsOriIntDistImages[i] = OriIntegralImage(itsOriDistImages[i], cos(theta), sin(theta));
00198   }
00199 }
00200 
00201 
00202 OriIntegralImage::OriIntegralImage(const Image<float>& distImage, float dx, float dy)
00203 {
00204         if (fabs(dx) > fabs(dy))
00205         {
00206                 itsDS = dy / (dx + 1e-9f);
00207                 itsXindexed = 1;                
00208         }
00209         else
00210         {
00211                 itsDS = dx / (dy + 1e-9f);
00212                 itsXindexed = 0;
00213         }
00214         // Compute secant
00215         itsFactor = sqrt(itsDS*itsDS + 1);
00216 
00217   //Build the indecies used to find the pixel location
00218   int width = distImage.getWidth();
00219   int height = distImage.getHeight();
00220 
00221   if (itsXindexed)
00222     itsIndices.resize(width);
00223   else
00224     itsIndices.resize(height);
00225 
00226   for(uint i=0; i<itsIndices.size(); i++)
00227     itsIndices[i] = (int)ceil(i*itsDS - 0.5);
00228 
00229   itsIntegralImage = Image<float>(width, height, NO_INIT);
00230 
00231   //Build the integral image
00232   for(int x=0; x<width; x++)
00233     itsIntegralImage.setVal(x,0, 0.0F);
00234 
00235   for(int y=0; y<height; y++)
00236     itsIntegralImage.setVal(0,y, 0.0F);
00237 
00238 
00239   if (itsXindexed)
00240   {
00241     int miny=0, maxy=0;
00242     //Find the miny and maxy
00243     if (itsIndices[width-1] > 0)
00244     {
00245       miny = -itsIndices[width-1];
00246       maxy = height;
00247     } else {
00248       miny = 0;
00249       maxy = height - itsIndices[width-1];
00250     }
00251 
00252     //Build the integral image
00253     for(int y=miny; y<=maxy; y++)
00254       for(int x=1; x<width; x++)
00255       {
00256         int py = y + itsIndices[x-1];
00257         int cy = y + itsIndices[x];
00258 
00259         if (cy > 0 && cy < height - 1)
00260           itsIntegralImage.setVal(x, cy, 
00261               itsIntegralImage.getVal(x-1,py) + itsIntegralImage.getVal(x,cy));
00262       }
00263   } else {
00264     int minx =0, maxx = 0;
00265     //Find the minx and maxx
00266     if(itsIndices[height-1]>0)
00267     {
00268       minx = -itsIndices[height-1];
00269       maxx = width;
00270     } else {
00271       minx = 0;
00272       maxx = width - itsIndices[height-1];
00273     }
00274 
00275     //Build the integral image
00276     for(int x=minx; x<=maxx; x++)
00277       for(int y=1; y<height; y++)
00278       {
00279         int px = x + itsIndices[y-1];
00280         int cx = x + itsIndices[y];
00281 
00282         if (cx > 0 && cx < width - 1)
00283           itsIntegralImage.setVal(cx, y, 
00284               itsIntegralImage.getVal(px, y-1) + itsIntegralImage.getVal(cx,y));
00285       }
00286         
00287   }
00288 
00289 }
00290 
00291 
00292 
00293 // ######################################################################
00294 /* So things look consistent in everyone's emacs... */
00295 /* Local Variables: */
00296 /* indent-tabs-mode: nil */
00297 /* End: */
00298 
00299 #endif
00300 
Generated on Sun May 8 08:40:38 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3