赞
踩
在图像处理的过程中,特征点的选取与匹配是其中非常重要的一个部分,常见的应用场景有,图像的目标检测与追踪、地图场景关键点信息的提取等。
图像关键点特征选取与匹配一共包括三个步骤:
1、关键点检测
2、关键点描述
3、关键点匹配
在关键点检测的方法中:
首先需要知道角点的概念,角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中,也称为特征点检测。
角点的检测算法:
Moravec角点检测算法是最早的角点检测算法之一,该算法会检测图像的每一个像素,将像素周边的一个邻域作为一个patch,并检测这个patch和周围其他patch的相关性。这种相关性通过两个patch间的平方差之和(SSD)来衡量,SSD值越小则相似性越高。
如果像素位于平滑图像区域内,周围的patch都会非常相似。如果像素在边缘上,则周围的patch在与边缘正交的方向上会有很大差异,在与边缘平行的方向上则较为相似。而如果像素是各个方向上都有变化的特征点,则周围所有的patch都不会很相似。
Moravec会计算每个像素patch和周围patch的SSD最小值作为强度值,取局部强度最大的点作为特征点。
当一个窗口在图像上移动,在平滑区域如图(a),窗口在各个方向上没有变化。在边缘上如图(b),窗口在边缘的方向上没有变化。在角点处如图(c),窗口在各个方向上具有变化。Harris角点检测正是利用了这个直观的物理现象,通过窗口在各个方向上的变化程度,决定是否为角点,Harris角点检测算法就是对角点响应函数R进行阈值处理:R > threshold,即提取R的局部极大值。
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特征描述子
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。