作者:yjlz2012 | 来源:互联网 | 2023-09-15 17:09
在图像处理的过程中,特征点的选取与匹配是其中非常重要的一个部分,常见的应用场景有,图像的目标检测与追踪、地图场景关键点信息的提取等。图像关键点特征选取与匹配一共包括三个步骤:
在图像处理的过程中,特征点的选取与匹配是其中非常重要的一个部分,常见的应用场景有,图像的目标检测与追踪、地图场景关键点信息的提取等。
图像关键点特征选取与匹配一共包括三个步骤:
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 在对有较大模糊的图像配准时,BRISK算法在其中表现最为出色。
代码实现如下:
代码实现的整体思路:
1、加载图片,分别为目标图片和场景图片
2、创建特征描述器,用于进行特征点检测以及计算特征描述,使用detextAndCompute()函数进行实现,下面带面中的四个参数代表的含义分别为输入图像、掩码、输出特征点集合、输出特征描述向量
3、创建匹配器,这里用特征之间的最小值进行计算
4、寻找匹配点之间的映射矩阵,使用prespectiveTransfrom()函数进行实现
5、绘制图像区域
#include
#include
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..." < return -1;
}
imshow("object image", img1);
imshow("object in scene", img2);
// surf featurs extraction
double t1 = (double)getTickCount();
//int minHessian = 400;
Ptr detector = BRISK::create();
vector keypoints_obj;
vector 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 matches;
matcher.match(descriptor_obj, descriptor_scene, matches);
double t2 = (double)getTickCount();
double t = (t2 - t1) / getTickFrequency();
cout <<"spend time : " <
//求匹配点最近距离
double minDist = 1000;
for (int i = 0; i {
double dist = matches[i].distance;
if (dist minDist = dist;
}
cout<<"min distance : "<
//距离较近即匹配较好的点
vector goodMatches;
for (int i = 0; i {
double dist = matches[i].distance;
if (dist goodMatches.push_back(matches[i]);
}
//寻找匹配上的关键点的变换
vector obj; //目标特征点
vector objInScene; //场景中目标特征点
for (size_t t = 0; 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 obj_corners(4);
vector 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特征描述子