前言:
特征点的检测和匹配是计算机视觉中非常重要的技术之一。在物体检测、视觉跟踪、三维重建等领域都有很广泛的应用。由于在OpenCV的3.X版本中,许多著名的特征检测算子(比如SIFT、SURF、ORB算子等)所依赖的稳定版的源代码已经从官方发行的OpenCV3中移除,而转移到一个名为xfeature2d的第三方库当中。因此如果是OpenCV的3.X版本,需要自己手动编译安装扩展模块。
今天我们学习SURF特征检测,其原理部分请参考博客:https://blog.csdn.net/keith_bb/article/details/70225785。
一、相关函数介绍
下面介绍几个在第二节的演示代码中将会用到的函数。
1.1 KeyPoint类
KeyPoint类是一个为特征点检测而生的数据结构,用于形容特征点。
其定义如下所示:
class KeyPoint
{
Point2f pt; // 坐标
float size; // 特征点领域直径
float angle; // 特征点的方向
float response;
int octave; // 特征点所在的图像金字塔的组
int class_id; // 用于聚类的id
}
1.2 drawKeypoints()函数
在我们找到特征点以后,我们需要在原图像上绘制这些特征点。恰巧,OpenCV就为我们提供了这样的函数来实现该功能。
其函数声明如下所示:
其参数解释如下:
src:const Mat &类型,表示输入图像。
keypoints:const vector<KeyPoint> &类型,根据原图像得到的特征点。它是detect函数的输出参数。
outImage: Mat &类型,表示输出图像,其内容取决于第五个参数标识符flags。
color:const Scalar&类型,表示关键点的颜色,有默认值 Scalar::all(-1)。
flags:int类型,绘制关键点的特征标识符,有默认值DrawMatchesFlags::DEFAULT。它可以在下面这个结构体中选取值。
struct DrawMatchesFlags
{
enum
{
DEFAULT = 0, // 创建输出图像矩阵(使用Mat::create)。使用现存的输出图像绘制匹配对和特征点。且对每一个关键点,只绘制中间点。
DRAW_OVER_OUTIMG = 1, //不创建输出图像矩阵,而是在输出图像绘制匹配对。
NOT_DRAM_SINGLE_POINTS = 2, // 单点特征点不被绘制
DRAW_RICH_KEYPOINTS = 4 //对每一个关键点,绘制带大小和方向的关键点圆圈。
};
};
二、代码演示
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
using namespace cv;
using namespace cv::xfeatures2d; // 不要忘了导入扩展模块
using namespace std;
Mat src_img, gray_img;
const string output_name = "SURF特征检测";
int minHessian = 100; // 定义SURF中的hessian阈值特征点检测算子
int max_value = 500;
void SURF_detect_func(int, void *);
int main()
{
src_img = imread("test3.png");
if (src_img.empty())
{
printf("could not load the image...\n");
return -1;
}
namedWindow("原图", CV_WINDOW_AUTOSIZE);
imshow("原图", src_img);
cvtColor(src_img, gray_img, COLOR_BGR2GRAY);
namedWindow(output_name, CV_WINDOW_AUTOSIZE);
createTrackbar("hessian阈值", output_name,&minHessian, max_value, SURF_detect_func);
SURF_detect_func(0,0);
waitKey(0);
return 0;
}
void SURF_detect_func(int, void *)
{
// SURF特征检测
Ptr<SURF> detector = SURF::create(minHessian);
vector<KeyPoint> keypoints;
detector->detect(gray_img, keypoints, Mat()); // 检测src_img图像中的SURF特征
// 绘制关键点
Mat keypoint_img;
drawKeypoints(gray_img, keypoints, keypoint_img, Scalar::all(-1), DrawMatchesFlags::DEFAULT); // Scalar::all(-1)这是一种技巧,就是当用一个负数作为关键点颜色,表示每次随机选取颜色。
imshow(output_name, keypoint_img);
}
运行程序如下所示: