opencv特征匹配完成后筛选匹配点方法

        时间有限,本人在csdn上看到了三种匹配完成后筛选匹配点的方法,(csdn的搬运工,啥也不懂),若有其他的方法,欢迎交流指正。

1、第一种方法:

            最简单的利用经验值筛选最小距离4倍的matches或者小于最大距离的0.6倍;

vector good_matches;
double min_distance = 9999;
for (size_t i = 0; i < matches.size(); i++) {
    if (matches[i].distance < min_distance) {
      min_distance = matches[i].distance;
    }
}
for (size_t i = 0; i < matches.size(); i++) {
    if (matches[i].distance < 4 * min_distance) {
      good_matches.push_back(matches[i]);
    }
}

2、第二种方法:

        SIFT的作者Lowe提出了比较最近邻距离与次近邻距离的SIFT匹配方式:取一幅图像中的一个SIFT关键点,并找出其与另一幅图像中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离得到的比率ratio少于某个阈值T,则接受这一对匹配点。因为对于错误匹配,由于特征空间的高维性,相似的距离可能有大量其他的错误匹配,从而它的ratio值比较高。显然降低这个比例阈值T,SIFT匹配点数目会减少,但更加稳定,反之亦然。

Lowe推荐ratio的阈值为0.8,但作者对大量任意存在尺度、旋转和亮度变化的两幅图片进行匹配,结果表明ratio取值在0. 4~0. 6 之间最佳,小于0. 4的很少有匹配点,大于0. 6的则存在大量错误匹配点,所以建议ratio的取值原则如下:

ratio=0. 4:对于准确度要求高的匹配;

ratio=0. 6:对于匹配点数目要求比较多的匹配;

ratio=0. 5:一般情况下。

FlannBasedMatcher matcher;
vector > matchePoints;
vector GoodMatchePoints;
matcher.knnMatch(imageDesc1, imageDesc2, matchePoints, 2);
    // Lowe's algorithm,获取优秀匹配点
for (int i = 0; i < matchePoints.size(); i++){
    if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance) {
            GoodMatchePoints.push_back(matchePoints[i][0]);
    }
}

     FlannBasedMatcher 默认的KD-tree,自身带train,knnmatch应该用的是机器学习的knn算法,此外源码中还有radiusMatch,没去试,感兴趣的可以尝试一下。

3、第三种方法:

     通过RANSAC方法计算透视变换矩阵来筛选符合相同透视的特征点,这样做可以去除很多错误的匹配。

std::vector srcPoints(matches.size());
std::vector dstPoints(matches.size());
for (size_t i = 0; i < matches.size(); i++) {
    srcPoints[i] = trainKeypoints[matches[i].trainIdx].pt;
    dstPoints[i] = queryKeypoints[matches[i].queryIdx].pt;
}
 
std::vector inliersMask(srcPoints.size());
homography = cv::findHomography(srcPoints, dstPoints, CV_FM_RANSAC,
			reprojectionThreshold, inliersMask);
 
std::vector inliers;
for (size_t i = 0; i < inliersMask.size(); i++) {
    if (inliersMask[i])
	inliers.push_back(matches[i]);
}
matches.swap(inliers);

4、第四种方法:

    RANSAC 消除误匹配特征点 主要分为三个部分:
       1)根据matches将特征点对齐,将坐标转换为float类型
       2)使用求基础矩阵方法 findFundamentalMat,得到RansacStatus
       3)根据RansacStatus来将误匹配的点也即RansacStatus[i]=0的点删除

    不知道和第三种有什么区别,用的都是RANSAC 算法消除误匹配,但提取的函数不一样。

//根据matches将特征点对齐,将坐标转换为float类型
vector R_keypoint1,R_keypoint2;
for (size_t i=0;ip1,p2;
for (size_t i=0;i RansacStatus;
Mat Fundamental= findFundamentalMat(p01,p02,RansacStatus,FM_RANSAC);


vector RR_keypoint1,RR_keypoint2;
vector RR_matches;     //重新定义RR_keypoint 和RR_matches来存储新的关键点和匹配矩阵
int index=0;
for (size_t i=0;i

 

欢迎交流。

参考博客:

1.https://blog.csdn.net/weixin_33709609/article/details/85933024

2.https://blog.csdn.net/u010141147/article/details/9464571

3.https://blog.csdn.net/u011582199/article/details/82626629

你可能感兴趣的:(opencv,特征匹配,筛选特征匹配点,opencv)