opencv2鲁棒匹配robust matching

opencv2随书自带的代码,如果直接有会报错,头文件部分需要加些东西才行。

robustmatch.cpp:



#include <iostream>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include<opencv2/nonfree/nonfree.hpp>
#include<opencv2\legacy\legacy.hpp> 
#include "matcher.h"


using namespace std;
using namespace cv;
int main()
{
// Read input images,读入图像
cv::Mat image1= cv::imread("canal1.jpg",0);
cv::Mat image2= cv::imread("canal2.jpg",0);
if (!image1.data || !image2.data)
return 0; 


    // Display the images显示图像
cv::namedWindow("Right Image");
cv::imshow("Right Image",image1);
cv::namedWindow("Left Image");
cv::imshow("Left Image",image2);


// Prepare the matcher准备匹配器
RobustMatcher rmatcher;
rmatcher.setConfidenceLevel(0.98);
rmatcher.setMinDistanceToEpipolar(1.0);
rmatcher.setRatio(0.65f);
cv::Ptr<cv::FeatureDetector> pfd= new cv::SurfFeatureDetector(10); 
rmatcher.setFeatureDetector(pfd);


// Match the two images匹配两张图像
std::vector<cv::DMatch> matches;
std::vector<cv::KeyPoint> keypoints1, keypoints2;
cv::Mat fundemental= rmatcher.match(image1,image2,matches, keypoints1, keypoints2);


// draw the matches画匹配结果
cv::Mat imageMatches;
cv::drawMatches(image1,keypoints1,  // 1st image and its keypoints第一张图片及其关键点
           image2,keypoints2,  // 2nd image and its keypoints第二张图片及其关键点
matches, // the matches匹配的结果
imageMatches, // the image produced产生的图像
cv::Scalar(255,255,255)); // color of the lines线的颜色
cv::namedWindow("Matches");
cv::imshow("Matches",imageMatches);

// Convert keypoints into Point2f 将关键点转换成point2f
std::vector<cv::Point2f> points1, points2;

for (std::vector<cv::DMatch>::const_iterator it= matches.begin();
it!= matches.end(); ++it) {


// Get the position of left keypoints得到左图像的关键点
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
cv::circle(image1,cv::Point(x,y),3,cv::Scalar(255,255,255),3);
// Get the position of right keypoints得到右图像的关键点
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
cv::circle(image2,cv::Point(x,y),3,cv::Scalar(255,255,255),3);
points2.push_back(cv::Point2f(x,y));
}

// Draw the epipolar lines画极线
std::vector<cv::Vec3f> lines1; 
cv::computeCorrespondEpilines(cv::Mat(points1),1,fundemental,lines1);

for (vector<cv::Vec3f>::const_iterator it= lines1.begin();
it!=lines1.end(); ++it) {


cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]),
            cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]),
cv::Scalar(255,255,255));
}


std::vector<cv::Vec3f> lines2; 
cv::computeCorrespondEpilines(cv::Mat(points2),2,fundemental,lines2);

for (vector<cv::Vec3f>::const_iterator it= lines2.begin();
    it!=lines2.end(); ++it) {


cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]),
            cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]),
cv::Scalar(255,255,255));
}


    // Display the images with epipolar lines显示有极线的图像
cv::namedWindow("Right Image Epilines (RANSAC)");
cv::imshow("Right Image Epilines (RANSAC)",image1);
cv::namedWindow("Left Image Epilines (RANSAC)");
cv::imshow("Left Image Epilines (RANSAC)",image2);


cv::waitKey();
return 0;

}

matcher.h

#if !defined MATCHER
#define MATCHER


#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>


class RobustMatcher {


  private:


 // pointer to the feature point detector object特征点检测对象的指针
 cv::Ptr<cv::FeatureDetector> detector;
 // pointer to the feature descriptor extractor object特征描述符提取器对象的指针
 cv::Ptr<cv::DescriptorExtractor> extractor;
 float ratio; // max ratio between 1st and 2nd NN
 bool refineF; // if true will refine the F matrix
 double distance; // min distance to epipolar
 double confidence; // confidence level (probability)


  public:


 RobustMatcher() : ratio(0.65f), refineF(true), confidence(0.99), distance(3.0) { 


 // SURF is the default feature  SURF是默认的算法
 detector= new cv::SurfFeatureDetector();
 extractor= new cv::SurfDescriptorExtractor();
 }


