SimpleHoughClusterer.cpp
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *  SimpleHoughClusterer.cpp
00003  *
00004  *  (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de>
00005  *           Universitaet Koblenz-Landau
00006  *
00007  *  Additional information:
00008  *  $Id: $
00009  *******************************************************************************/
00010 
00011 #include "SimpleHoughClusterer.h"
00012 
00013 // #include "Architecture/Tracer/Tracer.h" // TODO
00014 
00015 #include "Workers/Math/vec2.h"
00016 
00017 #include <assert.h>
00018 #include <map>
00019 #include <list>
00020 #include <math.h>
00021 
00022 
00023 #define THIS SimpleHoughClusterer
00024 
00025 THIS::THIS ( std::vector< KeyPoint >* keyPoints1,  std::vector< KeyPoint >* keyPoints2, std::list< KeyPointMatch >& matches )
00026 {
00027     m_KeyPoints1 = keyPoints1;
00028     m_KeyPoints2 = keyPoints2;
00029     m_Matches = matches;
00030     m_Log << "SimpleHoughClusterer created\n";
00031     m_Log << "Number of keypoints (scenePoints/objectImagePoints): " << m_KeyPoints1->size() << " / " << m_KeyPoints2->size() << std::endl;
00032 }
00033 
00034 
00035 THIS::~THIS()
00036 {
00037 }
00038 
00039 
00040 void THIS::eliminateByOrientation ( )
00041 {
00042     m_Log << std::endl << "-------- Orientation based elimination -----------" << std::endl;
00043 
00044     int numBins=80;
00045     int windowSize=numBins/16;
00046 
00047     //Turn Angle histogram
00048      std::vector<double> hist;
00049     hist.assign ( numBins, 0 );
00050 
00051     std::list<KeyPointMatch>::iterator currentMatch=m_Matches.begin();
00052     while ( currentMatch != m_Matches.end() )
00053     {
00054         hist[ int ( ( currentMatch->turnAngle+M_PI ) /M_PI/2.0 * numBins ) % numBins ]++;
00055         currentMatch++;
00056     }
00057 
00058      std::vector<bool> deleteMap=computeDeleteMap( hist, numBins, windowSize);
00059 
00060     //Delete
00061     currentMatch=m_Matches.begin();
00062     while ( currentMatch != m_Matches.end() )
00063     {
00064         int index=int ( ( currentMatch->turnAngle+M_PI ) /M_PI/2.0 * numBins ) % numBins;
00065         //non-max
00066         if ( deleteMap[ index ] )
00067         {
00068             m_Log << "deleting: " << currentMatch->turnAngle/M_PI*180.0 << "deg " << hist[ index ] << "hist";
00069             currentMatch = m_Matches.erase ( currentMatch );
00070         }
00071         else
00072         {
00073             currentMatch++;
00074         }
00075     }
00076 
00077     m_Log << "\nTurn angles: ";
00078     currentMatch=m_Matches.begin();
00079     while ( currentMatch != m_Matches.end() )
00080     {
00081         m_Log << currentMatch->turnAngle << " ";
00082         currentMatch++;
00083     }
00084     m_Log << "\n--- " << m_Matches.size() << " remaining after orientation based elimination.\n";
00085     m_Log << std::endl;
00086 }
00087 
00088 
00089 void THIS::eliminateByScale ( )
00090 {
00091     m_Log << std::endl << "-------- Scale based elimination -----------" <<  std::endl;
00092 
00093     int numBins=150;
00094     int windowSize=numBins/15;
00095     int maxOctaves=5;
00096 
00097     //scale quotient histogram
00098     std::vector<double> hist;
00099     hist.assign ( numBins, 0 );
00100 
00101     std::list<KeyPointMatch>::iterator currentMatch=m_Matches.begin();
00102     while ( currentMatch != m_Matches.end() )
00103     {
00104         int index = ( log2( currentMatch->scaleQuotient ) / (maxOctaves-1) / 2 + 0.5 ) * numBins;
00105         if ( index >= numBins ) { index=numBins-1; }
00106         if ( index < 0 ) { index=0; }
00107 
00108         hist[ index ]++;
00109         currentMatch++;
00110     }
00111 
00112      std::vector<bool> deleteMap=computeDeleteMap( hist, numBins, windowSize);
00113 
00114     //Delete
00115     currentMatch=m_Matches.begin();
00116     while ( currentMatch != m_Matches.end() )
00117     {
00118         int index = ( log2( currentMatch->scaleQuotient ) / maxOctaves / 2 + 0.5 ) * numBins;
00119         if ( index >= numBins ) { index=numBins-1; }
00120         if ( index < 0 ) { index=0; }
00121 
00122         //non-max
00123         if ( deleteMap[ index ] )
00124         {
00125             m_Log << "deleting: scale quotient=" << currentMatch->scaleQuotient << " log=" << log2(currentMatch->scaleQuotient) << "  histogram entry=" << hist[ index ];
00126             currentMatch = m_Matches.erase ( currentMatch );
00127         }
00128         else
00129         {
00130             currentMatch++;
00131         }
00132     }
00133 
00134     m_Log << "\nScale quotients: ";
00135     currentMatch=m_Matches.begin();
00136     while ( currentMatch != m_Matches.end() )
00137     {
00138         m_Log << currentMatch->scaleQuotient << " ";
00139         currentMatch++;
00140     }
00141     m_Log << "\n--- " << m_Matches.size() << " remaining after scale based elimination:\n";
00142 }
00143 
00144 void THIS::eliminateByPosition ( float maxDistance )
00145 {
00146     float turnAngle = getMeanTurnAngle();
00147     float scaleChange = getMeanScaleQuotient();
00148     Point2D sourceCenter;
00149     Point2D targetCenter;
00150 
00151     bool outlierFound = true;
00152 
00153     while ( outlierFound )
00154     {
00155       getCenters ( targetCenter, sourceCenter );
00156 
00157       outlierFound = false;
00158 
00159       std::list<KeyPointMatch>::iterator currentMatch=m_Matches.begin();
00160       while ( currentMatch != m_Matches.end() )
00161       {
00162           Point2D position1 = (*m_KeyPoints1)[ currentMatch->index1 ].position();
00163           Point2D position2 = (*m_KeyPoints2)[ currentMatch->index2 ].position();
00164 
00165           position2 -= sourceCenter.toVector();
00166           position2.rotate ( turnAngle );
00167           position2 *= scaleChange;
00168           position2 += targetCenter.toVector();
00169 
00170           float distance = position1.distance ( position2 );
00171           float meanScale = ( (*m_KeyPoints1)[ currentMatch->index1 ].scale+ (*m_KeyPoints2)[ currentMatch->index2 ].scale) / 2.0;
00172           distance /= meanScale;
00173 
00174           if ( distance > maxDistance )
00175           {
00176               m_Log << " deleting " << currentMatch->index1 << "->" << currentMatch->index2 << "(" << distance << ")  ";
00177               currentMatch = m_Matches.erase ( currentMatch );
00178               outlierFound = true;
00179           }
00180           else
00181           {
00182               currentMatch++;
00183           }
00184       }
00185     }
00186     m_Log << "\n--- " << m_Matches.size() << " remaining after position based elimination:\n";
00187 }
00188 
00189 
00190 std::vector<bool> THIS::computeDeleteMap( std::vector<double> hist, int numBins, int windowSize )
00191 {
00192   m_Log << "original histogram: ";
00193   for ( int i=0; i<numBins; i++ )
00194   {
00195     m_Log << hist[i] << " ";
00196   }
00197   m_Log <<  std::endl;
00198 
00199     //calc sliding window mean
00200   float windowSum=0;
00201   std::vector<double> hist2=hist;
00202   for ( int i=0; i<windowSize; i++ )
00203   {
00204         //cout << i << " ";
00205     windowSum+=hist2[i];
00206   }
00207   for ( int i=0; i<numBins; i++ )
00208   {
00209     hist[ ( i+ ( windowSize/2 ) ) % numBins ]=windowSum;
00210     windowSum-=hist2[i];
00211     windowSum+=hist2[ ( i+windowSize ) % numBins ];
00212   }
00213 
00214   m_Log << "    mean histogram: ";
00215   for ( int i=0; i<numBins; i++ )
00216   {
00217     m_Log << hist[i] << " ";
00218   }
00219   m_Log <<  std::endl;
00220 
00221     //find max
00222   float max=0;
00223   for ( int i=0; i<numBins; i++ )
00224   {
00225     if ( hist[i] > max ) max=hist[i];
00226   }
00227   m_Log << "           maximum: " << max << std::endl;
00228 
00229     //determine what to keep (elements which are near a maximum)
00230   std::vector<bool> deleteMap;
00231   deleteMap.assign ( numBins, true );
00232   for ( int i=0; i<numBins; i++ )
00233   {
00234     for ( int j=-windowSize/2; j<=windowSize/2; j++ )
00235     {
00236       if ( hist[ ( numBins+i+j ) %numBins] >= max )
00237       {
00238         deleteMap[i]=false;
00239         break;
00240       }
00241     }
00242   }
00243 
00244   m_Log << "            delete: ";
00245   for ( int i=0; i<numBins; i++ )
00246   {
00247     m_Log << deleteMap[i] << " ";
00248   }
00249   m_Log <<  std::endl;
00250   return deleteMap;
00251 }
00252 
00253 
00254 float THIS::getMeanTurnAngle() const
00255 {
00256     std::vector<float> turnAngles;
00257     turnAngles.reserve ( m_Matches.size() );
00258 
00259     std::list< KeyPointMatch >::const_iterator currentMatch=m_Matches.begin();
00260     while ( currentMatch != m_Matches.end() )
00261     {
00262         turnAngles.push_back ( currentMatch->turnAngle );
00263         currentMatch++;
00264     }
00265     float mean=Math::meanAngle ( turnAngles );
00266     return mean;
00267 }
00268 
00269 
00270 float THIS::getMeanScaleQuotient() const
00271 {
00272     std::vector<float> scaleQuotients;
00273     scaleQuotients.reserve ( m_Matches.size() );
00274 
00275     std::list< KeyPointMatch >::const_iterator currentMatch=m_Matches.begin();
00276     while ( currentMatch != m_Matches.end() )
00277     {
00278         scaleQuotients.push_back ( currentMatch->scaleQuotient );
00279         currentMatch++;
00280     }
00281     float mean=Math::mean ( scaleQuotients );
00282     return mean;
00283 }
00284 
00285 
00286 void THIS::getCenters ( Point2D& center1, Point2D& center2 )
00287 {
00288   double numPoints = double ( m_Matches.size() );
00289 
00290   std::list< KeyPointMatch >::iterator currentMatch=m_Matches.begin();
00291   while ( currentMatch != m_Matches.end() )
00292   {
00293     unsigned index1 = currentMatch->index1;
00294     unsigned index2 = currentMatch->index2;
00295 
00296     center1 += (*m_KeyPoints1)[index1].position().toVector();
00297     center2 += (*m_KeyPoints2)[index2].position().toVector();
00298 
00299     currentMatch++;
00300   }
00301 
00302   center1 = Point2D ( center1.x() / numPoints, center1.y() / numPoints );
00303   center2 = Point2D ( center2.x() / numPoints, center2.y() / numPoints );
00304 }
00305 
00306 
00307 std::string THIS::getLog()
00308 {
00309   return m_Log.str();
00310 }
00311 
00312 
00313 #undef THIS


obj_rec_gui
Author(s): AGAS/agas@uni-koblenz.de
autogenerated on Mon Oct 6 2014 02:53:43