opencv之FLANN匹配(面向C++)

1.FLANN优点

尽管暴力匹配原理简单,但是算法的复杂度高,当遇到特征点数目比较大时,会大大影响程序运行时间,所以我们今天介绍快速最近邻搜寻库(Fast Libray for Approximate Nearest Neighbors,FLANN)用于实现特征点的高效匹配。

2.FLANN相关参数

FLANN被集成在FlannBasedMatcher类中,此类也继承了DescriptorMatcher类,因此可以使用DescriptorMatcher类中相关函数实现特征点匹配。FlannBasedMatcher类重载函数原型如下:

cv::FlannBasedMatcher::FlannBasedMatcher(
const Ptr'<'flann::IndexParams'>'& indexParams=makePtr'<'flann::KDTreeIndexParams'>'(),
const Ptr'<'flann::SearchParams'>'& searchParams=makePtr'<'flann::SearchParams'>'()
)
indexParams:匹配时需要使用的搜索算法标志,可以选择的标志及其含义如下表。
searchParams:递归遍历的次数,遍历次数越多越准确,但是耗时更长。
标志参数 含义
makePtr’<‘flann::KDTreeIndexParams’>'() 采集随机k-d树寻找匹配点
makePtr’<‘flann::KMeansIndexParams’>'() 采用K-means树寻找匹配点
makePtr’<‘flann::HierachicalClusteringIndexParams’>'() 采用层次聚类树寻找匹配点

该函数能够初始化FlannBasedMatcher类变量,以便于后续的特征带你匹配任务。此函数有两个参数,都具有默认值,第一个参数是匹配时需要使用的搜寻算法标志,可以选择的的标志和其含义在上表已经给出,默认值为随机k_d树寻找匹配点,一般情况下使用默认值即可。第二个参数是递归遍历的次数,与迭代终止条件相同,迭代遍历次数终止条件也是通过函数进行定义,该参数用flann::SearchParams()函数实现,该函数具有3个含有默认值的参数,分别是遍历次数(int),误差(float)和是否排序(bool),一般情况下使用默认参数即可。

3.注意事项

FLANN匹配与暴力匹配方式类似,两者都需要根据特征点对描述子之间的距离进行排序和筛选。但是需要注意将BFMatcher类改成FlannBasedMatcher类。其他需要注意使用FLANN方法进行匹配时描述子需要是CV_32F类型,因此ORB特征点的描述子变量需要进行类型转换后才可以实现特征点匹配。代码案例如下:

#include
#include
#include
#include
using namespace cv;
using namespace std;
using namespace xfeatures2d;
void orb_features(Mat &gray, vector<KeyPoint>&keypoints, Mat &descriptions) {
	Ptr<ORB>orb = ORB::create(1000, 1.2f);
	orb->detect(gray, keypoints);
	orb->compute(gray, keypoints, descriptions);


}
int main() {
	Mat img1, img2;
	img1 = imread("D:/样本/12.png");
	img2 = imread("D:/样本/14.png");
	if (!(img1.data&&img2.dataend)) {
		cout << "读取图像错误,请确认图像文件名称是否正确" << endl;
		return -1;
	}
	//提取ORB特征点
	vector<KeyPoint>Keypoints1, Keypoints2;
	Mat descriptions1, descriptions2;
	//计算ORB特征点
	orb_features(img1, Keypoints1, descriptions1);
	orb_features(img2, Keypoints2, descriptions2);
	//判断描述子数据类型,如果数据类型不符,那么需要类型转换。主要针对ORB特征点
	if ((descriptions1.type() != CV_32F) && (descriptions2.type() != CV_32F)) {
		descriptions1.convertTo(descriptions1, CV_32F);
		descriptions2.convertTo(descriptions2, CV_32F);

	}
	//特征点匹配
	vector<DMatch>matches;//定义存放匹配结果的变量
	FlannBasedMatcher matcher;//使用默认值
	matcher.match(descriptions1, descriptions2, matches);
	cout << "matches=" << matches.size() << endl;//匹配成功特征点数目

	//寻找距离最大值和最小值,如果是ORB特征点,那么min_dist取值需要大一些
	double max_dist = 0;
	double min_dist = 0;
	for (int i = 0; i < descriptions1.rows; i++) {
		double dist = matches[i].distance;
		if (dist < min_dist) min_dist = dist;
		if (dist > max_dist) max_dist = dist;

	}
	cout << "Max dist:" << max_dist << endl;
	cout << "Min dist:" << min_dist << endl;
	//将最大值距离的0.4倍作为最优匹配结果进行筛选
	std::vector<DMatch>good_matches;
	for (int i = 0; i < descriptions1.rows; i++) {
		if (matches[i].distance < 0.04*max_dist) {
			good_matches.push_back(matches[i]);
		}
	}
	//匹配成功特征点数目
	cout << "good_matches=" << good_matches.size() << endl;
	Mat outimg, outimg1;
	//绘制匹配结果
	drawMatches(img1, Keypoints1, img2, Keypoints2, matches, outimg);
	drawMatches(img1, Keypoints1, img2, Keypoints2, good_matches, outimg1);
	imshow("未筛选结果", outimg);
	imshow("筛选结果", outimg1);
	waitKey(0);
	return 0;

}

你可能感兴趣的:(opencv,c++,算法,计算机视觉)