/***好记性不如烂笔头,记下来便于以后复习***/
特征匹配的结果会得到两个特征集合的对应关系列表。第一组特征集被称为训练集(train),第二组被称为查询集(query)。Flann 在调用匹配函数之前,为了提高匹配速度,训练一个匹配器。训练阶段是为了优化cv::FlannBasedMatcher的性能。train类将会建立特征集的索引树。将 query image 的每一个特征点和 train 匹配器进行匹配,找出最佳匹配;也就是从query image 的特征中逐个去和训练器做匹配,也就是说每一个query image 特征点都会有一个最佳匹配,后期还需要验证这匹配的正确性,可以通过设置截断值来去除误差大的匹配;
去除了误差大的匹配即可以使用 Lowe's策略进行匹配的再一次筛选;
knnMatch()找每个query image特征的K近邻匹配,效率不够高,帧率很低。
Lowe’s算法:为了进一步筛选匹配点,来获取优秀的匹配点,这就是所谓的“去粗取精”。一般会采用Lowe’s算法来进一步获取优秀匹配点。
为了排除因为图像遮挡和背景混乱而产生的无匹配关系的关键点,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:一般情况下。
Lowe's改进:可以反过来使用最近邻比次近邻,在匹配中可以作为置信度来使用,当满足最近邻比次近邻大于某个值的时候,作为某个条件的判别 置信度;比如可以应用在双目视觉立体匹配中的视差选择与优化环节中(论文正在编写中);
#include "highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/legacy/legacy.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat image01 = imread("g2.jpg", 1);
Mat image02 = imread("g4.jpg", 1);
imshow("p2", image01);
imshow("p1", image02);
//灰度图转换
Mat image1, image2;
cvtColor(image01, image1, CV_RGB2GRAY);
cvtColor(image02, image2, CV_RGB2GRAY);
//提取特征点
SurfFeatureDetector surfDetector(2000); //海塞矩阵阈值,在这里调整精度,值越大点越少,越精准
vector<KeyPoint> keyPoint1, keyPoint2;
surfDetector.detect(image1, keyPoint1);
surfDetector.detect(image2, keyPoint2);
//特征点描述,为下边的特征点匹配做准备
SurfDescriptorExtractor SurfDescriptor;
Mat imageDesc1, imageDesc2;
SurfDescriptor.compute(image1, keyPoint1, imageDesc1);
SurfDescriptor.compute(image2, keyPoint2, imageDesc2);
FlannBasedMatcher matcher;
vector<vector<DMatch> > matchePoints;
vector<DMatch> GoodMatchePoints;
vector<Mat> train_desc(1, imageDesc1);
matcher.add(train_desc);
matcher.train();
matcher.knnMatch(imageDesc2, matchePoints, 2);
cout << "total match points: " << matchePoints.size() << endl;
// 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]);
}
}
Mat first_match;
drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
imshow("first_match ", first_match);
waitKey();
return 0;
}
参考博客:
https://blog.csdn.net/xxzxxzdlut/article/details/72930209
https://www.cnblogs.com/wyuzl/p/7816011.html
转载自原文链接, 如需删除请联系管理员。
原文链接:Flann特征点匹配简述(Lowe's algorithm),转载请注明来源!