**

前言

**
只要接口到手,不管烫不烫拿着就用。

**

FLANN特征点匹配

**

FLANN与SURF匹配使用上区别不大,只是在匹配和绘制之间多了

  1. 快速计算关键点间的最大最小距离
  2. 保存符合条件的匹配结果

这两步。对匹配后的输出图进行了处理,然后才绘制。

#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;

int main() {

	Mat img_1 = imread("E:/File/1.jpg");
	Mat img_2 = imread("E:/File/2.jpg");
	resize(img_1, img_1, Size(400, 400));
	resize(img_2, img_2, Size(400, 400));
	if (!img_1.data || !img_2.data) {
		cout << "ERROR";
		system("pause");
	}



	//SURF检测关键点
	int minHessian = 300;
	Ptr<xfeatures2d::SURF> detector = xfeatures2d::SURF::create(minHessian);
	vector<KeyPoint> keypoints_1, keypoints_2;
	detector->detect(img_1, keypoints_1);
	detector->detect(img_2, keypoints_2);


	//计算描述符(特征向量)
	Ptr<xfeatures2d::SURF> extrator = xfeatures2d::SURF::create();
	Mat desriptors_1, desriptors_2;
	extrator->compute(img_1, keypoints_1, desriptors_1);
	extrator->compute(img_2, keypoints_2, desriptors_2);



	//采用FLANN算法匹配描述符向量
	Ptr<FlannBasedMatcher> matcher = FlannBasedMatcher::create();
	vector<DMatch> matches;
	matcher->match(desriptors_1, desriptors_2, matches);
	


	//快速计算关键点间的最大最小距离
	double max_dist = 0, min_dist = 100;
	for (int i = 0; i < desriptors_1.rows; ++i) {
		double dist = matches[i].distance;
		if (dist < min_dist)min_dist = dist;
		if (dist > max_dist)max_dist = dist;
	}
	//输出距离信息
	printf(">最大距离(Max dist)> %f\n", max_dist);
	printf(">最小距离(Min dist) > %f\n", min_dist);


	//保存匹配结果小于2*min_dist的点
	vector<DMatch> good_matches;
	for (int i = 0; i < desriptors_1.rows; ++i) {
		if (matches[i].distance < 2 * min_dist)
			good_matches.push_back(matches[i]);
	}



	//绘制出符合条件的匹配点
	Mat img_matches;
	drawMatches(img_1, keypoints_1,
		img_2, keypoints_2,
		good_matches,//1到2的匹配点
		img_matches,//输出图像
		Scalar::all(-1),
		Scalar::all(-1),
		vector<char>(),
		DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);



	//输出相关匹配点信息
	for (int i = 0; i < good_matches.size(); ++i) {
		printf(">符合条件的匹配点  [%d] 特征点1> %d -----  特征点2> %d\n",
			i, good_matches[i].queryIdx, good_matches[i].trainIdx);
	}



	//显示效果图
	imshow("匹配效果图", img_matches);


	while (char(waitKey(10)) < 0)
		;
	destroyAllWindows();
}

opencv特征融合 opencv4特征点检测与匹配_opencv特征融合

**

FLANN结合SURF进行关键点的描述和匹配

**

#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;

int main() {

	Mat trainImage = imread("E:/File/noknown.jpg");
	resize(trainImage, trainImage, Size(400, 400));
	if (trainImage.empty()) {
		cout << "ERROR";
		system("pause");
	}
	Mat trainImage_gray;
	imshow("原始图", trainImage);
	cvtColor(trainImage, trainImage_gray, COLOR_BGR2GRAY);


	//检测SURF关键点,提取训练图像描述符
	vector<KeyPoint> train_keypoint;
	Mat trainDescriptor;
	int minHessian = 80;
	Ptr<xfeatures2d::SURF>  feature_detector = xfeatures2d::SURF::create(minHessian);
	feature_detector->detect(trainImage_gray, train_keypoint);
	Ptr<xfeatures2d::SURF> feature_extractor = xfeatures2d::SURF::create();
	feature_extractor->compute(trainImage_gray, train_keypoint, trainDescriptor);


	//创建基于FLANN的描述符对象
	Ptr<FlannBasedMatcher> matcher=FlannBasedMatcher::create();
	vector<Mat>  train_desc_collection(1, trainDescriptor);
	matcher->add(train_desc_collection);
	matcher->train();



	//创建视频对象,定义帧率
	VideoCapture cap(0);//0打开摄像头
	unsigned int frameCount = 0;//帧数




	//打算统计平均帧率
	double averageFrameRate = 0, formerFrameRate = 0;
	//
	while (char(waitKey(1)) != 'q') {

		//参数设置
		int64 time0 = getTickCount();
		Mat testImage, testImage_gray;
		cap >> testImage;//采集视频帧到testImage中
		if (testImage.empty())
			continue;


		//转换成灰度
		cvtColor(testImage, testImage_gray, COLOR_BGR2GRAY);

		//检测关键点,提取测试图像描述符
		vector<KeyPoint> test_keypoint;
		Mat testDescriptor;
		feature_detector->detect(testImage_gray, test_keypoint);
		feature_extractor->compute(testImage_gray, test_keypoint, testDescriptor);


		//匹配训练和测试描述符
		vector<vector<DMatch>> matches;
		matcher->knnMatch(testDescriptor, matches, 2);


		//根据劳式算法(Lowe's algorithm),得到优秀的匹配点
		vector<DMatch> goodMatches;
		for (unsigned int i = 0; i < matches.size(); ++i) {
			if (matches[i][0].distance < 0.6 * matches[i][1].distance)
				goodMatches.push_back(matches[i][0]);
		}



		//绘制匹配点
		Mat drawing;
		drawMatches(testImage, test_keypoint,
			trainImage, train_keypoint,
			goodMatches,
			drawing);
		imshow("匹配窗口", drawing);



		double frameRate = getTickFrequency() / (getTickCount() - time0);
		averageFrameRate = (frameRate + formerFrameRate) / 2;
		if (frameRate != 0 && averageFrameRate != 0)
			cout << "当前帧率为>>>" << frameRate << "\t>>>平均帧率 > " << averageFrameRate << endl;
		formerFrameRate = averageFrameRate;
	}


	destroyAllWindows();
}

