当前位置:   article > 正文

OpenCV-Python——第27章:SURF特征点提取算法_cv2.xfeatures2d.surf_create

cv2.xfeatures2d.surf_create

注意:

本章使用的是opencv-contrib-python的3.4.2.16版本,安装过程如下:

pip uninstall opencv-python

pip install opencv-contrib-python==3.4.2.16

目录

0 原理        1 OpenCV 中的 SURF        2 举例


0 原理

在上一节中我们学习了使用 SIFT 算法进行关键点检测和描述。但是这种算法的执行速度比较慢,人们需要速度更快的算法。在 2006 年 Bay,H.,Tuytelaars,T. 和 Van Gool,L 共同提出了 SURF(加速稳健特征) 算法。跟它的名字一样,这是个算法是加速版的 SIFT。

基本步骤:

  1. 构建Hessian矩阵构造高斯金字塔尺度空间 
  2. 利用非极大值抑制初步确定特征点 
  3. 精确定位极值点 
  4. 选取特征点的主方向
  5. 构造surf特征点描述算子

在SIFT中,Lowe在构建尺度空间时使用DoG对LoG进行近似。SURF使用盒子滤波器(box_filter)对 LoG 进行近似。下图显示了这种近似。在进 行卷积计算时可以利用积分图像(积分图像的一大特点是:计算图像中某个窗 口内所有像素和时,计算量的大小与窗口大小无关),是盒子滤波器的一大优点。而且这种计算可以在不同尺度空间同时进行。同样 SURF 算法计算关键点 的尺度和位置是也是依赖与 Hessian 矩阵行列式的。

为了保证特征矢量具有选装不变形,需要对于每一个特征点分配一个主要方向。需要以特征点为中心,以 6s(s 为特征点的尺度)为半径的圆形区域 内,对图像进行 Harr 小波相应运算。这样做实际就是对图像进行梯度运算, 但是利用积分图像,可以提高计算图像梯度的效率,为了求取主方向值,需要设计一个以方向为中心,张角为 60 度的扇形滑动窗口,以步长为 0.2 弧度 左右旋转这个滑动窗口,并对窗口内的图像 Haar 小波的响应值进行累加。主 方向为最大的 Haar 响应累加值对应的方向。在很多应用中根本就不需要旋转 不变性,所以没有必要确定它们的方向,如果不计算方向的话,又可以使算法 提速。SURF 提供了成为 U-SURF 的功能,它具有更快的速度,同时保持了 对 +/-15 度旋转的稳定性。OpenCV 对这两种模式同样支持,只需要对参数upright 进行设置,当 upright 为 0 时计算方向,为 1 时不计算方向,同时速度更快。

生成特征点的特征矢量需要计算图像的 Haar 小波响应。在一个矩形的区域内,以特征点为中心,沿主方向将 20s*20s 的图像划分成 4*4 个子块,每 个子块利用尺寸 2s 的 Haar 小波模版进行响应计算,然后对响应值进行统计, 组成向量 v = (
∑ dx, ∑ dy, ∑ |dx|, ∑ |dy|)。这个描述符的长度为 64。降低的维度可以加速计算和匹配,但又能提供更容易区分的特征。

为了增加特征点的独特性,SURF 还提供了一个加强版 128 维的特征描述符。当 dy 大于 0 和小于 0 时分别对 dx 和 |dx| 的和进行计算,计算 dy 和 |dy| 时也进行区分,这样获得特征就会加倍,但又不会增加计算的复杂度。 OpenCV 同样提供了这种功能,当参数 extended 设置为 1 时为 128 维,当 参数为 0 时为 64 维,默认情况为 128 维。

在检测特征点的过程中计算了 Hessian 矩阵的行列式,与此同时,计算得到了 Hessian 矩阵的迹,矩阵的迹为对角元素之和。

按照亮度的不同,可以将特征点分为两种,第一种为特征点迹其周围小邻域的亮度比背景区域要亮,Hessian 矩阵的迹为正;另外一种为特征点迹其周 围小邻域的亮度比背景区域要暗,Hessian 矩阵为负值。根据这个特性,首先 对两个特征点的 Hessian 的迹进行比较。如果同号,说明两个特征点具有相同 的对比度;如果异号的话,说明两个特征点的对比度不同,放弃特征点之间的 后续的相似性度量。

