robustmatcher.hpp
Go to the documentation of this file.
00001 
00041 #ifndef __ROBUSTMATCHER_H__
00042 #define __ROBUSTMATCHER_H__
00043 
00044 #include <opencv2/imgproc/imgproc.hpp>
00045 #include <opencv2/highgui/highgui.hpp>
00046 #include <opencv2/features2d/features2d.hpp>
00047 #include <opencv2/calib3d/calib3d.hpp>
00048 
00053 class RobustMatcher
00054 {
00055 public:
00058     RobustMatcher(void):
00059         matcher_(cv::NORM_HAMMING)
00060         {       
00061                 // Variable initialization
00062         ratio_ = 0.65f;
00063         refineF_ = false;
00064         confidence_ = 0.99;
00065         distance_ = 3.0;
00066         }
00067         
00079     cv::Mat match(std::vector<cv::KeyPoint>& keypoints1, cv::Mat &descriptors1,
00080                   std::vector<cv::KeyPoint>& keypoints2, cv::Mat &descriptors2,
00081                   std::vector<cv::DMatch>& matches, bool doRansacTest = true,
00082                   bool doRatioTest = false, bool refineF = false)
00083         {
00084                 cv::Mat F;
00085                 
00086         // Matching from image 1 to image 2 based on k nearest neighbours (k=2)
00087         std::vector<std::vector<cv::DMatch> > matches12;
00088         matcher_.knnMatch(descriptors1, descriptors2, matches12, 2);
00089                 
00090         // Matching from image 2 to image 1 based on k nearest neighbours (k=2)
00091         std::vector<std::vector<cv::DMatch> > matches21;
00092         matcher_.knnMatch(descriptors2, descriptors1, matches21, 2);
00093                 
00094         // Remove matches for which NN ratio > threshold
00095         if(doRatioTest)
00096                 {
00097             ratioTest(matches12);
00098             ratioTest(matches21);
00099                 }
00100                 
00101         // Remove non-symmetrical matches
00102                 std::vector<cv::DMatch> symMatches;
00103         symmetryTest(matches12, matches21, symMatches);
00104                 
00105         // Validate matches using RANSAC
00106         if(doRansacTest)
00107                 {
00108             refineF_ = refineF;
00109                         F = ransacTest(symMatches, keypoints1, keypoints2, matches);
00110                 }
00111                 else
00112                         matches = symMatches;
00113                 
00114                 return F;
00115         }
00116 
00122         int ratioTest(std::vector<std::vector<cv::DMatch> >     &matches) 
00123         {
00124                 int removed=0;
00125         for(std::vector<std::vector<cv::DMatch> >::iterator it = matches.begin(); it!= matches.end(); ++it)
00126                 {
00127             // if 2 nearest neighbors have been identified
00128             if(it->size() > 1)
00129                         {
00130                                 // check distance ratio
00131                 if((*it)[0].distance/(*it)[1].distance > ratio_)
00132                                 {
00133                     it->clear(); // remove match
00134                                         removed++;
00135                                 }
00136                         } 
00137                         else 
00138             {   // does not have 2 neighbors
00139                 it->clear(); // remove match
00140                                 removed++;
00141                         }
00142                 }
00143                 return removed;
00144         }
00145 
00151     void symmetryTest(const std::vector<std::vector<cv::DMatch> >& matches1,
00152                       const std::vector<std::vector<cv::DMatch> >& matches2,
00153                       std::vector<cv::DMatch>& symMatches)
00154         {
00155                 // for all matches image 1 -> image 2
00156         for(std::vector<std::vector<cv::DMatch> >::const_iterator it1= matches1.begin(); it1!= matches1.end(); ++it1)
00157                 {
00158                         // ignore deleted matches
00159             if(it1->size() < 2)
00160                                 continue;
00161                                 
00162                         // for all matches image 2 -> image 1
00163             for(std::vector<std::vector<cv::DMatch> >::const_iterator it2= matches2.begin(); it2!= matches2.end(); ++it2)
00164                         {
00165                                 // ignore deleted matches
00166                 if(it2->size() < 2)
00167                                         continue;
00168                                 // Match symmetry test
00169                 if((*it1)[0].queryIdx ==(*it2)[0].trainIdx &&
00170                         (*it2)[0].queryIdx == (*it1)[0].trainIdx)
00171                                 {
00172                                         // add symmetrical match
00173                     symMatches.push_back(cv::DMatch((*it1)[0].queryIdx, (*it1)[0].trainIdx, (*it1)[0].distance));
00174                                         break; // next match in image 1 -> image 2
00175                                 }
00176                         }
00177                 }
00178         }
00179         
00187     cv::Mat ransacTest(const std::vector<cv::DMatch>& matches,
00188                        const std::vector<cv::KeyPoint>& keypoints1,
00189                        const std::vector<cv::KeyPoint>& keypoints2,
00190                        std::vector<cv::DMatch>& outMatches)
00191         {
00192                 cv::Mat nullMat;
00193                 
00194         // Convert keypoints into Point2f
00195                 std::vector<cv::Point2f> points1, points2;              
00196         for(std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it)
00197                 {
00198                         // Get the position of left keypoints
00199             float x = keypoints1[it->queryIdx].pt.x;
00200             float y = keypoints1[it->queryIdx].pt.y;
00201                         points1.push_back(cv::Point2f(x,y));
00202 
00203                         // Get the position of right keypoints
00204             x = keypoints2[it->trainIdx].pt.x;
00205             y = keypoints2[it->trainIdx].pt.y;
00206                         points2.push_back(cv::Point2f(x,y));
00207                 }
00208                 
00209                 // Compute F matrix using RANSAC
00210                 if(points1.size() < 10)
00211                         return nullMat;
00212                 std::vector<uchar> inliers(points1.size(),0);
00213         cv::Mat fundamental= cv::findFundamentalMat(cv::Mat(points1),cv::Mat(points2), inliers,
00214                                                     CV_FM_RANSAC, distance_, confidence_);
00215                 
00216         // Extract the surviving (inliers) matches
00217         std::vector<uchar>::const_iterator itIn = inliers.begin();
00218         std::vector<cv::DMatch>::const_iterator itM = matches.begin();
00219                 
00220                 // for all matches
00221         for(; itIn!= inliers.end(); ++itIn, ++itM)
00222                 {
00223             if(*itIn)
00224                         { // it is a valid match
00225                                 outMatches.push_back(*itM);
00226                         }
00227                 }
00228                 
00229         if (refineF_)
00230                 {
00231             // The F matrix will be recomputed with all accepted matches
00232             // Convert surviving keypoints into Point2f for final F computation
00233                         points1.clear();
00234                         points2.clear();
00235             for(std::vector<cv::DMatch>::const_iterator it = outMatches.begin(); it!= outMatches.end(); ++it)
00236                         {
00237                                 // Get the position of left keypoints
00238                 float x = keypoints1[it->queryIdx].pt.x;
00239                 float y = keypoints1[it->queryIdx].pt.y;
00240                                 points1.push_back(cv::Point2f(x,y));
00241 
00242                                 // Get the position of right keypoints
00243                 x = keypoints2[it->trainIdx].pt.x;
00244                 y = keypoints2[it->trainIdx].pt.y;
00245                                 points2.push_back(cv::Point2f(x,y));
00246                         }
00247 
00248                         // Compute 8-point F from all accepted matches
00249                         if(points1.size() < 9)
00250                                 return nullMat;
00251             fundamental= cv::findFundamentalMat(cv::Mat(points1),cv::Mat(points2), CV_FM_8POINT);
00252                 }
00253                 
00254         return fundamental;
00255         }
00256 
00257 private:
00258 
00259     float ratio_;           
00260     bool refineF_;          
00261     double distance_;       
00262     double confidence_;     
00263     cv::BFMatcher matcher_; 
00265 };
00266 
00267 #endif


viodom
Author(s): Fernando Caballero , Francisco J. Perez Grau
autogenerated on Thu Jun 6 2019 20:17:02