OpenCV中的SURF(Speeded-Up Robust Features 加速鲁棒特征)

Posted 程序媛一枚~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV中的SURF(Speeded-Up Robust Features 加速鲁棒特征)相关的知识,希望对你有一定的参考价值。

上一篇博客介绍了用于关键点检测和描述的SIFT,但它相对较慢,这篇博客将介绍其优化版本——SURF(Speeded-Up Robust Features 加速鲁棒特征),它是加速版的SIFT;

  • 在SIFT中,Lowe用高斯差分近似高斯的拉普拉斯算子来寻找尺度空间。
  • SURF借助于积分图像,可以很容易地计算带盒滤波器的卷积。并行计算不同的尺度。此外,SURF还依赖于规模和位置的Hessian矩阵行列式。
  • SURF增加了许多功能以提高每一步的速度。它比SIFT快3倍,而性能与SIFT相当。
  • SURF擅长处理模糊和旋转的图像,但不擅长处理视点变化和照明变化。

1. 效果图

SURF默认参数效果图如下:

检查到的关键点比较多,把原图覆盖完了。

SURF调整阈值,检查到关键点近50个,效果图如下:

使用U-SURF不计算方向,方向全为一个,SURF关键点效果图如下:

默认以64D计算效果图如上,调整为128D,U-SURF效果图如下:基本没差别

2. 原理

OpenCV使用 SURF.detect()、SURF.compute()等来查找关键点和描述符。

2.1 为什么SURF比SIFT快?

  • 在任何尺度下,利用积分图像都可以很容易地发现小波响应。
  • 不考虑旋转不变形,因此不需要找到方向会加快过程。
  • SURF提供了一种称为Upright-SURF或U-SURF的功能。它提高了速度,±15°之间非常健壮。
  • OpenCV支持Upright-SURF、U-SURF,具体取决于标志。如果为0,则计算方向。如果为1,则不计算方向,速度更快。
  • 维数越低,计算和匹配的速度越快,但特征的显著性越好。OpenCV通过分别为64 dim和128 dim设置扩展为0和1的标志值(默认值为128 dim)来支持这两种功能
  • 另一个重要的改进是对潜在兴趣点使用拉普拉斯符号(Hessian矩阵的轨迹)。它不增加计算成本。拉普拉斯符号将黑暗背景上的明亮斑点与相反情况区分开来。
  • 在匹配阶段,只比较具有相同对比度的特征(如下图所示)。这种最小的信息允许更快的匹配,而不会降低描述符的性能。

2.3 怎样获取SIFT与SURF?

SIFT、SURF是有专利的算法,在OpenCV3.0以上时已去除。移到了opencv-contrib-python版本中。所以有以下方法可以获取:
1)安装opencv3以下版本
2)卸载opencv3以上版本,opencv-contrib-python安装指定版本
3)安装opencv3以上版本,安装opencv-contrib-python,源码编译安装opencv;

综上方法2更方便可行,只需要俩步:

  1. 卸载opencv-python
  2. 安装指定版本opencv-contrib-python==3.4.2.17
pip uninstall opencv-python

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.2.17

可以看到成功了

3. 源码

# 寻找SURF关键点和描述符并绘制
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('images/butterfly.jpg', 0)

# 创建SURF对象,可以在创建时指定参数也可以稍后设置参数
# 此处设置 Hessian阈值为 400
sift = cv2.xfeatures2d.SIFT_create()
print('sift: ', sift)
surf = cv2.xfeatures2d.SURF_create()
print('surf: ', surf,
      ' \\ndefaultParameter\\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

# 寻找SURF关键点和描述符
# kp:返回的关键点列表,des:numpy数组
kp, des = surf.detectAndCompute(img, None)
# 绘制关键点在图片上
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)
plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('more keypoints'), plt.show()

print('keypoints: ', len(kp))

# 检查当前Hessian阈值
# print(surf.getHessianThreshold())

# 调整Hessian阈值,此处设置为50000,但一般最佳设置为300~500
surf.setHessianThreshold(50000)
print(' parameters\\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

# 再一次计算关键点和描述符
kp, des = surf.detectAndCompute(img, None)

print('keypoints: ', len(kp))

# 绘制关键点在图片上
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)

plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('less than 50 keypoints'), plt.show()

# U-SURF不会计算方向
# print(surf.getUpright())
surf.setUpright(True)
print(' parameters\\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

# 重新计算关键点和描述符,并绘制
kp = surf.detect(img, None)
print('keypoints: ', len(kp))
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)

plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('U-SURF'), plt.show()

# 所有方向显示在同一方向,它比以前快多了。如果您正在处理方向不成问题的情况(如全景缝合)等,使用U-SURF会更好。
# 寻找描述符的大小
# print(surf.descriptorSize())
# extended为false,默认为64D
# print(surf.getExtended())

# 设置描述符为128D
surf.setExtended(True)
print(' parameters\\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

kp, des = surf.detectAndCompute(img, None)
print('keypoints: ',len(kp))
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)

plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('128D res'), plt.show()

参考

以上是关于OpenCV中的SURF(Speeded-Up Robust Features 加速鲁棒特征)的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV——SURF特征检测与匹配

OpenCV Sift/Surf/Orb:drawMatch 功能无法正常工作

在 openCV 中查找 SURF 的精确匹配

尝试从 OpenCV 使用 SURF 时出现 java.lang.UnsatisfiedLinkError

OpenCV竟然可以这样学!成神之路终将不远(三十六)

OpenCV:从用户定义的关键点中提取 SURF 特征