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
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
00087 std::vector<std::vector<cv::DMatch> > matches12;
00088 matcher_.knnMatch(descriptors1, descriptors2, matches12, 2);
00089
00090
00091 std::vector<std::vector<cv::DMatch> > matches21;
00092 matcher_.knnMatch(descriptors2, descriptors1, matches21, 2);
00093
00094
00095 if(doRatioTest)
00096 {
00097 ratioTest(matches12);
00098 ratioTest(matches21);
00099 }
00100
00101
00102 std::vector<cv::DMatch> symMatches;
00103 symmetryTest(matches12, matches21, symMatches);
00104
00105
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
00128 if(it->size() > 1)
00129 {
00130
00131 if((*it)[0].distance/(*it)[1].distance > ratio_)
00132 {
00133 it->clear();
00134 removed++;
00135 }
00136 }
00137 else
00138 {
00139 it->clear();
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
00156 for(std::vector<std::vector<cv::DMatch> >::const_iterator it1= matches1.begin(); it1!= matches1.end(); ++it1)
00157 {
00158
00159 if(it1->size() < 2)
00160 continue;
00161
00162
00163 for(std::vector<std::vector<cv::DMatch> >::const_iterator it2= matches2.begin(); it2!= matches2.end(); ++it2)
00164 {
00165
00166 if(it2->size() < 2)
00167 continue;
00168
00169 if((*it1)[0].queryIdx ==(*it2)[0].trainIdx &&
00170 (*it2)[0].queryIdx == (*it1)[0].trainIdx)
00171 {
00172
00173 symMatches.push_back(cv::DMatch((*it1)[0].queryIdx, (*it1)[0].trainIdx, (*it1)[0].distance));
00174 break;
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
00195 std::vector<cv::Point2f> points1, points2;
00196 for(std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it)
00197 {
00198
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
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
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
00217 std::vector<uchar>::const_iterator itIn = inliers.begin();
00218 std::vector<cv::DMatch>::const_iterator itM = matches.begin();
00219
00220
00221 for(; itIn!= inliers.end(); ++itIn, ++itM)
00222 {
00223 if(*itIn)
00224 {
00225 outMatches.push_back(*itM);
00226 }
00227 }
00228
00229 if (refineF_)
00230 {
00231
00232
00233 points1.clear();
00234 points2.clear();
00235 for(std::vector<cv::DMatch>::const_iterator it = outMatches.begin(); it!= outMatches.end(); ++it)
00236 {
00237
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
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
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