SURF(加速增强特征)简介 OpenCV-Python v4.7.0

文章介绍了SURF(SpeededUpRobustFeatures)作为SIFT的加速版本,详细阐述了SURF的理论基础,包括使用箱式滤波器代替高斯差分,Hessian矩阵在确定尺度和位置中的作用,以及小波响应在确定方向和特征描述中的应用。文章还讨论了OpenCV中如何实现SURF功能,包括设置参数如描述符尺寸和直立标志,以及检测和计算关键点的步骤。
摘要由CSDN通过智能技术生成

目标

在本章中

  • 我们将看到SURF的基础知识
  • 我们将看到OpenCV中的SURF功能

理论

在上一章中,我们看到SIFT用于关键点的检测和描述。但它相对较慢,人们需要更多的加速版本。2006年,三个人,Bay, H., Tuytelaars, T.和Van Gool, L,发表了另一篇论文,“SURF: Speeded Up Robust Features”,介绍了一种新的算法,叫做SURF。顾名思义,它是SIFT的一个加速版本。

在SIFT中,Lowe用高斯之差(Difference of Gaussian)近似了高斯的拉普拉斯,以寻找标度空间。SURF走得更远,用箱形滤波器近似于LoG。下面的图片显示了这种近似的演示。这种近似的一大优势是,在积分图像的帮助下,可以很容易地计算出箱式滤波器的卷积。而且它可以在不同的尺度上并行进行。此外,SURF还依靠Hessian矩阵的行列式来确定规模和位置。
在这里插入图片描述
对于方向分配,SURF使用水平和垂直方向上的小波响应,其邻域大小为6s。适当的高斯权重也被应用到它。然后,它们被绘制在一个空间中,如下图所示。通过计算60度的滑动方向窗口内所有反应的总和来估计主导方向。有趣的是,小波响应可以在任何规模下使用积分图像非常容易地被发现。对于许多应用来说,旋转不变性是不需要的,所以不需要找到这个方向,这就加快了进程。SURF提供了这样一种功能,称为Upright-SURF或U-SURF。它提高了速度,并具有高达±15°的稳定性。OpenCV支持这两种功能,这取决于标志,即直立。如果它是0,就会计算方向。如果它是1,则不计算方向,而且速度更快。
在这里插入图片描述
对于特征描述,SURF使用水平和垂直方向的小波响应(同样,使用积分图像使事情更容易)。在关键点周围取一个大小为20sX20s的邻域,其中s为大小。它被划分为4x4个子区域。对于每个子区域,采取水平和垂直小波响应,并形成这样一个矢量 v = ( ∑ d x , ∑ d y , ∑ ∣ d x ∣ , ∑ ∣ d y ∣ ) v=\left( \sum{d_x},\sum{d_y},\sum{\left| d_x \right|},\sum{\left| d_y \right|} \right) v=(dx,dy,dx,dy)

当表示为矢量时,SURF特征描述符共有64维。维数越低,计算和匹配的速度就越快,但能提供更好的特征识别性。

为了使特征更加明显,SURF特征描述符有一个扩展的128维版本。dx和|dx|的总和在dy<0和dy≥0的情况下分别计算。同样地,dy和|dy|的总和根据dx的符号分割,从而使特征的数量增加一倍。这并没有增加多少计算的复杂性。OpenCV支持这两种方法,通过设置标志扩展的值,分别为0对应64-dim和1对应128-dim(默认为128-dim)。

另一个重要的改进是使用拉普拉斯的符号(Hessian矩阵的轨迹)来表示基本兴趣点。它没有增加任何计算成本,因为它已经在检测过程中计算过了。拉普拉斯的符号将黑暗背景上的亮斑与相反情况区分开来。在匹配阶段,我们只比较具有相同类型对比度的特征(如下图所示)。这种最小的信息允许更快的匹配,而不会降低描述符的性能。
在这里插入图片描述
简而言之,SURF增加了很多功能,以提高每一步的速度。分析表明它比SIFT快3倍,而性能与SIFT相当。SURF擅长处理模糊和旋转的图像,但不擅长处理视角变化和光照变化。

OpenCV中的SURF

OpenCV提供SURF功能,就像SIFT一样。你可以用一些可选的条件启动一个SURF对象,如64/128-dim描述符,直立/正常SURF等。所有的细节在文件中都有很好的解释。然后,正如我们在SIFT中所做的那样,我们可以使用SURF.detect()、SURF.compute()等来寻找关键点和描述符。

首先,我们将看到一个关于如何找到SURF关键点和描述符并绘制它的简单演示。所有的例子都是在Python终端上显示的,因为它只是和SIFT一样。

>>> img = cv.imread('fly.png',0)
# 创建SURF对象。你可以在这里或之后指定参数。
# 这里我把Hessian阈值设为400
>>> surf = cv.xfeatures2d.SURF_create(400)
# 直接查找关键点和描述符
>>> kp, des = surf.detectAndCompute(img,None)
>>> len(kp)
 699

1199个关键点太多,无法在图片上显示。我们把它减少到50个左右,在图片上画出来。在匹配时,我们可能需要所有这些特征,但不是现在。所以我们增加Hessian阈值。

# 检查目前的Hessian阈值
>>> print( surf.getHessianThreshold() )
400.0
# 我们把它设置为50000左右。请记住,这只是为了在图片中表示。
# 在实际情况下,最好有一个300-500的值
>>> surf.setHessianThreshold(50000)
# 再次计算关键点并检查其数量。
>>> kp, des = surf.detectAndCompute(img,None)
>>> print( len(kp) )
47

它小于50。让我们把它画在图像上。

>>> img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)
>>> plt.imshow(img2),plt.show()

请看下面的结果。你可以看到,SURF更像是一个blob检测器。它可以检测到蝴蝶翅膀上的白色斑点。你可以用其他图像来测试它。

在这里插入图片描述

# 检查直立标志,如果是假的,就把它设为真。
>>> print( surf.getUpright() )
False
>>> surf.setUpright(True)
# 重新计算特征点并绘制
>>> kp = surf.detect(img,None)
>>> img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)
>>> plt.imshow(img2),plt.show()

请看下面的结果。所有的方向都显示为同一方向。它比以前的快。如果你在处理方向不是问题的情况下(如全景拼接)等,这就更好了。

在这里插入图片描述
最后,我们检查描述符的大小,如果只有64个,就把它改成128。

# 查找描述符的大小
>>> print( surf.descriptorSize() )
64
# 这就意味着旗帜,"extended"是假的。
>>> surf.getExtended()
 False
# 所以我们把它变成 "真",以获得128个描述符。
>>> surf.setExtended(True)
>>> kp, des = surf.detectAndCompute(img,None)
>>> print( surf.descriptorSize() )
128
>>> print( des.shape )
(47, 128)

剩下的部分是匹配,我们将在另一章进行讲述。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值