SERF(speed up robust feature )特征的关键特性:
- 特征检测
- 尺度空间:缩放到不同的大小或分辨率仍能检测
- 选择不变性:光照不变,旋转不变
- 特征向量:描述为一个特征向量
DDN过程为:检测、描述、匹配
工作原理:
- 选择感兴趣的区域POI,用Hessian矩阵找到,然后求取梯度
- 在不同尺度空间发现关键点,非最大信号压制,把不是局部的最大信号放弃
- 发现特征点,求取在某个方向上的特征最大值就找到了特征方向。旋转不变性
- 再根据光照不变性生成特征向量
Hessian矩阵:$left[ {egin{array}{*{20}{c}}
{frac{{partial {I^2}}}{{partial {x^2}}}}&{frac{{partial {I^2}}}{{partial xpartial y}}}\
{frac{{partial {I^2}}}{{partial ypartial x}}}&{frac{{partial {I^2}}}{{partial {{
m{y}}^2}}}}
end{array}}
ight]$
用Hessian矩阵寻找POI最好用整数特征点区域连续的浮点数特征计算
要近似转换成近似的整数计算如下:
[frac{{{partial ^2}H}}{{partial {x^2}}} = left[ {egin{array}{*{20}{c}}
{{d_{xx}}}&{{d_{yx}}}&{{d_{sx}}}\
{{d_{xy}}}&{{d_{yy}}}&{{d_{sy}}}\
{{d_{xs}}}&{{d_{ys}}}&{{d_{ss}}}
end{array}}
ight]]
$$frac{{partial H}}{{partial x}} = left[ {egin{array}{*{20}{c}}
{{d_x}}\
{{d_y}}\
{{d_z}}
end{array}}
ight]$$
尺度空间如下:中间X表示最大尺度空间
Hessian矩阵在尺度空间寻找关键点:$H(x) = H + frac{{partial {H^T}}}{{partial x}}x + frac{1}{2}{x^T}frac{{{partial ^2}{ m{H}}}}{{partial {x^2}}}x$(拉格朗日泰勒级数展开形式) 求取Hessian矩阵为0时候的x值$hat x = - frac{{{partial ^2}{{ m{H}}^{ - 1}}}}{{partial {x^2}}}frac{{partial H}}{{partial x}}$就是最大值,然后每次移动0.5,不断向这个最大值逼近,这样就在空间尺度找到最大关键点。
旋转不变性:
如图所示,在4$ imes $4的方格中,每隔方格为5$ imes $5的像素,用如图2$ imes $2的Haar在5$ imes $5的像素求取dx,dy,得到每个方向的值,然后所有5$ imes $5内的dx加起来,dy加起来,每个5$ imes $5的区域得到一个向量
[V = { sum {dx,} sum {left| {dx} ight|,} sum {dy,} sum {left| {dy} ight|} } ]
在4$ imes $4的方格中总共有16个向量。
原图如下:
minHessian = 400的特征点如下:
minHessian = 100的特征点如下:
相关函数解释:
static Ptr<SURF> create(double hessianThreshold=100, //hessian关键点检测器的阈值,默认在300-500之间 int nOctaves = 4, //表示在4个尺度空间 int nOctaveLayers = 3, //每个尺度空间的层数 bool extended = false, //扩展描述符标志(true使用扩展的128个元素的描述符,false使用64个元素的描述符) bool upright = false //旋转的特征标志(true不计算方向,false计算方向) ); /****************************************************************/ detect( InputArray image, //图像 vector<KeyPoint>& keypoints,// 检测到的关键点 InputArray mask=noArray() //指定在哪里寻找关键点的掩码(必须是在感兴趣区域中具有非零值的8位整数矩阵) ); /****************************************************************/ drawKeypoints(InputArray image, //源图像 vector<KeyPoint>& keypoints, //来自源图像的关键点 InputOutputArray outImage,//输出图像 const Scalar& color=Scalar::all(-1), //关键点的颜色 int flags=DrawMatchesFlags::DEFAULT //设置绘图功能的标志 );
参考程序如下:
1 #include<opencv2/opencv.hpp> 2 #include<opencv2/xfeatures2d.hpp> 3 #include<iostream> 4 5 using namespace std; 6 using namespace cv; 7 using namespace cv::xfeatures2d; 8 9 int main(int argc, char *argv[]) 10 { 11 Mat src = imread("H:/cv_code/image/home.jpg",0); 12 if(src.empty()) 13 { 14 printf("no image"); 15 return -1; 16 } 17 namedWindow("src",CV_WINDOW_AUTOSIZE); 18 imshow("src", src); 19 //Hessian矩阵 20 int minHessian = 400; 21 Ptr <SURF> detector = SURF::create(minHessian); 22 vector <KeyPoint> keyPoints; 23 detector->detect(src,keyPoints,Mat()); 24 //绘制关键点 25 Mat keyPoint_result; 26 drawKeypoints(src, keyPoints, keyPoint_result, Scalar::all(-1), DrawMatchesFlags::DEFAULT); 27 namedWindow("src",CV_WINDOW_AUTOSIZE); 28 imshow("keyPoint_result", keyPoint_result); 29 30 waitKey(0); 31 return 0; 32 }