opencv特征融合 opencv4特征点检测与匹配_C++_02

**

SIFT配合暴力匹配进行关键点描述和提取

**

opencv特征融合 opencv4特征点检测与匹配_opencv特征融合_03


理论上,SURF是SIFT速度的3倍。

下面是一个SIFT算法配合暴力匹配的示例程序,看看SURF算法波SIFT更快(由于匹配方式不同,这里只进行大概比较)

#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;

int main() {

	Mat trainImage = imread("E:/File/noknown.jpg");
	resize(trainImage, trainImage, Size(400, 400));
	if (trainImage.empty()) {
		cout << "ERROR";
		system("pause");
	}
	Mat trainImage_gray;
	imshow("原始图", trainImage);
	cvtColor(trainImage, trainImage_gray, COLOR_BGR2GRAY);


	//检测SIFT关键点,提取训练图像描述符
	vector<KeyPoint> train_keypoint;
	Mat trainDescriptor;
	int minHessian = 80;
	Ptr<xfeatures2d::SIFT>  feature_detector = xfeatures2d::SIFT::create(minHessian);
	feature_detector->detect(trainImage_gray, train_keypoint);
	Ptr<xfeatures2d::SIFT> feature_extractor = xfeatures2d::SIFT::create();
	feature_extractor->compute(trainImage_gray, train_keypoint, trainDescriptor);


	//进行基于描述符的暴力匹配
	Ptr<BFMatcher> matcher = BFMatcher::create();
	vector<Mat>  train_desc_collection(1, trainDescriptor);
	matcher->add(train_desc_collection);
	matcher->train();



	//创建视频对象,定义帧率
	VideoCapture cap(0);//0打开摄像头
	unsigned int frameCount = 0;//帧数



	//打算统计平均帧率
	double averageFrameRate = 0,formerFrameRate=0;
	//
	while (char(waitKey(1)) != 'q') {

		//参数设置
		int64 time0 = getTickCount();
		Mat testImage, testImage_gray;
		cap >> testImage;//采集视频帧到testImage中
		if (testImage.empty())
			continue;


		//转换成灰度
		cvtColor(testImage, testImage_gray, COLOR_BGR2GRAY);

		//检测关键点,提取测试图像描述符
		vector<KeyPoint> test_keypoint;
		Mat testDescriptor;
		feature_detector->detect(testImage_gray, test_keypoint);
		feature_extractor->compute(testImage_gray, test_keypoint, testDescriptor);


		//匹配训练和测试描述符
		vector<vector<DMatch>> matches;
		matcher->knnMatch(testDescriptor, matches, 2);


		//根据劳式算法(Lowe's algorithm),得到优秀的匹配点
		vector<DMatch> goodMatches;
		for (unsigned int i = 0; i < matches.size(); ++i) {
			if (matches[i][0].distance < 0.6 * matches[i][1].distance)
				goodMatches.push_back(matches[i][0]);
		}



		//绘制匹配点
		Mat drawing;
		drawMatches(testImage, test_keypoint,
			trainImage, train_keypoint,
			goodMatches,
			drawing);
		imshow("匹配窗口", drawing);


		
		double frameRate = getTickFrequency() / (getTickCount() - time0);
		averageFrameRate = (frameRate + formerFrameRate) / 2;
		if(frameRate!=0 && averageFrameRate!=0)
			cout << "当前帧率为>>>" <<frameRate<<"\t>>>平均帧率 > "<<averageFrameRate<< endl;
		formerFrameRate = averageFrameRate;
	}


	destroyAllWindows();

}

opencv特征融合 opencv4特征点检测与匹配_opencv特征融合_04

SIFT配合暴力匹配的帧率与SURF的相差无几。倒是点的数量前者更少。

参考:《Opencv3编程入门》