GSoC2011SfM
0.1
Google Summer of Code 2011: Structure from motion
|
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 }