GSoC2011SfM  0.1
Google Summer of Code 2011: Structure from motion
D:/Travail/These/Determination caracteristiques camera/GSoC/SfM/src/PointsToTrack.cpp
00001 #include "PointsToTrack.h"
00002 #include "TracksOfPoints.h"
00003 
00004 using cv::Mat;
00005 using cv::Scalar;
00006 using cv::KeyPoint;
00007 using cv::Point;
00008 using std::vector;
00009 using cv::line;
00010 using cv::circle;
00011 
00012 namespace OpencvSfM{
00013   int PointsToTrack::glob_number_images_ = 0;
00014 
00015   PointsToTrack::PointsToTrack( int corresponding_image,
00016     std::vector<KeyPoint> keypoints, Mat descriptors )
00017     :keypoints_( keypoints ),descriptors_( descriptors )
00018   {
00019     if ( corresponding_image>=0 )
00020       corresponding_image_ = corresponding_image;
00021     else
00022       corresponding_image_ = PointsToTrack::glob_number_images_;
00023 
00024     PointsToTrack::glob_number_images_++;
00025     nb_workers_ = 0;
00026     INIT_MUTEX(worker_exclusion);
00027   }
00028 
00029   void PointsToTrack::free_descriptors( bool force )
00030   {
00031     P_MUTEX(worker_exclusion);
00032     if(nb_workers_<=1 || force)
00033     {//if equal to 0, descriptors_ is already empty...
00034       nb_workers_ = 0;
00035       descriptors_.release( );
00036     }
00037     else
00038       nb_workers_--;
00039     V_MUTEX(worker_exclusion);
00040   }
00041 
00042   PointsToTrack::~PointsToTrack( void )
00043   {
00044     keypoints_.clear( );
00045     descriptors_.release( );
00046     PointsToTrack::glob_number_images_--;
00047   }
00048 
00049   int PointsToTrack::computeKeypointsAndDesc( bool forcing_recalculation )
00050   {
00051     P_MUTEX(worker_exclusion);
00052     bool need_descriptors = true;
00053     bool need_keypoints = true;
00054     if( !forcing_recalculation )
00055     {
00056       need_keypoints = keypoints_.empty( );
00057       need_descriptors = need_keypoints || descriptors_.empty( );
00058       if( need_keypoints )
00059         impl_computeKeypoints_();
00060     }
00061     else
00062       impl_computeKeypoints_();
00063 
00064     if( need_keypoints )//as points have been computed, refilter them:
00065       impl_filterByDistance_( 3 );
00066 
00067     nb_workers_++;
00068 
00069     if( need_descriptors )
00070       impl_computeDescriptors_();
00071     V_MUTEX(worker_exclusion);
00072     return keypoints_.size( );
00073   }
00074 
00075   void PointsToTrack::impl_filterByDistance_( double dist_min )
00076   {
00077     return;
00078     bool discard_data = false;
00079     size_t nb_points = keypoints_.size();
00080     for(size_t i = 0; i<nb_points ; ++i)
00081     {
00082       const cv::KeyPoint& kp = keypoints_[i];
00083       for(size_t j = i+1; j<nb_points ; ++j)
00084       {
00085         const cv::KeyPoint& kp1 = keypoints_[j];
00086         float dist = sqrt( (kp.pt.x - kp1.pt.x)*(kp.pt.x - kp1.pt.x)
00087           + (kp.pt.y - kp1.pt.y) * (kp.pt.y - kp1.pt.y) );
00088         if( dist<dist_min )
00089         {
00090           //we have to remove this point!
00091           discard_data = true;
00092           nb_points--;
00093           keypoints_[ j ] = keypoints_[ nb_points ];
00094           j--;
00095           keypoints_.pop_back();
00096         }
00097       }
00098     }
00099     if( discard_data )
00100     {
00101       if( nb_workers_>=1 && descriptors_.empty( ) )
00102         impl_computeDescriptors_();//recompute the descriptors...
00103     }
00104   }
00105   void PointsToTrack::filterByDistance( double dist_min )
00106   {
00107     P_MUTEX(worker_exclusion);
00108     impl_filterByDistance_( dist_min );
00109     V_MUTEX(worker_exclusion);
00110   }
00111 
00112   int PointsToTrack::computeKeypoints( )
00113   {
00114     P_MUTEX(worker_exclusion);
00115     impl_computeKeypoints_();
00116     V_MUTEX(worker_exclusion);
00117     filterByDistance( 3 );
00118     return keypoints_.size( );
00119   }
00120 
00121   void PointsToTrack::computeDescriptors( )
00122   {
00123     P_MUTEX(worker_exclusion);
00124     nb_workers_++;
00125     impl_computeDescriptors_();
00126     V_MUTEX(worker_exclusion);
00127   }
00128 
00129   void PointsToTrack::addKeypoints( std::vector<cv::KeyPoint> keypoints,cv::Mat descriptors/*=cv::Mat( )*/,bool computeMissingDescriptor/*=false*/ )
00130   {
00131     if( keypoints.size()==0 )
00132       return;//nothing to do...
00133     P_MUTEX(worker_exclusion);
00134     //add the keypoints to the end of our points vector:
00135     this->keypoints_.insert( this->keypoints_.end( ),keypoints.begin( ),keypoints.end( ) );
00136 
00137     V_MUTEX(worker_exclusion);
00138     filterByDistance( 3 );
00139 
00140     if( !computeMissingDescriptor )
00141     {
00142       if( !descriptors_.empty( ) )
00143       {
00144         Mat newDescriptors( this->keypoints_.size( ), this->descriptors_.cols,
00145           this->descriptors_.type( ) );
00146         newDescriptors(
00147           cv::Rect( 0, 0, this->descriptors_.cols,this->descriptors_.rows ) ) =
00148           this->descriptors_;
00149 
00150         newDescriptors( cv::Rect( 0, this->descriptors_.rows,
00151           this->descriptors_.cols,descriptors.rows ) ) = descriptors;
00152 
00153         this->descriptors_=newDescriptors;
00154       }
00155     }
00156     else
00157     {
00158       this->computeDescriptors( );
00159     }
00160   }
00161   void PointsToTrack::printPointsOnImage( const Mat &image, Mat& outImg, const Scalar& color/*=Scalar::all( -1 )*/, int flags/*=DrawMatchesFlags::DEFAULT*/ ) const
00162   {
00163     if( outImg.empty( ) )
00164       outImg=image.clone( );
00165     cv::drawKeypoints( image, keypoints_, outImg, color, flags );
00166   }
00167   void PointsToTrack::read( const cv::FileNode& node, PointsToTrack& points )
00168   {
00169     std::string myName=node.name( );
00170     if( myName != "PointsToTrack" )
00171       return;//this node is not for us...
00172     cv::FileNode node_keypoints = node[ "keypoints" ];
00173     if( node_keypoints.empty( ) )
00174       CV_Error( CV_StsError, "PointsToTrack FileNode is not correct!" );
00175 
00176     cv::FileNodeIterator it = node_keypoints.begin( ), it_end = node_keypoints.end( );
00177     while( it != it_end )
00178     {
00179       KeyPoint kpt;
00180       it >> kpt.pt.x >> kpt.pt.y >> kpt.size >> kpt.angle >> kpt.response >> kpt.octave >> kpt.class_id;
00181       points.keypoints_.push_back( kpt );
00182       //it++ is not needed as the >> operator increment automatically it!
00183     }
00184 
00185     cv::FileNode node_descriptors = node[ "descriptors" ];
00186     if( node_descriptors.empty( ) )
00187       CV_Error( CV_StsError, "PointsToTrack FileNode is not correct!" );
00188     node_descriptors >> points.descriptors_;
00189 
00190     CV_Assert( points.descriptors_.rows == points.keypoints_.size() );
00191 
00192     //as the loaded PointsToTrack can't recompute the descriptors_, set the nbworkers
00193     //to a high value (this will disable free_descriptors to release descriptor ;)
00194     points.nb_workers_ = 999999;
00195 
00196     cv::FileNode node_colors = node[ "colors" ];
00197     if( !node_colors.empty( ) )
00198     {
00199       cv::FileNodeIterator it = node_colors.begin( ), it_end = node_colors.end( );
00200       while( it != it_end )
00201       {
00202         int color;
00203         it >> color;
00204         points.RGB_values_.push_back( color );
00205         //it++ is not needed as the >> operator increment automatically it!
00206       }
00207     }
00208   };
00209   void PointsToTrack::write( cv::FileStorage& fs, const PointsToTrack& keypoints )
00210   {
00211     PointsToTrack ppt = keypoints;
00212     //as we want to save them, compute keypoints and descriptor:
00213     ppt.computeKeypointsAndDesc();
00214 
00215     fs << "{" << "PointsToTrack" << "{";
00216     cv::write( fs, "keypoints", ppt.keypoints_ );
00217 
00218     fs << "descriptors" << ppt.descriptors_;
00219     fs << "colors" <<"[:";
00220     unsigned int size_max = ppt.RGB_values_.size( );
00221     for(unsigned int i=0; i<size_max; ++i )
00222     {
00223       fs << (int)(ppt.RGB_values_[i] & 0x00FFFFFF);
00224     }
00225     fs << "]" << "}" << "}";
00226   }
00227 
00228   void PointsToTrack::getKeyMatches( const std::vector<TrackOfPoints>& matches,
00229     int otherImage, std::vector<cv::Point2f>& pointsVals ) const
00230   {
00231     //for each points:
00232     vector<TrackOfPoints>::size_type key_size = matches.size( );
00233     vector<TrackOfPoints>::size_type i;
00234 
00235     for ( i=0; i < key_size; i++ )
00236     {
00237       const TrackOfPoints &track = matches[ i ];
00238 
00239       if( track.containImage( corresponding_image_ ) &&
00240         track.containImage( otherImage ) )
00241       {
00242         const KeyPoint &kp = keypoints_[ track.getPointIndex( corresponding_image_ ) ];
00243         pointsVals.push_back( cv::Point2f( kp.pt.x,kp.pt.y ));
00244       }
00245     }
00246   }
00247 
00248   size_t PointsToTrack::getClosestKeypoint( cv::Point2f point )
00249   {
00250     P_MUTEX(worker_exclusion);
00251     size_t nb_points = keypoints_.size(),
00252       idx_min = 0;
00253     float dist_min = 1e10;
00254     for(size_t i = 0; i<nb_points ; ++i)
00255     {
00256       const cv::KeyPoint& kp = keypoints_[i];
00257       float dist = sqrt( (point.x - kp.pt.x)*(point.x - kp.pt.x)
00258         + (point.y - kp.pt.y) * (point.y - kp.pt.y) );
00259       if( dist<dist_min )
00260       {
00261         dist_min = dist;
00262         idx_min = i;
00263       }
00264     }
00265     V_MUTEX(worker_exclusion);
00266     return idx_min;
00267   };
00268 }
 All Classes Functions Variables