对于两个特征点描述子的相似性度量,我们采用欧式距离进行计算。

简单来说 SURF 算法采用了很多方法来对每一步进行优化从而提高速度。分析显示在结果效果相当的情况下 SURF 的速度是 SIFT 的 3 倍。SURF 善 于处理具有模糊和旋转的图像,但是不善于处理视角变化和关照变化。

与SIFT比较:

 SIFTSURF
尺度空间DOG与不同尺度的图片卷积不同尺度的box filters与原图片卷积
特征点检测先进行非极大抑制,再去除低对比度 点。再通过Hessian矩阵去除边缘的点先利用Hessian矩阵确定候选点,然 后进行非极大抑制
方向在正方形区域内统计梯度的幅值的直方图,找max对应的方向。可以有多个方向。在圆形区域内,计算各个扇形范围内 X、y方向的haar小波响应,找模最大的扇形方向
特征描述子16x16的采样点划分为4x4的区域, 计算每个区域的采样点的梯度方向和 幅值,统计成8bin直方图,一共 4x4x8=128维20x20s的区域划分为4x4的子区域, 每个子区域找5x5个采样点,计算采样 点的haar小波响应,记录Σdx, Σdy,Σ|dx|,Σ|dy|, —共 4x4x4=64

 

1 OpenCV 中的 SURF

与 SIFT 相同 OpenCV 也提供了 SURF 的相关函数。首先我们要初始化一个 SURF 对象,同时设置好可选参数:64/128 维描述符,Upright/ Normal 模式等。所有的细节都已经在文档中解释的很明白了。就像我们在 SIFT 中一样,我们可以使用函数 SURF.detect(),SURF.compute() 等 来进行关键点搀着和描述。

创建一个SURF对象:

cv2.xfeatures2d.SURF_create(, hessianThreshold, nOctaves, nOctaveLayers, extended, upright)

  • hessianThreshold:默认100关键点检测的阈值,越高监测的点越少
  • nOctaves:默认4,金字塔组数
  • nOctaveLayers:默认3,每组金子塔的层数
  • extended:默认False,扩展描述符标志,True表示使用扩展的128个元素描述符,False表示使用64个元素描述符。
  • upright:默认False,垂直向上或旋转的特征标志,True表示不计算特征的方向,False-计算方向。

之后也可以通过类似getHessianThreshold(),setHessianThreshold()等函数来获取或修改上述参数值,例如

surf.setHessianThreshold(True)表示将HessianThreshold参数修改为True。

绘制特征点:

cv2.drawKeypoint(image, keypoints, outImage, color, flags)

或:outImage = cv2.drawKeypoint(image, keypoints, None, color, flags)

  • image:输入图像
  • keypoints:上面获取的特征点
  • outImage:输出图像
  • color:颜色,默认为随机颜色
  • flags:绘制点的模式,有以下四种模式

cv2.DRAW_MATCHES_FLAGS_DEFAULT

默认值,只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标。

cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS

绘制特征点的时候绘制的是带有方向的圆,这种方法同时显示图像的坐标,size,和方向,是最能显示特征的一种绘制方式。

cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG

只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标。

cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINT

 单点的特征点不被绘制 

2 举例

程序如下:

  1. import numpy as np
  2. import cv2
  3. import matplotlib.pyplot as plt
  4. img = cv2.imread('test32.jpg', 0)
  5. surf = cv2.xfeatures2d.SURF_create(30000)
  6. kp = surf.detect(img, None)
  7. img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)
  8. # 不检查关键点的方向
  9. surf.setUpright(True)
  10. # 修改阈值
  11. surf.setHessianThreshold(40000)
  12. kp = surf.detect(img, None)
  13. img3 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)
  14. plt.subplot(121), plt.imshow(img2),
  15. plt.title('Dstination'), plt.axis('off')
  16. plt.subplot(122), plt.imshow(img3),
  17. plt.title('Dstination'), plt.axis('off')
  18. plt.show()

结果如下:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/81215
推荐阅读
相关标签
  

闽ICP备14008679号