JunctionHOG.C

Go to the documentation of this file.
00001 /*!@file Features/JunctionHOG.C  */
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: Daniel Parks <danielfp@usc.edu>
00035 // $HeadURL$
00036 // $Id$
00037 //
00038 
00039 #include "Features/JunctionHOG.H"
00040 #include "SIFT/FeatureVector.H"
00041 
00042 JunctionHOG::JunctionHOG() :
00043   HistogramOfGradients(),
00044   itsNeighborDistance(0.0)
00045 {
00046   
00047 }
00048 
00049 JunctionHOG::JunctionHOG(bool normalize, Dims cellDims, bool fixedDims, int numOrientations, bool signedOrient, int numContinuityBins, float neighborDistance) :
00050   HistogramOfGradients(normalize,cellDims,fixedDims,numOrientations,signedOrient),
00051   itsContinuityBins(numContinuityBins),
00052   itsNeighborDistance(neighborDistance)
00053 {
00054   if(neighborDistance > 0)
00055     {
00056       for(int t=0;t<8;t++)
00057         {
00058           float ang=float(t)/8.0*M_PI;
00059           initializeNeighbors(itsRelevantNeighbors[t],itsPerpAngles[t],itsParallelAngles[t],ang);
00060         }
00061     }
00062 }
00063 
00064 JunctionHOG::~JunctionHOG() 
00065 {
00066 }
00067 
00068 
00069 std::vector<float> JunctionHOG::createHistogramFromGradient(const Image<float>& gradmag, const Image<float>& gradang)
00070 {
00071   std::vector<float> ret = HistogramOfGradients::createHistogramFromGradient(gradmag,gradang);
00072   std::vector<float> tmp = calculateJunctionHistogram(gradmag,gradang);
00073   ret.insert(ret.end(),tmp.begin(),tmp.end());
00074   return ret;
00075 }
00076 
00077 
00078 void JunctionHOG::initializeNeighbors(std::vector<Point2D<int> >& neighbors, std::vector<float>& perpAngles, std::vector<float>& parallelAngles, float angle)
00079 {
00080   // NOTE: This makes the same assumptions about an image that Rectangle.H makes, namely that (0,0) is the top left of the image
00081 
00082   // Remember atan2 has coords inverted: atan2(y,x) 
00083 
00084   // Left center point
00085   float lcprot=atan2(0,-1)+angle;
00086   Point2D<int> lcp=Point2D<int>(round(cos(lcprot)*itsNeighborDistance),round(sin(lcprot)*itsNeighborDistance));
00087   float lca=0+angle; 
00088   lca=(lca>M_PI) ? lca-M_PI : lca;
00089   float lcaPerp=(lca>M_PI/2.0) ? lca-M_PI/2.0 : lca+M_PI/2.0;
00090   neighbors.push_back(lcp); parallelAngles.push_back(lca); perpAngles.push_back(lcaPerp);
00091   // Left upper point
00092   float luprot=atan2(-1,-1)+angle;
00093   Point2D<int> lup=Point2D<int>(round(cos(luprot)*itsNeighborDistance),round(sin(luprot)*itsNeighborDistance));
00094   float lua=M_PI/4.0+angle; 
00095   lua=(lua>M_PI) ? lua-M_PI : lua;
00096   float luaPerp=(lua>M_PI/2.0) ? lua-M_PI/2.0 : lua+M_PI/2.0;
00097   neighbors.push_back(lup); parallelAngles.push_back(lua); perpAngles.push_back(luaPerp);
00098   // Left lower point
00099   float llprot=atan2(1,-1)+angle;
00100   Point2D<int> llp = Point2D<int>(round(cos(llprot)*itsNeighborDistance),round(sin(llprot)*itsNeighborDistance));
00101   float lla=M_PI-M_PI/4.0+angle; 
00102   lla=(lla>M_PI) ? lla-M_PI : lla;
00103   float llaPerp=(lla>M_PI/2.0) ? lla-M_PI/2.0 : lla+M_PI/2.0;
00104   neighbors.push_back(llp); parallelAngles.push_back(lla); perpAngles.push_back(llaPerp);
00105   
00106   // Right center point
00107   float rcprot=atan2(0,1)+angle;
00108   Point2D<int> rcp=Point2D<int>(round(cos(rcprot)*itsNeighborDistance),round(sin(rcprot)*itsNeighborDistance));
00109   float rca=0+angle; 
00110   rca=(rca>M_PI) ? rca-M_PI : rca;
00111   float rcaPerp=(rca>M_PI/2.0) ? rca-M_PI/2.0 : rca+M_PI/2.0;
00112   neighbors.push_back(rcp); parallelAngles.push_back(rca); perpAngles.push_back(rcaPerp);
00113   // Right upper point
00114   float ruprot=atan2(-1,1)+angle;
00115   Point2D<int> rup=Point2D<int>(round(cos(ruprot)*itsNeighborDistance),round(sin(ruprot)*itsNeighborDistance));
00116   float rua=M_PI/4.0+angle; 
00117   rua=(rua>M_PI) ? rua-M_PI : rua;
00118   float ruaPerp=(rua>M_PI/2.0) ? rua-M_PI/2.0 : rua+M_PI/2.0;
00119   neighbors.push_back(rup); parallelAngles.push_back(rua); perpAngles.push_back(ruaPerp);
00120   // Right lower point
00121   float rlprot=atan2(1,1)+angle;
00122   Point2D<int> rlp = Point2D<int>(round(cos(rlprot)*itsNeighborDistance),round(sin(rlprot)*itsNeighborDistance));
00123   float rla=M_PI-M_PI/4.0+angle; 
00124   rla=(rla>M_PI) ? rla-M_PI : rla;
00125   float rlaPerp=(rla>M_PI/2.0) ? rla-M_PI/2.0 : rla+M_PI/2.0;
00126   neighbors.push_back(rlp); parallelAngles.push_back(rla); perpAngles.push_back(rlaPerp);
00127 
00128 }
00129 
00130 
00131 std::vector<float> JunctionHOG::calculateJunctionHistogram(Image<float> gradmag, Image<float> gradang)
00132 {
00133   // Determine the number of cells, based on whether we have fixed dims or not
00134   Dims cells;
00135   if(itsFixedDims)
00136     cells = itsCellDims;
00137   else
00138     cells = Dims(int(round(float(gradmag.getWidth())/itsCellDims.w())),int(round(float(gradmag.getHeight())/itsCellDims.h())));
00139 
00140   const int w=gradmag.getWidth(), h=gradmag.getHeight();
00141 
00142   // Create a SIFT-like feature vector to soft bin the continuity values
00143   FeatureVector cntfv = FeatureVector(cells.w(),cells.h(),itsContinuityBins,true);
00144   Image<float>::const_iterator gmg = gradmag.begin(), gang = gradang.begin();
00145 
00146   // loop over rows:
00147   for (int i = 0; i < w; i ++)
00148     {
00149       // loop over columns:
00150       for (int j = 0; j < h; j ++)
00151         {
00152           // Check for line continuity using unsigned angles into bins [0-7]
00153           int oriBin=floor(((*gang < 0) ?  *gang + M_PI : *gang)/M_PI*8);
00154           float continuityStrength=0;
00155           float continuityParallel=0;
00156           int validNeighbors = 0;
00157           // Go through all relevant neighbors and accumulate continuity votes
00158           for(size_t n=0;n<itsRelevantNeighbors[oriBin].size();n++)
00159             {
00160               Point2D<int> neigh = itsRelevantNeighbors[oriBin][n];
00161               if(!gradmag.coordsOk(i+neigh.i,j+neigh.j))
00162                 {
00163                   // Ignore this neighbor, it is outside of image bounds
00164                   continue;
00165                 }
00166               int offset=neigh.i*h+neigh.j;
00167               // Convert neighbor orientation to unsigned orientation
00168               float unsignedNeighAng=(gang[offset] < 0) ?  gang[offset] + M_PI : gang[offset];
00169               // Vote strength of neighbor
00170               continuityStrength += gmg[offset]; // gradmag.getValInterp(neigh);
00171               // Add parallel support for continuity
00172               float ctrParallel=itsParallelAngles[oriBin][n];
00173               //LINFO("offset %d ctrParallel %f, uNO %f",offset,ctrParallel,unsignedNeighAng);
00174               continuityParallel += cos(fabs(ctrParallel-unsignedNeighAng));
00175               // Perpendicular support is negative parallel support
00176               float ctrPerp=itsPerpAngles[oriBin][n];
00177               continuityParallel -= cos(fabs(ctrPerp-unsignedNeighAng));
00178               ASSERT(!isnan(continuityParallel) && !isnan(continuityStrength));
00179               validNeighbors++;
00180             }
00181           // Normalize by the number of contributing neighbors
00182           if(itsNormalize && validNeighbors>0)
00183             {
00184               continuityParallel/=float(validNeighbors);
00185               continuityStrength/=float(validNeighbors);
00186             }
00187           float continuityAng = atan2(continuityParallel,continuityStrength);
00188           float continuityMag = sqrt(continuityParallel*continuityParallel+continuityStrength*continuityStrength);
00189 
00190           // Get bin fractions
00191           const float xf = float(i)/float(w)*cells.w();
00192           const float yf = float(j)/float(h)*cells.h();
00193           // Add Orientation to bin (always unsigned orientation)
00194           addToBin(xf,yf,continuityAng,continuityMag,true,cntfv);
00195           gmg++;
00196           gang++;
00197         }
00198     }
00199   // Return the continuity histogram
00200   
00201   std::vector<float> hist;
00202   if(itsNormalize)
00203     hist = normalizeFeatureVector(cntfv);
00204   else
00205     hist = cntfv.getFeatureVector();
00206   LINFO("Calculated Junction Histogram of size %Zu",hist.size());
00207   return hist;
00208 }
00209 
Generated on Sun May 8 08:04:47 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3