SURF原理及基于OPENCV实现

写在前面:

六月,沉云湿雨。黄宁然——Time to say goodbye.

参考文献镇楼:

[1]卜珂,基于SURF的图像配准与拼接技术研究
[2]曹君宇,基于SURF的图像拼接算法研究
[3]陈秀芳,基于改进SURF的图像匹配算法研究
[4] SURF特征匹配原理及源代码,https://www.cnblogs.com/urglyfish/p/12460060.html
[5] python使用Opencv的Sift/Surf算法,https://zhuanlan.zhihu.com/p/138152338
[6] python-opencv图像处理之SURF函数,
https://blog.csdn.net/welcome_yu/article/details/105447393

1. 概述

SURF,全称为speed-up robust features,与SIFT算法类似,在各个方面接近或超越SIFT算子,但是速度却是SIFT的3倍[1]。SURF同样具备尺度不变、旋转不变的性能,对光照变化、放射、透视变换具有部分不变性 [1]。
SURF算子,同样需要找兴趣点(SIFT中,称之为关键点),在找到兴趣点之后,确定兴趣点的方向特征,然后在构建特征描述符向量,这一套流程与SIFT算子是类似的。

2. 兴趣点的检测

兴趣点的检测,是检测极值点。SURF兴趣点的检测是基于Hessian矩阵,其原理是:当hessian矩阵行列式为局部最大时,所检测出的实际上是个斑状结构,即比周围区域更亮或更暗的一个小区域(SIFT算子是求DoG的极值)。所以,SURF主要是要求取Hessian矩阵、然后求取hessian矩阵的行列式、然后比较行列式是否为局部最大,即可判定是否为兴趣点。
为了考虑尺度不变性,Hessian矩阵将尺度作为变量之一(在SIFT算子中,也求取了hessian矩阵,并且是关于x,y,σ的三维)。思路与SIFT算子类似,可以理解为将图像使用尺度为sigma的高斯滤波器进行滤波,滤波后的图像再求取x,y方向上的二阶偏导,获得hessian矩阵。实际中,是先求取尺度为sigma的高斯滤波器的二阶偏导矩阵,然后再与图像做卷积,hessian矩阵如下:
在这里插入图片描述
其中,Lxx(X,σ)表示高斯二阶偏到在X处与图像I的卷积,X表示图像坐标(x,y),Lxy、Lyy具有同样的含义。

2.1 Hessian矩阵的简化求取

那么hessian矩阵如何简化求取?

2.1.1 盒状滤波器的使用

首先简化高斯二阶偏导矩阵。鉴于Lowe在用DoG近似LoG时获得的成功,Bay等人直接使用盒状(框状)滤波器去近似高斯二阶偏导。
以尺度sigma=1.2为例(高斯核近似为9×9),如下图所示,上面一行是将高斯二阶微分算子(高斯二阶微分算子是文献2的描述,应该是高斯滤波算子,经过按x、y、xy方向偏导后,得到高斯二阶微分算子)经过离散后,剪切成9×9的小方格,沿着x方向、y方向、xy方向进行离散,即CLxx、CLyy、CLxy模板系数。为简化计算,使用盒状滤波器进行近似,即图中的CDxx、CDyy、CDxy。盒状滤波器中,白色部分为1,灰色部分为0,CDxx、CDyy黑色部分为-2,CDxy黑色部分为-1。
在这里插入图片描述

2.1.2 积分图像的使用

使用盒状滤波器与图像进行卷积滤波,其实就是求取图像指定区域的像素累加和,再乘以系数1或2。为了一劳永逸,首先求取图像的积分图像。
在这里插入图片描述
原始图像中,原点与点X(x,y)形成的矩形区域里面所有像素之和来表示该点的积分面积,
在这里插入图片描述
对于每一点X,均求出及积分面积,便形成积分图像。对于原图中矩形区域ABCD的面积,可以按下式计算:
在这里插入图片描述
其中Sa、Sb、Sc、Sd分别表示A、B、C、D点到原点的积分面积。使用积分图像进行计算时,用3个加减法便可完成计算,且与面积大小无关。这样,便大大减小盒状滤波器与图像的卷积运算。