 // Set the feature detector设置特征检测器
 void setFeatureDetector(cv::Ptr<cv::FeatureDetector>& detect) {


 detector= detect;
 }


 // Set descriptor extractor设置描述符提取器
 void setDescriptorExtractor(cv::Ptr<cv::DescriptorExtractor>& desc) {


 extractor= desc;
 }


 // Set the minimum distance to epipolar in RANSAC设置最小距离RANSAC核线
 void setMinDistanceToEpipolar(double d) {


 distance= d;
 }


 // Set confidence level in RANSAC设置RANSAC信心水平
 void setConfidenceLevel(double c) {


 confidence= c;
 }


 // Set the NN ratio设置NN比
 void setRatio(float r) {


 ratio= r;
 }


 // if you want the F matrix to be recalculated如果你想要重新计算F矩阵
 void refineFundamental(bool flag) {


 refineF= flag;
 }


 // Clear matches for which NN ratio is bigger than threshold清除NN比大于阈值的匹配
 // return the number of removed points 返回移除的点的数目
 // (corresponding entries being cleared, i.e. size will be 0)
 int ratioTest(std::vector<std::vector<cv::DMatch>>& matches) {


int removed=0;


        // for all matches对于所有的匹配
for (std::vector<std::vector<cv::DMatch>>::iterator matchIterator= matches.begin();
matchIterator!= matches.end(); ++matchIterator) {


// if 2 NN has been identified如果2NN已经被确认
if (matchIterator->size() > 1) {


// check distance ratio检查距离比
if ((*matchIterator)[0].distance/(*matchIterator)[1].distance > ratio) {


matchIterator->clear(); // remove match清除匹配
removed++;
}


} else { // does not have 2 neighbours//没有两个邻居


matchIterator->clear(); // remove match清除匹配
removed++;
}
}


return removed;
 }


 // Insert symmetrical matches in symMatches vector插入对称匹配symMatches向量
 void symmetryTest(const std::vector<std::vector<cv::DMatch>>& matches1,
               const std::vector<std::vector<cv::DMatch>>& matches2,
   std::vector<cv::DMatch>& symMatches) {

// for all matches image 1 -> image 2    对于所有图1到图2的匹配
for (std::vector<std::vector<cv::DMatch>>::const_iterator matchIterator1= matches1.begin();
matchIterator1!= matches1.end(); ++matchIterator1) {


if (matchIterator1->size() < 2) // ignore deleted matches 
continue;


// for all matches image 2 -> image 1   对于所有图2到图1的匹配
for (std::vector<std::vector<cv::DMatch>>::const_iterator matchIterator2= matches2.begin();
matchIterator2!= matches2.end(); ++matchIterator2) {


if (matchIterator2->size() < 2) // ignore deleted matches 
continue;


// Match symmetry test  对称性匹配测试
if ((*matchIterator1)[0].queryIdx == (*matchIterator2)[0].trainIdx  && 
(*matchIterator2)[0].queryIdx == (*matchIterator1)[0].trainIdx) {


// add symmetrical match添加对称匹配
symMatches.push_back(cv::DMatch((*matchIterator1)[0].queryIdx,
     (*matchIterator1)[0].trainIdx,
   (*matchIterator1)[0].distance));
break; // next match in image 1 -> image 2
}
}
}
 }


