Feature Matching with FLANN
一.基础知识
1.Lowe’s算法
为了进一步筛选匹配点,来获取优秀的匹配点,这就是所谓的“去粗取精”。一般会采用Lowe’s算法来进一步获取优秀匹配点。为了排除因为图像遮挡和背景混乱而产生的无匹配关系的关键点,SIFT的作者Lowe提出了比较最近邻距离与次近邻距离的SIFT匹配方式:取一幅图像中的一个SIFT关键点,并找出其与另一幅图像中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离得到的比率ratio少于某个阈值T,则接受这一对匹配点。因为对于错误匹配,由于特征空间的高维性,相似的距离可能有大量其他的错误匹配,从而它的ratio值比较高。显然降低这个比例阈值T,SIFT匹配点数目会减少,但更加稳定,反之亦然。
参考博客:
https://blog.csdn.net/u010368556/article/details/82939404
2.k近邻算法
K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
参考网址:
https://baike.baidu.com/item/k近邻算法/9512781?fr=aladdin
https://www.jianshu.com/p/bad83a08b1a8
3.此外,还有一些概念需要了解,感兴趣的可以进行了解(强烈推荐了解)
https://www.cnblogs.com/wangguchangqing/p/4333873.html
https://www.cnblogs.com/cgjdemo/p/4117400.html?utm_source=tuicool&utm_medium=referral
二.代码实现
#include <iostream>
#include "opencv2/core.hpp"
#ifdef HAVE_OPENCV_XFEATURES2D
#include "opencv2/highgui.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/xfeatures2d.hpp"
using namespace cv
;
using namespace cv
::xfeatures2d
;
using std
::cout
;
using std
::endl
;
const char* keys
=
"{ help h | | Print help message. }"
"{ input1 | ../data/box.png | Path to input image 1. }"
"{ input2 | ../data/box_in_scene.png | Path to input image 2. }";
int main( int argc
, char* argv
[] )
{
CommandLineParser
parser( argc
, argv
, keys
);
Mat img1
= imread( parser
.get
<String
>("input1"), IMREAD_GRAYSCALE
);
Mat img2
= imread( parser
.get
<String
>("input2"), IMREAD_GRAYSCALE
);
if ( img1
.empty() || img2
.empty() )
{
cout
<< "Could not open or find the image!\n" << endl
;
parser
.printMessage();
return -1;
}
int minHessian
= 400;
Ptr
<SURF
> detector
= SURF
::create( minHessian
);
std
::vector
<KeyPoint
> keypoints1
, keypoints2
;
Mat descriptors1
, descriptors2
;
detector
->detectAndCompute( img1
, noArray(), keypoints1
, descriptors1
);
detector
->detectAndCompute( img2
, noArray(), keypoints2
, descriptors2
);
Ptr
<DescriptorMatcher
> matcher
= DescriptorMatcher
::create(DescriptorMatcher
::FLANNBASED
);
std
::vector
< std
::vector
<DMatch
> > knn_matches
;
matcher
->knnMatch( descriptors1
, descriptors2
, knn_matches
, 2 );
const float ratio_thresh
= 0.7f;
std
::vector
<DMatch
> good_matches
;
for (size_t i
= 0; i
< knn_matches
.size(); i
++)
{
if (knn_matches
[i
][0].distance
< ratio_thresh
* knn_matches
[i
][1].distance
)
{
good_matches
.push_back(knn_matches
[i
][0]);
}
}
Mat img_matches
;
drawMatches( img1
, keypoints1
, img2
, keypoints2
, good_matches
, img_matches
, Scalar
::all(-1),
Scalar
::all(-1), std
::vector
<char>(), DrawMatchesFlags
::NOT_DRAW_SINGLE_POINTS
);
imshow("Good Matches", img_matches
);
waitKey();
return 0;
}
#else
int main()
{
std
::cout
<< "This tutorial code needs the xfeatures2d contrib module to be run." << std
::endl
;
return 0;
}
#endif
运行截图: