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