Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "SimpleHoughClusterer.h"
00012
00013
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
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
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
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
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
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
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
00200 float windowSum=0;
00201 std::vector<double> hist2=hist;
00202 for ( int i=0; i<windowSize; i++ )
00203 {
00204
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
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
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