OpenCv-C++-BRISK特征检测与匹配

BRISK:Binary Robust Invariant Scalable Keypoints。它是一种二进制的特征描述算子。它具有较好的旋转不变性、尺度不变性,较好的鲁棒性等。在对有较大模糊的图像配准时,BRISK算法在其中表现最为出色。

算法原理参考下面这篇文章,其中的表达描述的很清楚。
参考文章:https://blog.csdn.net/hujingshuang/article/details/47045497

特征检测与步骤:
1、构建尺度空间-------->高斯金字塔构建;
2、特征点检测;
3、FAST9-16寻找特征点----------->连续9个点大于或小于当前值都被视为特征点;
4、特征点定位;
5、关键点描述子。

大体上来说,只要是涉及特征点寻找的,都要保持旋转不变性,尺度不变性,光照强度不变性等。只需要解决以上问题,特征点的检测就较为准确。

代码部分:

#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>

using namespace cv;
using namespace std;


int main(int argc, char**argv)
{
	Mat img1 = imread("D:/test/box.png",IMREAD_GRAYSCALE);
	Mat img2 = imread("D:/test/box_in_scene.png", IMREAD_GRAYSCALE);
	if (!img1.data || !img2.data)
	{
		cout << "图片未找到!!!" << endl;
		return -1;
	}
	imshow("img1_box", img1);
	imshow("img2_scene", img2);
	//用Brisk算法去检测特征点
	vector<KeyPoint> keypoint_obj;
	vector<KeyPoint> keypoint_scene;
	double t1 = getTickCount();//计算运行时间

	Ptr<Feature2D> detect = BRISK::create();
	Mat desciptor_obj, descriptor_scene;
	//检测并计算描述子
	detect->detectAndCompute(img1, Mat(), keypoint_obj, desciptor_obj);
	detect->detectAndCompute(img2, Mat(), keypoint_scene, descriptor_scene);

	double t2 = getTickCount();
	double t = (t2 - t1) * 1000 / getTickFrequency();
	//匹配描述子,这里使用FLANN匹配,也可以使用(BF)暴力匹配
	vector<DMatch> matches;
	FlannBasedMatcher fbmatcher(new flann::LshIndexParams(20, 10, 2));
	//匹配描述子
	fbmatcher.match(desciptor_obj, descriptor_scene, matches);
	vector<DMatch> goodmatches;//找到最优匹配点
	double minDist = 1000;
	double maxDist = 0;//初始化
	
	for (int i = 0; i < desciptor_obj.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist > maxDist)
		{
			maxDist = dist;
		}
		if (dist < minDist)
		{
			minDist = dist;
		}


	}
	for (int i = 0; i < desciptor_obj.rows; i++)
	{
		double dist = matches[i].distance;
		//比最小距离还小的就是最优匹配点
		if (dist < max(2 * minDist, 0.02))
		{
			goodmatches.push_back(matches[i]);

		}
	}
	Mat resultImg;
	drawMatches(img1, keypoint_obj, img2, keypoint_scene, goodmatches, resultImg,
		Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
	imshow("BRISK Matches demo",resultImg);
	printf("BRISK 执行时间为(ms):%f",t);

	//使用透视矩阵画出匹配物体
	vector<Point2f> obj;
	vector<Point2f> scene_in_obj;
	
	for (size_t i= 0; i < goodmatches.size(); i++) 
	{
		obj.push_back(keypoint_obj[goodmatches[i].queryIdx].pt);
		scene_in_obj.push_back(keypoint_scene[goodmatches[i].trainIdx].pt);

	}
	//生成透视矩阵
	Mat H = findHomography(obj, scene_in_obj, RANSAC);

	vector<Point2f>obj_corner(4);
	vector<Point2f>scene_corner(4);
	obj_corner[0] = Point(0, 0);
	obj_corner[1] = Point(img1.cols, 0);
	obj_corner[2] = Point(img1.cols,img1.rows);
	obj_corner[3] = Point(0, img1.rows);

	//透视变换
	perspectiveTransform(obj_corner, scene_corner, H);
	Mat pptfImg = resultImg.clone();
	line(pptfImg, scene_corner[0] + Point2f(img1.cols, 0), scene_corner[1] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
	line(pptfImg, scene_corner[1] + Point2f(img1.cols, 0), scene_corner[2] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
	line(pptfImg, scene_corner[2] + Point2f(img1.cols, 0), scene_corner[3] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
	line(pptfImg, scene_corner[3] + Point2f(img1.cols, 0), scene_corner[0] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
	imshow("pptfImg demo",pptfImg);

	waitKey(0);
	return 0;

}

运行结果:
在这里插入图片描述

在这里插入图片描述

算法执行效率:
在这里插入图片描述

可以看到,BRISK算法的执行效率大概在3秒左右,上一篇文章所提到的KAZE大概在2秒左右,AKAZE则更少,虽然BRISK效率慢了点,但是在图像配准应用中,速度比较:SIFT<SURF<BRISK<FREAK<ORB,在对有较大模糊的图像配准时,BRISK算法在其中表现最为出色。

猜你喜欢

转载自blog.csdn.net/Daker_Huang/article/details/84960704
今日推荐