FLANN(快速最近邻逼近搜索函数库),它是一个算法库,包含一系列算法库,OpenCv中集成了FLANN的一部分匹配算法,主要对高维数据搜索比较快。
相比于上一篇的暴力匹配算法,FLANN更加精确,不会有过多的描述特征匹配到。
匹配基本步骤:
检测->提取->计算得到描述子->特征比对
实现代码:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
#include<math.h>
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
//检测计算和绘制时,源图(img1)在前面,目标图像(img2)在后面
Mat img1, img2;
int main(int argc, char**argv)
{
img1 = imread("D:/test/BookAll.png", 0);
img2 = imread("D:/test/Bookinscene.png", 0);
if (!img1.data || !img2.data)
{
cout << "图片为空!" << endl;
return -1;
}
int minHesssion = 400;
Ptr<SURF> detector = SURF::create(minHesssion); //也可以用SIRF,但是效率比SURF低
vector<KeyPoint> keypoints_obj; //存放img1的特征值
vector<KeyPoint> keypoints_scene; //存放img2的特征值
Mat descript_obj, descript_scene;
detector->detectAndCompute(img1, Mat(), keypoints_obj, descript_obj); //检测并计算特征描述子
detector->detectAndCompute(img2, Mat(), keypoints_scene, descript_scene);
FlannBasedMatcher fbmatcher;
vector<DMatch>matches;
fbmatcher.match(descript_obj, descript_scene, matches); //特征描述子匹配
//找出最优特征点
double minDist = 1000; //初始化最大最小距离
double maxDist = 0;
for (int i = 0; i < descript_obj.rows; i++)
{
double dist = matches[i].distance;
if (dist > maxDist)
{
maxDist = dist;
}
if (dist < minDist)
{
minDist = dist;
}
}
printf("maxDist:%f\n", maxDist);
printf("minDist:%f\n", minDist);
vector<DMatch> goodMatches;
for (int i = 0; i < descript_obj.rows; i++)
{
double dist = matches[i].distance;
if (dist < max(2 * minDist, 0.02)) {
goodMatches.push_back(matches[i]);
}
}
Mat resultImg;
drawMatches(img1, keypoints_obj, img2, keypoints_scene, goodMatches, resultImg, Scalar::all(-1),
Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS
);
imshow("input image1", img1);
imshow("input image2", img2);
imshow("FlannBasedMatcher demo", resultImg);
waitKey(0);
return 0;
}
需要匹配的图片1(目标图片):
需要匹配的图片2(源图片):
运行结果:
1、当if (dist < max(2 * minDist, 0.02)) { goodMatches.push_back(matches[i]); }
中为(2 * minDist)
所得结果是:
查找的结果很精确,但匹配到的共有描述子很少。
2、当if (dist < max(3 * minDist, 0.02)) { goodMatches.push_back(matches[i]); }
中为(3 * minDist)
所得结果是:
查找的结果较为精确,匹配到的共有描述子稍多,但比之暴力匹配,已经很精准了。
注:这里的(n * minDist)中的n可以取成小数,如:1.5,2.5等等,根据情况而定。