2.2 Hessian矩阵行列式的求取

盒状滤波器与图像进行卷积运算(过程可见文献[2])得到hessian矩阵的近似,即Dxx、Dyy、Dxy。盒状滤波器虽然会加快运算速度,但是也不可避免的会对正确率产生影响,为减少误差,重新分配Dxy的权重,得到hessian矩阵的行列式[3]:
在这里插入图片描述
在文献2中,w常取0.9。
在文献[2]中描述:如果行列式的值符号为负,那么特征值会出现不同符号,该点就不是局部极值点,排除掉;如果行列式值为正,那么此行列式的两个特征值就同时为正或负,该点就会保留为感兴趣的点。但文献[1]描述,是要寻找hessian矩阵行列式的局部最大值,局部最大时,为兴趣点位置。不解。但是在SIFT算子中,在寻找兴趣点时,行列式大于0也是条件之一。所以猜测,行列式要大于0,然后才有必要去考虑是否为局部最大值(数学底子不好)。
对图像上的每一点,均求取hessian矩阵的行列式,便得到在该尺度σ上的响应图(response map)。
那如何获取不同尺度σ下的响应图?引入尺度空间。

3. 尺度空间

与SIFT算子类似,SURF算子也要求取图像在不同尺度下的响应图,这就要构造尺度空间。尺度空间(scale space)通常用图像金字塔来实现,即通过不同尺度因子的高斯函数与图像进行卷积运算,并结合对图像进行降采样处理,获得更高阶的图像金字塔(SIFT算子就是这样处理的,Lowe通过对图像金子塔的相邻层做差,得到DoG,并在DoG上寻找局部极值点)[1]。
SURF算子则采用不同方法,其直接使用不同尺寸的盒状滤波器对原始图像进行处理(因为使用积分图像,所以不同尺寸的盒状滤波器,计算量是相同的),通过依次增大盒状滤波器的尺寸并与图像进行卷积,得到尺寸空间。举例如下:
在这里插入图片描述
图中,左边盒状滤波器尺寸为9×9,为初始尺度,近似为σ=1.2的高斯2阶偏导滤波器,即此尺度S=1.2。用初始尺度模板与图像做卷积得到的尺度空间为第一层;接下来通过增大模板尺寸,与图像做卷积,得到第二层。为保证模板尺寸的奇数性和中心像素的存在,相邻模板的尺寸总是相差偶数个像素,如白色区域上下各加一行、左右各加一列,这样尺寸由9×9变成15×15。如此依次下去,且每4层为一个阶(Octave)。并有如下规律:第1阶中,相邻模板尺寸相差6像素,第2阶相邻模板相差12像素,第3阶相差24像素。每一阶的第一个模板尺寸是上一阶的第二个模板尺寸。如下表:
在这里插入图片描述
一般取4个octave即足够[1]。
若模板尺寸为N*N,则对应的尺度S=1.2×N/9(参考文献[2],但是在文献[1],似乎分子分母弄反了)。依次用不同尺度的模板对原始图像做卷积,然后使用(式4)计算每一点响应,这样就得到不同尺度σ下的响应图,便构成3维响应图。
在这里插入图片描述

4. 兴趣点的定位

定位与SIFT算子类似。如下图所示。
在这里插入图片描述
在3维度(x,y,S)尺度空间中,在每个3×3×3的局部区域,进行非极大值抑制,对于中心点,只有比周边26个点的响应值都大的点才被选为兴趣点,然后进行插值,得到精确位置。

5. 特征点(兴趣点)的方向分配

与SIFT算子类似,在对特征点定位后,需要进行方向分配。也是结合一定半径内的邻域的点的信息。

5.1 邻域半径

以特征点为圆心,以6S为半径(S为该特征点所在的尺度),获取感兴趣的区域。
使用尺寸为4S的Haar小波模板对的区域图像内的每个点进行处理,求得x、y两个方向的Haar小波响应。Haar小波滤波器如下图所示,其中黑色为-1,白色为1,这便相当于对邻域内的图像进行了梯度响应的求取;并且,同样可以使用积分图像来快捷计算。
在这里插入图片描述
在得到区域内每个点的x、y方向上的梯度响应后,以特征点为中心、使用σ=2S的高斯函数,对每个点的响应进行加权。

