图像特征提取与匹配方法总结

在图像处理的过程中,特征点的选取与匹配是其中非常重要的一个部分,常见的应用场景有,图像的目标检测与追踪、地图场景关键点信息的提取等。

图像关键点特征选取与匹配一共包括三个步骤:

1、关键点检测

2、关键点描述

3、关键点匹配

在关键点检测的方法中:

首先需要知道角点的概念,角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中,也称为特征点检测。

角点的检测算法

1、Moravec角点检测算法

Moravec角点检测算法是最早的角点检测算法之一,该算法会检测图像的每一个像素,将像素周边的一个邻域作为一个patch,并检测这个patch和周围其他patch的相关性。这种相关性通过两个patch间的平方差之和(SSD)来衡量,SSD值越小则相似性越高。
如果像素位于平滑图像区域内,周围的patch都会非常相似。如果像素在边缘上,则周围的patch在与边缘正交的方向上会有很大差异,在与边缘平行的方向上则较为相似。而如果像素是各个方向上都有变化的特征点,则周围所有的patch都不会很相似。
Moravec会计算每个像素patch和周围patch的SSD最小值作为强度值,取局部强度最大的点作为特征点。

2、Harris角点检测

当一个窗口在图像上移动,在平滑区域如图(a),窗口在各个方向上没有变化。在边缘上如图(b),窗口在边缘的方向上没有变化。在角点处如图(c),窗口在各个方向上具有变化。Harris角点检测正是利用了这个直观的物理现象,通过窗口在各个方向上的变化程度,决定是否为角点,Harris角点检测算法就是对角点响应函数R进行阈值处理:R > threshold,即提取R的局部极大值。

3、Shi-Tomasi 算法

Shi-Tomasi 算法是Harris 算法的改进。Harris 算法最原始的定义是将矩阵 M 的行列式值与 M 的迹相减,再将差值同预先给定的阈值进行比较。后来Shi 和Tomasi 提出改进的方法,若两个特征值中较小的一个大于最小阈值,则会得到强角点。Shi 和Tomasi 的方法比较充分,并且在很多情况下可以得到比使用Harris 算法更好的结果。

关键点描述算法

1、BRISK特征

        BRISK算法是是一种二进制的特征描述算子,它具有较好的旋转不变性、尺度不变性,较好的鲁棒性等。在图像配准应用中,速度比较:SIFT<SURF<BRISK<FREAK<ORB,

      在对有较大模糊的图像配准时,BRISK算法在其中表现最为出色。

代码实现如下:

代码实现的整体思路:

1、加载图片,分别为目标图片和场景图片

2、创建特征描述器,用于进行特征点检测以及计算特征描述,使用detextAndCompute()函数进行实现,下面带面中的四个参数代表的含义分别为输入图像、掩码、输出特征点集合、输出特征描述向量

3、创建匹配器,这里用特征之间的最小值进行计算

4、寻找匹配点之间的映射矩阵,使用prespectiveTransfrom()函数进行实现

5、绘制图像区域

#include <opencv2/opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
 
 
int main(int argc, char** argv) 
{	
	Mat img1 = imread("D:/cv400/data/box.png", 0);
	Mat img2 = imread("D:/cv400/data/box_in_scene.png", 0);
	if (img1.empty() || img2.empty()) 
	{
		cout << "Load image error..." << endl;
		return -1;
	}
	imshow("object image", img1);
	imshow("object in scene", img2);
 
	// surf featurs extraction
	double t1 = (double)getTickCount();
	//int minHessian = 400;
	Ptr<Feature2D> detector = BRISK::create();
	vector<KeyPoint> keypoints_obj;
	vector<KeyPoint> keypoints_scene;
	Mat descriptor_obj, descriptor_scene;
	detector->detectAndCompute(img1, Mat(), keypoints_obj, descriptor_obj);
	detector->detectAndCompute(img2, Mat(), keypoints_scene, descriptor_scene);
//detectAndCompute()函数是用来检测关键点并计算描述符
 
	// matching
	BFMatcher matcher(NORM_L2);
	vector<DMatch> matches;
	matcher.match(descriptor_obj, descriptor_scene, matches);
	double t2 = (double)getTickCount();
	double t = (t2 - t1) / getTickFrequency();
	cout << "spend time : " << t << "s" << endl;
	
	//求匹配点最近距离
	double minDist = 1000;
	for (int i = 0; i < descriptor_obj.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist < minDist) 
			minDist = dist;	
	}
	cout<<"min distance : "<< minDist<<endl;
 
	//距离较近即匹配较好的点
	vector<DMatch> goodMatches;
	for (int i = 0; i < descriptor_obj.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist < max(2* minDist, 0.02)) 
			goodMatches.push_back(matches[i]);	
	}
 
	
	//寻找匹配上的关键点的变换
	vector<Point2f> obj;  //目标特征点
	vector<Point2f> objInScene;  //场景中目标特征点
	for (size_t t = 0; t < goodMatches.size(); t++) 
	{
		obj.push_back(keypoints_obj[goodMatches[t].queryIdx].pt);
		objInScene.push_back(keypoints_scene[goodMatches[t].trainIdx].pt);
	}
	Mat imgBH = findHomography(obj, objInScene, RANSAC);
 
	//映射点
	vector<Point2f> obj_corners(4);
	vector<Point2f> scene_corners(4);
	obj_corners[0] = Point(0, 0);
	obj_corners[1] = Point(img1.cols, 0);
	obj_corners[2] = Point(img1.cols, img1.rows);
	obj_corners[3] = Point(0, img1.rows);
	perspectiveTransform(obj_corners, scene_corners, imgBH);
 
	//四个点之间画线
	Mat dst;
	cvtColor(img2, dst, COLOR_GRAY2BGR);
	for(int i=0;i<4;i++)
		line(dst, scene_corners[i%4], scene_corners[(i+1)%4], Scalar(0, 0, 255), 2, 8, 0);
	
	imshow("find object in sence", dst);
	waitKey(0);
	return 0;
}

2、HOG特征描述子

 

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值