GSoC2011SfM
0.1
Google Summer of Code 2011: Structure from motion
|
00001 00002 #include <boost/thread/thread.hpp> 00003 00004 #include <iostream> 00005 #include <sstream> 00006 00007 #include "SequenceAnalyzer.h" 00008 #include "Boost_Matching.h" 00009 #include "Camera.h" 00010 00011 #include "config_SFM.h" //SEMAPHORE 00012 00013 using cv::Ptr; 00014 using cv::Mat; 00015 using cv::DMatch; 00016 using cv::KeyPoint; 00017 using std::vector; 00018 using cv::Point3d; 00019 00020 namespace OpencvSfM{ 00021 00022 int SequenceAnalyzer::mininum_points_matches = 20; 00023 int SequenceAnalyzer::mininum_image_matches = 2; 00024 00025 00026 SequenceAnalyzer::SequenceAnalyzer( 00027 cv::Ptr<cv::FeatureDetector> feature_detector, 00028 cv::Ptr<cv::DescriptorExtractor> descriptor_extractor, 00029 cv::Ptr<PointsMatcher> match_algorithm ) 00030 :match_algorithm_( match_algorithm ), 00031 feature_detector_( feature_detector ), 00032 descriptor_extractor_( descriptor_extractor ) 00033 { 00034 00035 } 00036 00037 SequenceAnalyzer::SequenceAnalyzer( MotionProcessor input_sequence, 00038 cv::Ptr< cv::FeatureDetector > feature_detector, 00039 cv::Ptr< cv::DescriptorExtractor > descriptor_extractor, 00040 cv::Ptr< PointsMatcher > match_algorithm ) 00041 :match_algorithm_( match_algorithm ), 00042 feature_detector_( feature_detector ), 00043 descriptor_extractor_( descriptor_extractor ) 00044 { 00045 //only finite sequences can be used: 00046 CV_DbgAssert( input_sequence.isBidirectional( ) ); 00047 //go back to the begining: 00048 input_sequence.setProperty( CV_CAP_PROP_POS_FRAMES,0 ); 00049 00050 //load entire sequence! Can be problematic but if a user want to have 00051 //more controls, he can use the other constructor... 00052 00053 int nbFrame=0; 00054 Mat currentImage=input_sequence.getFrame( ); 00055 while ( !currentImage.empty( ) )// && nbFrame<50 ) 00056 { 00057 addImageToPipeline( currentImage ); 00058 nbFrame++; 00059 currentImage=input_sequence.getFrame( ); 00060 } 00061 } 00062 00063 SequenceAnalyzer::SequenceAnalyzer( 00064 std::vector< cv::Ptr< PointsToTrack > > &points_to_track, 00065 std::vector< cv::Mat > *images, 00066 cv::Ptr<PointsMatcher> match_algorithm ) 00067 :points_to_track_( points_to_track ) 00068 { 00069 if( match_algorithm.empty() ) 00070 match_algorithm_ = new PointsMatcher( 00071 Ptr<cv::DescriptorMatcher>( new cv::FlannBasedMatcher( ) ) ); 00072 else 00073 match_algorithm_ = match_algorithm; 00074 if( images != NULL) 00075 images_ = (*images); 00076 } 00077 00078 //by default, use flann based matcher 00079 SequenceAnalyzer::SequenceAnalyzer( cv::FileNode file, 00080 std::vector<cv::Mat> *images, 00081 cv::Ptr<PointsMatcher> match_algorithm ) 00082 { 00083 if( match_algorithm.empty() ) 00084 match_algorithm_ = new PointsMatcher( 00085 Ptr<cv::DescriptorMatcher>( new cv::FlannBasedMatcher( ) ) ); 00086 else 00087 match_algorithm_ = match_algorithm; 00088 if( images != NULL) 00089 images_ = (*images); 00090 read( file,*this ); 00091 } 00092 00093 SequenceAnalyzer::~SequenceAnalyzer( void ) 00094 { 00095 } 00096 00097 void SequenceAnalyzer::addImageToPipeline( cv::Mat image, cv::Ptr<PointsToTrack> points ) 00098 { 00099 if( points.empty( ) ) 00100 { 00101 CV_DbgAssert( !feature_detector_.empty( ) && 00102 !descriptor_extractor_.empty( ) ); 00103 int nbFrame = points_to_track_.size( ); 00104 Ptr<PointsToTrack> ptrPoints_tmp( new PointsToTrackWithImage ( 00105 nbFrame, image, feature_detector_, descriptor_extractor_ )); 00106 ptrPoints_tmp->computeKeypointsAndDesc( ); 00107 00108 points_to_track_.push_back( ptrPoints_tmp ); 00109 } 00110 else 00111 points_to_track_.push_back( points ); 00112 00113 images_.push_back( image ); 00114 } 00115 00116 void SequenceAnalyzer::addImageToTracks( cv::Mat image, cv::Ptr<PointsToTrack> points ) 00117 { 00118 if( points.empty( ) ) 00119 { 00120 CV_DbgAssert( !feature_detector_.empty( ) && 00121 !descriptor_extractor_.empty( ) ); 00122 int nbFrame = points_to_track_.size( ); 00123 points = new PointsToTrackWithImage ( 00124 nbFrame, image, feature_detector_, descriptor_extractor_ ); 00125 points->computeKeypointsAndDesc( ); 00126 00127 points_to_track_.push_back( points ); 00128 } 00129 else 00130 points_to_track_.push_back( points ); 00131 00132 images_.push_back( image ); 00133 00135 //First compute missing features descriptors: 00136 vector< Ptr< PointsToTrack > >::iterator matches_it = 00137 points_to_track_.begin( ), 00138 end_matches_it = points_to_track_.end( ); 00139 00140 Ptr<PointsMatcher> point_matcher = match_algorithm_->clone( true ); 00141 point_matcher->add( points ); 00142 point_matcher->train( ); 00143 int i = 0; 00144 while ( matches_it != end_matches_it ) 00145 { 00146 Ptr<PointsMatcher> point_matcher1 = match_algorithm_->clone( true ); 00147 point_matcher1->add( points_to_track_[i] ); 00148 point_matcher1->train( ); 00149 00150 00151 std::vector< cv::DMatch > matches = SequenceAnalyzer::simple_matching( 00152 point_matcher, point_matcher1, 10 ); 00153 00154 i++; 00155 matches_it++; 00156 } 00157 00158 //compute the color of each matches: 00159 unsigned int max_tracks = tracks_.size(); 00160 for(unsigned int t=0;t<max_tracks; t++) 00161 { 00162 TrackOfPoints& tmp = tracks_[t]; 00163 if(tmp.color == 0) 00164 { 00165 unsigned int max_points = tmp.point_indexes_.size(); 00166 int R = 0, G = 0, B = 0; 00167 for(unsigned int j=0; j<max_points; ++j) 00168 { 00169 unsigned int img_idx = tmp.images_indexes_[j]; 00170 unsigned int pt_idx = tmp.point_indexes_[j]; 00171 00172 unsigned int packed_color = points_to_track_[ img_idx ]->getColor( pt_idx ); 00173 R += (packed_color>>16) & 0x000000FF; 00174 G += (packed_color>>8) & 0x000000FF; 00175 B += (packed_color) & 0x000000FF; 00176 } 00177 R /= max_points; 00178 G /= max_points; 00179 B /= max_points; 00180 tmp.color = (unsigned int)( 00181 ((R<<16) & 0x00FF0000) | ((R<<8) & 0x0000FF00)| (B & 0x000000FF)); 00182 } 00183 } 00184 TrackOfPoints::fusionDuplicates( tracks_ ); 00186 } 00187 00188 void SequenceAnalyzer::computeMatches( uchar nbMaxThread, bool printProgress ) 00189 { 00190 //First compute missing features descriptors: 00191 vector< Ptr< PointsToTrack > >::iterator matches_it = 00192 points_to_track_.begin( ), 00193 end_matches_it = points_to_track_.end( ); 00194 MatchingThread::size_list = points_to_track_.size(); 00195 MatchingThread::match_algorithm = match_algorithm_; 00196 00197 MatchingThread::matches_ = &points_to_track_; 00198 00199 double nbMatches = points_to_track_.size(); 00200 MatchingThread::total_matches = nbMatches * nbMatches / 2.0; 00201 MatchingThread::current_match_ = 0; 00202 MatchingThread::print_progress_ = printProgress; 00203 00204 //then init the fundamental matrix list: 00205 list_fundamental_.clear(); 00206 00207 for( size_t cpt = 0; cpt<MatchingThread::size_list; ++cpt ) 00208 list_fundamental_.push_back( 00209 vector< cv::Ptr<Mat> > ( MatchingThread::size_list - cpt + 1 ) ); 00210 00211 //Try to match each picture with other: 00212 vector<Mat> masks; 00213 00214 MatchingThread::mininum_points_matches = mininum_points_matches; 00215 unsigned int nb_proc = MIN( nbMaxThread, boost::thread::hardware_concurrency() ); 00216 INIT_SEMAPHORE( MatchingThread::thread_concurr, nb_proc ); 00217 INIT_MUTEX( MatchingThread::thread_unicity ); 00218 00219 unsigned int i=0; 00220 00221 while ( matches_it != end_matches_it ) 00222 { 00223 //can we start a new thread? 00224 P_MUTEX( MatchingThread::thread_concurr ); 00225 //create local values for the thead: 00226 MatchingThread match_thread(this, i ); 00227 //start the thread: 00228 boost::thread myThread(match_thread); 00229 00230 i++; 00231 matches_it++; 00232 } 00233 for(unsigned int wait_endThread = 0; 00234 wait_endThread<nb_proc ; ++wait_endThread) 00235 P_MUTEX( MatchingThread::thread_concurr );//wait for last threads 00236 00237 //compute the color of each matches: 00238 unsigned int max_tracks = tracks_.size(); 00239 for(unsigned int t=0;t<max_tracks; t++) 00240 { 00241 TrackOfPoints& tmp = tracks_[t]; 00242 unsigned int max_points = tmp.point_indexes_.size(); 00243 int R = 0, G = 0, B = 0; 00244 for(unsigned int j=0; j<max_points; ++j) 00245 { 00246 unsigned int img_idx = tmp.images_indexes_[j]; 00247 unsigned int pt_idx = tmp.point_indexes_[j]; 00248 00249 unsigned int packed_color = points_to_track_[ img_idx ]->getColor( pt_idx ); 00250 R += (packed_color>>16) & 0x000000FF; 00251 G += (packed_color>>8) & 0x000000FF; 00252 B += (packed_color) & 0x000000FF; 00253 } 00254 R /= max_points; 00255 G /= max_points; 00256 B /= max_points; 00257 tmp.color = (unsigned int)( 00258 ((R<<16) & 0x00FF0000) | ((R<<8) & 0x0000FF00)| (B & 0x000000FF)); 00259 } 00260 TrackOfPoints::fusionDuplicates( tracks_ ); 00261 } 00262 00263 void SequenceAnalyzer::keepOnlyCorrectMatches( 00264 std::vector<TrackOfPoints>& tracks, 00265 unsigned int min_matches, unsigned int min_consistance ) 00266 { 00267 unsigned int tracks_size = tracks.size( ); 00268 unsigned int index=0; 00269 00270 while ( index < tracks_size ) 00271 { 00272 if( ( tracks[ index ].getNbTrack( ) < min_matches ) || 00273 ( tracks[ index ].track_consistance < (int)min_consistance ) ) 00274 { 00275 //problem with this track, too small to be consistent 00276 // or inconsistant... 00277 tracks_size--; 00278 tracks[ index ]=tracks[ tracks_size ]; 00279 tracks.pop_back( ); 00280 index--; 00281 } 00282 index++; 00283 } 00284 } 00285 00286 void SequenceAnalyzer::addMatches( std::vector< cv::DMatch > &newMatches, 00287 unsigned int img1, unsigned int img2 ) 00288 { 00289 //add to tracks_ the new matches: 00290 00291 vector<DMatch>::iterator match_it = newMatches.begin( ); 00292 vector<DMatch>::iterator match_it_end = newMatches.end( ); 00293 00294 while ( match_it != match_it_end ) 00295 { 00296 DMatch &point_matcher = ( *match_it ); 00297 00298 bool is_found=false; 00299 vector<TrackOfPoints>::iterator tracks_it = tracks_.begin( ); 00300 while ( tracks_it != tracks_.end( ) && !is_found ) 00301 { 00302 TrackOfPoints& track = ( *tracks_it ); 00303 00304 if( track.containPoint( img1,point_matcher.trainIdx )) 00305 { 00306 track.addMatch( img2,point_matcher.queryIdx ); 00307 is_found=true; 00308 } 00309 else 00310 { 00311 if( track.containPoint( img2,point_matcher.queryIdx )) 00312 { 00313 track.addMatch( img1,point_matcher.trainIdx ); 00314 is_found=true; 00315 } 00316 } 00317 tracks_it++; 00318 } 00319 if( !is_found ) 00320 { 00321 //it's a new point match, create a new track: 00322 TrackOfPoints newTrack; 00323 newTrack.addMatch( img1,point_matcher.trainIdx ); 00324 newTrack.addMatch( img2,point_matcher.queryIdx ); 00325 tracks_.push_back( newTrack ); 00326 } 00327 00328 match_it++; 00329 } 00330 } 00331 00332 void SequenceAnalyzer::addTracks( std::vector< TrackOfPoints > &newTracks ) 00333 { 00334 00335 vector<TrackOfPoints>::iterator match_it = newTracks.begin( ), 00336 match_it_end = newTracks.end( ); 00337 00338 while ( match_it != match_it_end ) 00339 { 00340 tracks_.push_back( *match_it ); 00341 00342 match_it++; 00343 } 00344 } 00345 00346 void SequenceAnalyzer::showTracks( int timeBetweenImg ) 00347 { 00348 if( points_to_track_.size( ) == 0 ) 00349 return;//nothing to do... 00350 00351 unsigned int it=0,it1=0; 00352 unsigned int end_iter = points_to_track_.size( ) - 1 ; 00353 if( images_.size( ) - 1 < end_iter ) 00354 end_iter = images_.size( ) - 1; 00355 while ( it < end_iter ) 00356 { 00357 it1=it+1; 00358 while ( it1 < end_iter ) 00359 { 00360 vector<DMatch> matches_to_print; 00361 //add to matches_to_print only points of img it and it+1: 00362 00363 vector<TrackOfPoints>::iterator match_it = tracks_.begin( ); 00364 vector<TrackOfPoints>::iterator match_it_end = tracks_.end( ); 00365 00366 while ( match_it != match_it_end ) 00367 { 00368 if( match_it->containImage( it ) && 00369 match_it->containImage( it1 ) ) 00370 { 00371 matches_to_print.push_back( match_it->toDMatch( it,it1 )); 00372 } 00373 match_it++; 00374 } 00375 00376 if( matches_to_print.size()>0 ) 00377 { 00378 Mat firstImg=images_[ it ]; 00379 Mat outImg; 00380 00381 PointsMatcher::drawMatches( firstImg, points_to_track_[ it ]->getKeypoints( ), 00382 points_to_track_[ it1 ]->getKeypoints( ), 00383 matches_to_print, outImg, 00384 cv::Scalar::all( -1 ), cv::Scalar::all( -1 ), vector<char>( ), 00385 cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); 00386 00387 imshow( "showTracks",outImg ); 00388 cv::waitKey( timeBetweenImg ); 00389 } 00390 00391 it1++; 00392 } 00393 it++; 00394 } 00395 cvDestroyWindow( "showTracks" ); 00396 } 00397 00398 void SequenceAnalyzer::showTracks( int img_to_show, int timeBetweenImg ) 00399 { 00400 unsigned int it=0,it1=0; 00401 unsigned int end_iter = points_to_track_.size( ) - 1 ; 00402 if( images_.size( ) - 1 < end_iter ) 00403 end_iter = images_.size( ) - 1; 00404 vector< vector<DMatch> > matches_to_print; 00405 matches_to_print.assign( points_to_track_.size( ), vector<DMatch>() ); 00406 //add to matches_to_print only points of img it and it+1: 00407 00408 vector<TrackOfPoints>::iterator match_it = tracks_.begin( ); 00409 vector<TrackOfPoints>::iterator match_it_end = tracks_.end( ); 00410 unsigned int i = 0; 00411 while ( match_it != match_it_end ) 00412 { 00413 if( match_it->containImage( img_to_show ) ) 00414 { 00415 for(i = 0; i<match_it->images_indexes_.size(); i++) 00416 { 00417 if(match_it->images_indexes_[i] != img_to_show) 00418 { 00419 matches_to_print[ match_it->images_indexes_[i] ]. 00420 push_back( match_it->toDMatch( img_to_show, match_it->images_indexes_[i] )); 00421 } 00422 } 00423 } 00424 match_it++; 00425 } 00426 00427 for(i = 0; i<matches_to_print.size(); i++) 00428 { 00429 if( matches_to_print[i].size()>0 ) 00430 { 00431 Mat firstImg=images_[ it ]; 00432 Mat outImg; 00433 00434 PointsMatcher::drawMatches( firstImg, points_to_track_[ img_to_show ]->getKeypoints( ), 00435 points_to_track_[ i ]->getKeypoints( ), 00436 matches_to_print[i], outImg, 00437 cv::Scalar::all( -1 ), cv::Scalar::all( -1 ), vector<char>( ), 00438 cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); 00439 00440 imshow( "showTracks",outImg ); 00441 cv::waitKey( timeBetweenImg ); 00442 } 00443 } 00444 cvDestroyWindow( "showTracks" ); 00445 } 00446 00447 cv::Mat SequenceAnalyzer::showTracksBetween( unsigned int img1, unsigned int img2, 00448 cv::Mat img, bool should_print ) 00449 { 00450 CV_Assert( points_to_track_.size( ) != 0 ); 00451 CV_Assert( images_.size( ) > img1 && images_.size( ) > img2 ); 00452 CV_Assert( 0 <= img1 && 0 <= img2 ); 00453 00454 vector<DMatch> matches_to_print,matches_to_print1; 00455 //add to matches_to_print only points of img1 and img2: 00456 00457 vector<TrackOfPoints>::iterator match_it = tracks_.begin( ); 00458 vector<TrackOfPoints>::iterator match_it_end = tracks_.end( ); 00459 00460 while ( match_it != match_it_end ) 00461 { 00462 if( match_it->containImage( img1 ) && 00463 match_it->containImage( img2 ) ) 00464 { 00465 matches_to_print.push_back( match_it->toDMatch( img1,img2 )); 00466 matches_to_print1.push_back( match_it->toDMatch( img2,img1 )); 00467 } 00468 match_it++; 00469 } 00470 if( img.empty() ) 00471 img = images_[ img1 ]; 00472 Mat outImg,outImg1; 00473 PointsMatcher::drawMatches( img, points_to_track_[ img1 ]->getKeypoints( ), 00474 points_to_track_[ img2 ]->getKeypoints( ), 00475 matches_to_print, outImg, 00476 cv::Scalar::all( -1 ), cv::Scalar::all( -1 ), vector<char>( ), 00477 cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); 00478 if(should_print) 00479 imshow( "showTracks Img1-Img2",outImg ); 00480 00481 if(should_print) 00482 { 00483 PointsMatcher::drawMatches( images_[ img2 ], points_to_track_[ img2 ]->getKeypoints( ), 00484 points_to_track_[ img1 ]->getKeypoints( ), 00485 matches_to_print1, outImg1, 00486 cv::Scalar::all( -1 ), cv::Scalar::all( -1 ), vector<char>( ), 00487 cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); 00488 00489 imshow( "showTracks Img2-Img1",outImg1 ); 00490 cv::waitKey( 0 ); 00491 } 00492 00493 cvDestroyAllWindows(); 00494 return outImg; 00495 } 00496 00497 void SequenceAnalyzer::read( const cv::FileNode& node, SequenceAnalyzer& me ) 00498 { 00499 std::string myName=node.name( ); 00500 if( myName != "SequenceAnalyzer" ) 00501 { 00502 std::string error = "FileNode is not correct!\nExpected \"SequenceAnalyzer\", got "; 00503 error += node.name(); 00504 CV_Error( CV_StsError, error.c_str() ); 00505 } 00506 if( node.empty( ) || !node.isMap( ) ) 00507 CV_Error( CV_StsError, "SequenceAnalyzer FileNode is not correct!" ); 00508 00509 int nb_pictures = ( int ) node[ "nbPictures" ]; 00510 //initialisation of all empty vectors 00511 for( int i=0; i<nb_pictures; i++ ) 00512 { 00513 Ptr<PointsToTrack> ptt = Ptr<PointsToTrack>( new PointsToTrackWithImage( i, me.images_[i] )); 00514 me.points_to_track_.push_back( ptt ); 00515 00516 Ptr<PointsMatcher> p_m = Ptr<PointsMatcher>( new PointsMatcher( 00517 *me.match_algorithm_ ) ); 00518 p_m->add( ptt ); 00519 00520 me.matches_.push_back( p_m ); 00521 } 00522 00523 cv::FileNode node_TrackPoints = node[ "TrackPoints" ]; 00524 00525 //tracks are stored in the following form: 00526 //list of track where a track is stored like this: 00527 // nbPoints idImage1 point1 idImage2 point2 ... 00528 if( node_TrackPoints.empty( ) || !node_TrackPoints.isSeq( ) ) 00529 CV_Error( CV_StsError, "SequenceAnalyzer FileNode is not correct!" ); 00530 cv::FileNodeIterator it = node_TrackPoints.begin( ), 00531 it_end = node_TrackPoints.end( ); 00532 while( it != it_end ) 00533 { 00534 cv::FileNode it_track = ( *it )[ 0 ]; 00535 int nbPoints,track_consistance; 00536 it_track[ "nbPoints" ] >> nbPoints; 00537 it_track[ "track_consistance" ] >> track_consistance; 00538 bool has_3d_point = false; 00539 it_track[ "has_3d_position" ] >> has_3d_point; 00540 TrackOfPoints track; 00541 if( has_3d_point ) 00542 { 00543 cv::Vec3d point; 00544 point[ 0 ] = it_track[ "point3D_triangulated" ][ 0 ]; 00545 point[ 1 ] = it_track[ "point3D_triangulated" ][ 1 ]; 00546 point[ 2 ] = it_track[ "point3D_triangulated" ][ 2 ]; 00547 track.point3D = Ptr<cv::Vec3d>( new cv::Vec3d( point ) ); 00548 } 00549 int color; 00550 it_track[ "color" ] >> color; 00551 track.setColor( *((unsigned int*)&color) ); 00552 cv::FileNodeIterator itPoints = it_track[ "list_of_points" ].begin( ), 00553 itPoints_end = it_track[ "list_of_points" ].end( ); 00554 while( itPoints != itPoints_end ) 00555 { 00556 int idImage; 00557 cv::KeyPoint kpt; 00558 idImage = ( *itPoints )[ 0 ]; 00559 itPoints++; 00560 kpt.pt.x = ( *itPoints )[ 0 ]; 00561 kpt.pt.y = ( *itPoints )[ 1 ]; 00562 kpt.size = ( *itPoints )[ 2 ]; 00563 kpt.angle = ( *itPoints )[ 3 ]; 00564 kpt.response = ( *itPoints )[ 4 ]; 00565 kpt.octave = ( *itPoints )[ 5 ]; 00566 kpt.class_id = ( *itPoints )[ 6 ]; 00567 00568 unsigned int point_index = me.points_to_track_[ idImage ]-> 00569 addKeypoint( kpt ); 00570 track.addMatch( idImage,point_index ); 00571 00572 itPoints++; 00573 } 00574 track.track_consistance = track_consistance; 00575 me.tracks_.push_back( track ); 00576 it++; 00577 } 00578 } 00579 00580 void SequenceAnalyzer::write( cv::FileStorage& fs, const SequenceAnalyzer& me ) 00581 { 00582 vector<TrackOfPoints>::size_type key_size = me.tracks_.size( ); 00583 int idImage=-1, idPoint=-1; 00584 00585 fs << "SequenceAnalyzer" << "{"; 00586 fs << "nbPictures" << ( int )me.points_to_track_.size( ); 00587 fs << "nbPoints" << ( int )key_size; 00588 fs << "TrackPoints" << "["; 00589 for ( vector<TrackOfPoints>::size_type i=0; i < key_size; i++ ) 00590 { 00591 const TrackOfPoints &track = me.tracks_[ i ]; 00592 unsigned int nbPoints = track.getNbTrack( ); 00593 if( nbPoints > 0 ) 00594 { 00595 fs << "{" << "nbPoints" << ( int )nbPoints; 00596 fs << "track_consistance" << track.track_consistance; 00597 fs << "has_3d_position" << ( !track.point3D.empty( ) ); 00598 if( !track.point3D.empty( ) ) 00599 fs << "point3D_triangulated" << *(track.point3D); 00600 00601 unsigned int real_color = track.getColor(); 00602 int color = *((int*)&real_color); 00603 fs << "color" << color; 00604 00605 fs << "list_of_points" << "[:"; 00606 nbPoints = track.images_indexes_.size(); 00607 for ( unsigned int j = 0; j < nbPoints ; j++ ) 00608 { 00609 if( track.good_values[j] ) 00610 { 00611 idImage = track.images_indexes_[ j ]; 00612 idPoint = track.point_indexes_[ j ]; 00613 if( idImage>=0 && idPoint>=0 ) 00614 { 00615 fs << idImage; 00616 fs << "[:"; 00617 00618 const cv::KeyPoint kpt = me.points_to_track_[ idImage ]-> 00619 getKeypoints( )[ idPoint ]; 00620 cv::write( fs, kpt.pt.x ); 00621 cv::write( fs, kpt.pt.y ); 00622 cv::write( fs, kpt.size ); 00623 cv::write( fs, kpt.angle ); 00624 cv::write( fs, kpt.response ); 00625 cv::write( fs, kpt.octave ); 00626 cv::write( fs, kpt.class_id ); 00627 fs << "]" ; 00628 } 00629 } 00630 } 00631 fs << "]" << "}" ; 00632 } 00633 } 00634 fs << "]" << "}"; 00635 } 00636 00637 void SequenceAnalyzer::constructImagesGraph( ) 00638 { 00639 images_graph_.initStructure( points_to_track_.size( ) ); 00640 00641 //for each points: 00642 vector<TrackOfPoints>::size_type key_size = tracks_.size( ); 00643 vector<TrackOfPoints>::size_type i; 00644 00645 for ( i=0; i < key_size; i++ ) 00646 { 00647 TrackOfPoints &track = tracks_[ i ]; 00648 unsigned int nviews = track.images_indexes_.size( ); 00649 00650 for( unsigned int cpt=0;cpt<nviews;cpt++ ) 00651 { 00652 unsigned int imgSrc = track.images_indexes_[ cpt ]; 00653 for( unsigned int cpt1=cpt+1;cpt1<nviews;cpt1++ ) 00654 { 00655 images_graph_.addLink( imgSrc, track.images_indexes_[ cpt1 ] ); 00656 } 00657 } 00658 } 00659 } 00660 00661 std::vector< cv::Vec3d > SequenceAnalyzer::get3DStructure( ) 00662 { 00663 vector<cv::Vec3d> out_vector; 00664 vector<TrackOfPoints>::iterator itTrack=tracks_.begin( ); 00665 while ( itTrack != tracks_.end( ) ) 00666 { 00667 if( !itTrack->point3D.empty( ) ) 00668 out_vector.push_back( ( cv::Vec3d )( *itTrack ) ); 00669 itTrack++; 00670 } 00671 return out_vector; 00672 } 00673 00674 std::vector< unsigned int > SequenceAnalyzer::getColors( ) 00675 { 00676 vector<unsigned int> out_vector; 00677 vector<TrackOfPoints>::iterator itTrack=tracks_.begin( ); 00678 while ( itTrack != tracks_.end( ) ) 00679 { 00680 if( !itTrack->point3D.empty( ) ) 00681 out_vector.push_back( itTrack->getColor() ); 00682 itTrack++; 00683 } 00684 return out_vector; 00685 } 00686 00687 void SequenceAnalyzer::showPointsOnImage(unsigned int i, 00688 const std::vector<cv::Vec2d>& pixelProjection) 00689 { 00690 CV_Assert( i < images_.size() ); 00691 //convert Vec2D into Keypoints: 00692 std::vector<KeyPoint> keypoints; 00693 for(size_t cpt = 0; cpt<pixelProjection.size(); ++cpt) 00694 { 00695 keypoints.push_back( cv::KeyPoint( (float)pixelProjection[ cpt ][0], 00696 (float)pixelProjection[ cpt ][1], 1.0 ) ); 00697 } 00698 cv::Mat outImg; 00699 cv::drawKeypoints( images_[i], keypoints, outImg ); 00700 cv::imshow( "Keypoints", outImg ); 00701 cv::waitKey( 0 ); 00702 cv::destroyWindow( "Keypoints" ); 00703 } 00704 00705 std::vector< cv::DMatch > SequenceAnalyzer::simple_matching( 00706 cv::Ptr<PointsMatcher> point_matcher, 00707 cv::Ptr<PointsMatcher> point_matcher1, 00708 unsigned int mininum_points_matches) 00709 { 00710 vector< cv::DMatch > matches_i_j; 00711 point_matcher->crossMatch( point_matcher1, matches_i_j ); 00712 00713 //First compute points matches: 00714 unsigned int size_match=matches_i_j.size( ); 00715 vector<cv::Point2f> srcP; 00716 vector<cv::Point2f> destP; 00717 vector<uchar> status; 00718 00719 //vector<KeyPoint> points1 = point_matcher->; 00720 for( size_t cpt = 0; cpt < size_match; ++cpt ){ 00721 const cv::KeyPoint &key1 = point_matcher1->getKeypoint( 00722 matches_i_j[ cpt ].queryIdx ); 00723 const cv::KeyPoint &key2 = point_matcher->getKeypoint( 00724 matches_i_j[ cpt ].trainIdx ); 00725 srcP.push_back( cv::Point2f( key1.pt.x,key1.pt.y ) ); 00726 destP.push_back( cv::Point2f( key2.pt.x,key2.pt.y ) ); 00727 status.push_back( 1 ); 00728 } 00729 00730 //free some memory: 00731 point_matcher->clear(); 00732 point_matcher1->clear(); 00733 00734 if( srcP.size()< mininum_points_matches ) 00735 return matches_i_j; 00736 cv::Mat fundam = cv::findFundamentalMat( srcP, destP, status, cv::FM_RANSAC, 1 ); 00737 00738 unsigned int nbErrors = 0, nb_iter=0; 00739 //refine the mathing : 00740 size_match = status.size( ); 00741 for( size_t cpt = 0; cpt < size_match; ++cpt ){ 00742 if( status[ cpt ] == 0 ) 00743 { 00744 size_match--; 00745 status[ cpt ] = status[ size_match ]; 00746 status.pop_back( ); 00747 srcP[ cpt ] = srcP[ size_match ]; 00748 srcP.pop_back( ); 00749 destP[ cpt ] = destP[ size_match ]; 00750 destP.pop_back( ); 00751 matches_i_j[ cpt ] = matches_i_j[ size_match ]; 00752 matches_i_j.pop_back( ); 00753 cpt--; 00754 ++nbErrors; 00755 } 00756 } 00757 00758 if( srcP.size()< mininum_points_matches ) 00759 return matches_i_j; 00760 00761 //refine the mathing: 00762 fundam = cv::findFundamentalMat( srcP, destP, status, cv::FM_LMEDS ); 00763 00764 size_match = status.size( ); 00765 for( size_t cpt = 0; cpt < size_match; ++cpt ){ 00766 if( status[ cpt ] == 0 ) 00767 { 00768 size_match--; 00769 status[ cpt ] = status[ size_match ]; 00770 status.pop_back( ); 00771 srcP[ cpt ] = srcP[ size_match ]; 00772 srcP.pop_back( ); 00773 destP[ cpt ] = destP[ size_match ]; 00774 destP.pop_back( ); 00775 matches_i_j[ cpt ] = matches_i_j[ size_match ]; 00776 matches_i_j.pop_back( ); 00777 cpt--; 00778 ++nbErrors; 00779 } 00780 } 00781 return matches_i_j; 00782 }; 00783 00784 00785 void SequenceAnalyzer::removePointsWithoutProjection( 00786 SequenceAnalyzer &motion_estim ) 00787 { 00788 vector<TrackOfPoints>::size_type key_size = motion_estim.tracks_.size( ); 00789 int idImage=-1, idPoint=-1; 00790 vector< Ptr<PointsToTrack> > new_ptt; 00791 //initialisation of empty vector 00792 int before = 0, after = 0; 00793 for( size_t i=0; i<motion_estim.points_to_track_.size(); i++ ) 00794 { 00795 Ptr<PointsToTrack> ptt = Ptr<PointsToTrack>( 00796 new PointsToTrackWithImage( i, motion_estim.images_[i], 00797 motion_estim.feature_detector_, motion_estim.descriptor_extractor_ )); 00798 new_ptt.push_back( ptt ); 00799 before += motion_estim.points_to_track_[i]->getKeypoints().size(); 00800 } 00801 for ( size_t i=0; i < key_size; i++ ) 00802 { 00803 TrackOfPoints &track = motion_estim.tracks_[ i ]; 00804 unsigned int nbPoints = track.getNbTrack( ); 00805 if( nbPoints > 0 && !track.point3D.empty( ) ) 00806 { 00807 nbPoints = track.images_indexes_.size(); 00808 for ( unsigned int j = 0; j < nbPoints ; j++ ) 00809 { 00810 if( track.good_values[j] ) 00811 { 00812 idImage = track.images_indexes_[ j ]; 00813 idPoint = track.point_indexes_[ j ]; 00814 if( idImage>=0 && idPoint>=0 ) 00815 { 00816 00817 const cv::KeyPoint kpt = 00818 motion_estim.points_to_track_[ idImage ]-> 00819 getKeypoints( )[ idPoint ]; 00820 track.point_indexes_[ j ] = new_ptt[ idImage ]->addKeypoint( kpt ); 00821 } 00822 } 00823 } 00824 } 00825 } 00826 motion_estim.points_to_track_ = new_ptt; 00827 for( size_t i=0; i<motion_estim.points_to_track_.size(); i++ ) 00828 { 00829 Ptr<PointsToTrack> ptt = Ptr<PointsToTrack>( 00830 new PointsToTrackWithImage( i, motion_estim.images_[i] )); 00831 new_ptt.push_back( ptt ); 00832 after += motion_estim.points_to_track_[i]->getKeypoints().size(); 00833 } 00834 std::cout<<" before "<<before<<", after "<<after<<std::endl; 00835 } 00836 }