5.2 主方向确定

使用圆心角为pi/3的扇形,以特征点为中心,环绕一周,计算该扇形处于每个角度时,它所包括的图像点的haar小波响应之和。由于每个点都有x、y两个方向上的响应,所以扇形区域所有点的响应之和构成一个矢量。把扇形区域环绕一周所形成的矢量都记录下来,取长度最大的矢量,其方向作为特征点的方向[1]。文献[2]描述,扇形环绕的步长为0.2弧度。
在这里插入图片描述
在这里插入图片描述

6. 生成特征描述符

生成描述符时,同样需要使用一定邻域内的点的信息,即需要确定以特征点为中心的邻域。邻域为正方形,边长为20S(S为特征点对应的尺度);将上节确定的特征点的方向,作为该邻域的y轴方向。然后把邻域分成4x4个子块区域[1],每个子区域内有25个像素[2](在文献2的配图中是5Sx5S,文字描述为25个像素,在文献1中,描述的是5x5网格)。对于每一个子块,使用haar小波滤波器进行处理(haar小波模板尺寸为2Sx2S),使用dx表示水平方向的haar小波响应,使用dy表示数值方向的haar小波响应。在构建特征描述符之前,对于所有的dx、dy都要用一个以特征点为中心的高斯函数进行加权,高斯函数的σ=3.3S。对每个子块中的dx、dy、|dx|、|dy|进行求和,这样就得到一个64维的向量。如果在对dx、|dx|求和时,分成dy<0和dy>=0两种情况,同时,在对dy、|dy|求和时,分成dx<0和dx>=0两种情况,就会得到128维的向量。这就是所谓的SURF-64和SURF-128。
128维比64维具有更好的独特性,且计算速度并无太大差别,但是在匹配阶段,128维匹配耗时明显大于64维向量匹配耗时。
在这里插入图片描述
另外,据文献1描述,在程序实现中,并不是通过旋转图像来实现上述计算,因为旋转为降低计算效率。直接使用haar小波滤波器对原始图像进行处理,然后对所得响应进行插值处理。

7. 特征点匹配

7.1 基于最近距离比次近距离的匹配方法

需要求取距离。假设PA是图像A中的任意一点,PB是图像B中的任意一点,他们的描述特征符分量分别为DescrA和DescrB,其第i个分量分别为DescrAi和DescrBi。
则PA和PB的距离定义为:
在这里插入图片描述
据文献1描述,若直接求最短距离,会有如下问题:
在这里插入图片描述
与SIFT算子类似,采用lowe的办法。
在这里插入图片描述
意思就是,最近距离与次近距离要能拉的开。

7.2 用hessian矩阵的正负性加速

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

8. 基于opencv-python实现

由于sift算法的专利问题,部分opencv版本的Sift/Surf算法无法使用,即无法调用。Opencv高版本中不支持SURF算子。欲使用SURF算子,需要将opencv版本降低:
opencv-python:3.4.2.16
opencv-contrib-python:3.4.2.16
代码也比较简单,如下:

img_src1 = cv2.imread('box.png',-1)
img_src2 = cv2.imread('box_in_scene.png', -1)
#
surf = cv2.xfeatures2d.SURF_create(500)
kp1, des1 = surf.detectAndCompute(img_src1, None)
kp2, des2 = surf.detectAndCompute(img_src2, None)

image1 = None
img_kp1 = cv2.drawKeypoints(image=img_src1, keypoints=kp1, outImage=None, color=(255, 0, 255),
                     flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
img_kp2 = cv2.drawKeypoints(img_src2,kp2,None,(255,0,255),4)

pt_flag = 1
reu_img = do_match(img_src1, kp1, des1, img_src2, kp2, des2, embed=1, pt_flag=pt_flag,MIN_MATCH_COUNT=3)
cv2.imshow('reu',reu_img)

其中,do_match函数请参考sift的帖子。

9. 其它

220531,HNR:“日后随机”。
So,time to say goodbye.

猜你喜欢

转载自blog.csdn.net/xiaohuolong1827/article/details/125091151
今日推荐