 // Identify good matches using RANSAC确定好使用RANSAC匹配
 // Return fundemental matrix返回基本矩阵
 cv::Mat ransacTest(const std::vector<cv::DMatch>& matches,
                const std::vector<cv::KeyPoint>& keypoints1, 
const std::vector<cv::KeyPoint>& keypoints2,
    std::vector<cv::DMatch>& outMatches) {


// Convert keypoints into Point2f  关键点转换成Point2f
std::vector<cv::Point2f> points1, points2;
for (std::vector<cv::DMatch>::const_iterator it= matches.begin();
it!= matches.end(); ++it) {


// Get the position of left keypoints得到左图关键点的位置
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints得到右图关键点的位置
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
   }


// Compute F matrix using RANSAC使用RANSAC计算F矩阵
std::vector<uchar> inliers(points1.size(),0);
cv::Mat fundemental= cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matching points
   inliers,      // match status (inlier ou outlier)  
   CV_FM_RANSAC, // RANSAC method
   distance,     // distance to epipolar line
   confidence);  // confidence probability

// extract the surviving (inliers) matches提取存在的(内窗层)匹配
std::vector<uchar>::const_iterator itIn= inliers.begin();
std::vector<cv::DMatch>::const_iterator itM= matches.begin();
// for all matches对于所有的匹配
for ( ;itIn!= inliers.end(); ++itIn, ++itM) {


if (*itIn) { // it is a valid match这是一个有效匹配


outMatches.push_back(*itM);
}
}


std::cout << "Number of matched points (after cleaning): " << outMatches.size() << std::endl;


if (refineF) {
// The F matrix will be recomputed with all accepted matchesF矩阵根据所有已接收到匹配重新计算

// Convert keypoints into Point2f for final F computation关键点转换成Point2f 以计算最终的F

points1.clear();
points2.clear();

for (std::vector<cv::DMatch>::const_iterator it= outMatches.begin();
it!= outMatches.end(); ++it) {


// Get the position of left keypoints得到左图关键点的位置
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints得到右图关键点的位置
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}


// Compute 8-point F from all accepted matches从所有接收到匹配计算8个点的 F
fundemental= cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matching points
CV_FM_8POINT); // 8-point method
}


return fundemental;
 }


 // Match feature points using symmetry test and RANSAC使用对称测试和RANSAC匹配特征点
 // returns fundemental matrix返回基本矩阵
 cv::Mat match(cv::Mat& image1, cv::Mat& image2, // input images 
 std::vector<cv::DMatch>& matches, // output matches and keypoints
 std::vector<cv::KeyPoint>& keypoints1, std::vector<cv::KeyPoint>& keypoints2) {


// 1a. Detection of the SURF features  SURF 特征检测
detector->detect(image1,keypoints1);
detector->detect(image2,keypoints2);


std::cout << "Number of SURF points (1): " << keypoints1.size() << std::endl;
std::cout << "Number of SURF points (2): " << keypoints2.size() << std::endl;


// 1b. Extraction of the SURF descriptors提取SURF描述符
cv::Mat descriptors1, descriptors2;
extractor->compute(image1,keypoints1,descriptors1);
extractor->compute(image2,keypoints2,descriptors2);


std::cout << "descriptor matrix size: " << descriptors1.rows << " by " << descriptors1.cols << std::endl;


// 2. Match the two image descriptors匹配两幅图像的描述符


// Construction of the matcher 构建匹配
cv::BruteForceMatcher<cv::L2<float>> matcher;


// from image 1 to image 2从图像1到图像2
// based on k nearest neighbours (with k=2)基于k个最近的邻居
std::vector<std::vector<cv::DMatch>> matches1;
matcher.knnMatch(descriptors1,descriptors2, 
matches1, // vector of matches (up to 2 per entry) 匹配向量
2);  // return 2 nearest neighbours返回两个最近的邻居


// from image 2 to image 1从图像1到图像2
// based on k nearest neighbours (with k=2)
std::vector<std::vector<cv::DMatch>> matches2;
matcher.knnMatch(descriptors2,descriptors1, 
matches2, // vector of matches (up to 2 per entry) 
2);  // return 2 nearest neighbours


std::cout << "Number of matched points 1->2: " << matches1.size() << std::endl;
std::cout << "Number of matched points 2->1: " << matches2.size() << std::endl;


// 3. Remove matches for which NN ratio is bigger than threshold删除NN比大于阈值的匹配


// clean image 1 -> image 2 matches删除图像1到图像2的匹配
int removed= ratioTest(matches1);
std::cout << "Number of matched points 1->2 (ratio test) : " << matches1.size()-removed << std::endl;
// clean image 2 -> image 1 matches删除图像2到图像1的匹配
removed= ratioTest(matches2);
std::cout << "Number of matched points 1->2 (ratio test) : " << matches2.size()-removed << std::endl;


// 4. Remove non-symmetrical matches删除不对称匹配
   std::vector<cv::DMatch> symMatches;
symmetryTest(matches1,matches2,symMatches);


std::cout << "Number of matched points (symmetry test): " << symMatches.size() << std::endl;


// 5. Validate matches using RANSAC 使用RANSAC验证匹配

cv::Mat fundemental= ransacTest(symMatches, keypoints1, keypoints2, matches);


// return the found fundemental matrix返回找到的基本矩阵
return fundemental;
}
};


#endif

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值