1. 常用的特征检测常用方法
- FAST——FastFeatureDetector
- STAR——StarFeatureDetector
- SIFT——SIFT(nonfree module)
- SURF——SURF(nonfree module)
- ORB——ORB
- MSER——MSER
- GFTT——GoodFeatureToTrackDetector
- HARRIS——GoodFeatureToTrackDetector(配合HarrisDetector操作)
- Dense——DenseFeatureDetector
- SimpleBlob——SimpleBlobDetector
2. SURF特征点检测
2.1 SURF算法概述
SURF英文全称为SpeedUp Robust Features。SURF是SIFT算法的加速版 。SURF可以用于计算机视觉的物体识别以及3D重构中。
2.2 SURF算法原理
① 构建Hessian矩阵构建高斯金字塔尺度空间
SIFT采用的是DOG图像(Difference of Gaussian),而SURF采用的是Hessian矩阵近似值图像。Hessian矩阵是SURF算法的核心。
海森矩阵是一个自变量为实值函数二阶偏导数组成的方块矩阵。所以图像中某个像素点的Hessian矩阵为
H(f(x,y))=⎡⎣⎢∂2f∂x2∂2f∂x∂y∂2f∂x∂y∂2f∂y2⎤⎦⎥
H
(
f
(
x
,
y
)
)
=
[
∂
2
f
∂
x
2
∂
2
f
∂
x
∂
y
∂
2
f
∂
x
∂
y
∂
2
f
∂
y
2
]
且每一个像素点都可以求出一个Hessian矩阵。
H矩阵的判别式为:
det(H)=∂2f∂2f∂x2∂y2−(∂2f∂x∂y)2
d
e
t
(
H
)
=
∂
2
f
∂
2
f
∂
x
2
∂
y
2
−
(
∂
2
f
∂
x
∂
y
)
2
根据判别式的正负情况可以判断该点是不是极值点。
求Hessian矩阵时要先进行高斯滤波,然后再求二阶导数。
经过上述步骤得到一张近似Hessian行列式图。
②利用非极大值抑制初步确定特征点
将经过Hessian矩阵处理的每个像素点与三位邻域的26个点进行比较,如果它是最大值或最小值,则保留,当做初步特征点。
③精确定位极值点
采用三维线性插值法得到亚像素级特征点,同时将小于一定阈值的点去除,得到几个特征最强的点。
④选取特征点的主方向
⑤构造SURF特征点描述算子
2.3 SURF类在OpenCV代码分析
在OpenCV中SURF类、SurfFeatureDetector类、SurfDescriptorExtractor类等价。
2.3.1 drawKeypoints()函数
void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, CV_OUT Mat& outImage,const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
第二个参数:const vector< KeyPoint >& 类型的keypoints,根据图像得到的特征点;
第三个参数:输出图像,其形式取决于第五个参数;
第四个参数:关键点的颜色;
第五个参数:int 类型的 flags,默认为DEFAULT,表示使用创建的的输出图像绘制匹配对和特征点;当为DRAW_ OVER _OUTIMG时,不创建输出图像矩阵而是在输出图像上绘制匹配对……
2.3.2 KeyPoint类
KeyPoint类用于表示特征点。
class KeyPoint
{
Point2f pt; //坐标
float size; //特征点邻域直径;
float angle; //特征点方向,值为0-360
float response;
int octave; //特征点所在的图像金字塔的组
int class_id;//用于聚类的id
}
2.3.3 程序实例
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include <iostream>
using namespace cv;
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
//【0】改变console字体颜色
system("color 2F");
//【1】载入源图片并显示
Mat srcImage1 = imread("1.jpg", 1 );
Mat srcImage2 = imread("2.jpg", 1 );
if( !srcImage1.data || !srcImage2.data )//检测是否读取成功
{ printf("读取图片错误,请确定目录下是否有imread函数指定名称的图片存在~! \n"); return false; }
imshow("原始图1",srcImage1);
imshow("原始图2",srcImage2);
//【2】定义需要用到的变量和类
int minHessian = 400;//定义SURF中的hessian阈值特征点检测算子
SurfFeatureDetector detector( minHessian );//定义一个SurfFeatureDetector(SURF) 特征检测类对象
std::vector<KeyPoint> keypoints_1, keypoints_2;//vector模板类是能够存放任意类型的动态数组,能够增加和压缩数据
//【3】调用detect函数检测出SURF特征关键点,保存在vector容器中
detector.detect( srcImage1, keypoints_1 );
detector.detect( srcImage2, keypoints_2 );
//【4】绘制特征关键点.
Mat img_keypoints_1; Mat img_keypoints_2;
drawKeypoints( srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
drawKeypoints( srcImage2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
//【5】显示效果图
imshow("特征点检测效果图1", img_keypoints_1 );
imshow("特征点检测效果图2", img_keypoints_2 );
waitKey(0);
return 0;
}