时间有限,本人在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