OpenCV-Python 系列 三十九 | SURF简介(加速的强大功能)
本文是全系列中第29 / 63篇:OpenCV-Python
- OpenCV-Python 系列 四 | 视频入门
- OpenCV-Python 系列 十二 | 图像的几何变换
- OpenCV-Python 系列 二十 | 轮廓:入门
- OpenCV-Python 系列 二十八 | 直方图4:直方图反投影
- OpenCV-Python 系列 三十六 | 哈里斯角检测
- OpenCV-Python 系列 四十四 | 特征匹配 + 单应性查找对象
- OpenCV-Python 系列 五十二 | 理解K近邻
- OpenCV-Python 系列 六十 | 高动态范围
- OpenCV-Python 系列 五 | OpenCV中的绘图功能
- OpenCV-Python 系列 十三 | 图像阈值
- OpenCV-Python 系列 二十一 | 轮廓特征
- OpenCV-Python 系列 二十九 | 傅里叶变换
- OpenCV-Python 系列 三十七 | Shi-tomas拐角检测器和益于跟踪的特征
- OpenCV-Python 系列 四十五 | 如何使用背景分离方法
- OpenCV-Python 系列 五十三 | 使用OCR手写数据集运行KNN
- OpenCV-Python 系列 六十一 | 级联分类器
- OpenCV-Python 系列 六 | 鼠标作为画笔
- OpenCV-Python 系列 十四 | 图像阈值
- OpenCV-Python 系列 二十二 | 轮廓属性
- OpenCV-Python 系列 三十 | 模板匹配
- OpenCV-Python 系列 三十八 | SIFT尺度不变特征变换
- OpenCV-Python 系列 四十六 | Meanshift和Camshift
- OpenCV-Python 系列 五十四 | 理解SVM
- OpenCV-Python 系列 六十二 | 级联分类器训练
- OpenCV-Python 系列 七 | 轨迹栏作为调色板
- OpenCV-Python 系列 十五 | 图像平滑
- OpenCV-Python 系列 二十三 | 轮廓:更多属性
- OpenCV-Python 系列 三十一 | 霍夫线变换
- OpenCV-Python 系列 三十九 | SURF简介(加速的强大功能)
- OpenCV-Python 系列 四十七 | 光流
- OpenCV-Python 系列 五十五 | 使用OCR手写数据集运行SVM
- OpenCV-Python 系列 六十三 | OpenCV-Python Bindings 如何工作?
- OpenCV-Python 系列 八 | 图像的基本操作
- OpenCV-Python 系列 十六 | 形态学转换
- OpenCV-Python 系列 二十四 | 轮廓分层
- OpenCV-Python 系列 三十二 | 霍夫圈变换
- OpenCV-Python 系列 四十 | 用于角点检测的FAST算法
- OpenCV-Python 系列 四十八 | 相机校准
- OpenCV-Python 系列 五十六 | 理解K-Means聚类
- OpenCV-Python 系列 一 | 系列简介与目录
- OpenCV-Python 系列 九 | 图像上的算术运算
- OpenCV-Python 系列 十七 | 图像梯度
- OpenCV-Python 系列 二十五 | 直方图-1:查找、绘制和分析
- OpenCV-Python 系列 三十三 | 图像分割与Watershed算法
- OpenCV-Python 系列 四十一 | BRIEF(二进制的鲁棒独立基本特征)
- OpenCV-Python 系列 四十九 | 姿态估计
- OpenCV-Python 系列 五十七 | OpenCV中的K-Means聚类
- OpenCV-Python 系列 二 | 安装OpenCV-Python
- OpenCV-Python 系列 十 | 性能衡量和提升技术
- OpenCV-Python 系列 十八 | Canny边缘检测
- OpenCV-Python 系列 二十六 | 直方图-2:直方图均衡
- OpenCV-Python 系列 三十四 | 交互式前景提取使用GrabCut算法
- OpenCV-Python 系列 四十二 | ORB(面向快速和旋转的BRIEF)
- OpenCV-Python 系列 五十 | 对极几何
- OpenCV-Python 系列 五十八 | 图像去噪
- OpenCV-Python 系列 三 | 图像入门
- OpenCV-Python 系列 十一 | 改变颜色空间
- OpenCV-Python 系列 十九 | 图像金字塔
- OpenCV-Python 系列 二十七 | 直方图-3:二维直方图
- OpenCV-Python 系列 三十五 | 理解特征
- OpenCV-Python 系列 四十三 | 特征匹配
- OpenCV-Python 系列 五十一 | 立体图像的深度图
- OpenCV-Python 系列 五十九 | 图像修补
目标
在这一章当中,
– 我们将了解SURF的基础
– 我们将在OpenCV中看到SURF函数
理论
在上一章中,我们看到了SIFT用于关键点检测和描述符。但相对缓慢,人们需要更多的加速版本。2006年,三个人,H .Tuytelaars,T. and Van Gool,L,发表了另一篇论文,“SURF:加速健壮的特征”,引入了一种名为“SURF”的新算法。正如名字所表明的那样,它是一个加速版本的SIFT。
在SIFT中,Lowe用高斯差近似高斯的拉普拉斯算子来寻找尺度空间。SURF走得更远,使用Box Filter近似LoG。下图显示了这种近似值的演示。这种近似的一大优点是,借助积分图像可以轻松地计算出带盒滤波器的卷积。并且可以针对不同规模并行执行。SURF还依赖于Hessian矩阵的行列式来确定尺度和位置。
对于方向分配,SURF在水平和垂直方向上对大小为6s的邻域使用小波响应。适当的高斯权重也适用于它。然后将它们绘制在下图所示的空间中。通过计算角度为60度的滑动方向窗口内所有响应的总和,可以估算主导方向。有趣的是,小波响应可以很容易地使用积分图像在任何规模下发现。对于许多应用,不需要旋转不变性,因此无需查找此方向,从而加快了过程。SURF提供了称为Upright-SURF或U-SURF的功能。它提高了速度,并具有高达$pm 15^{circ}$的鲁棒性。OpenCV根据标志支持两种方式。如果为0,则计算方向。如果为1,则不计算方向并且速度更快。
对于功能描述,SURF在水平和垂直方向上使用小波响应(同样,使用积分图像使事情变得更容易)。在s是大小的关键点周围采用大小为20sX20s的邻域。它分为4×4子区域。对于每个子区域,获取水平和垂直小波响应,并像这样形成向量,$v =(sum dx,sum dy,sum |dx|,sum |dy|)$。当表示为向量时,这将为SURF特征描述符提供总共64个维度。尺寸越小,计算和匹配速度越快,但特征的区分性更好。
为了更加独特,SURF特征描述符具有扩展的128维版本。dx和$|dx|$的和分别针对$dy<0$和$dy≥0$进行计算。同样,$dy$和$|dy|$的总和 根据$dx$的符号进行拆分,从而使特征数量加倍。它不会增加太多的计算复杂性。OpenCV通过将分别为64-dim和128-dim(默认值为128-dim)的标志的值设置为0和1来支持这两者(默认为128-dim)。
另一个重要的改进是对基础兴趣点使用了Laplacian算符(海森矩阵的迹)。它不增加计算成本,因为它已在检测期间进行了计算。拉普拉斯算子的标志将深色背景上的明亮斑点与相反的情况区分开。在匹配阶段,我们仅比较具有相同对比类型的特征(如下图所示)。这些最少的信息可加快匹配速度,而不会降低描述符的性能。
简而言之,SURF添加了许多功能来提高每一步的速度。分析表明,它的速度是SIFT的3倍,而性能却与SIFT相当。SURF擅长处理具有模糊和旋转的图像,但不擅长处理视点变化和照明变化。
OpenCV中的SURF
OpenCV提供类似于SIFT的SURF功能。您可以使用一些可选条件(例如64 / 128-dim描述符,Upright / Normal SURF等)来启动SURF对象。所有详细信息在docs中都有详细说明。然后,就像在SIFT中所做的那样,我们可以使用SURF.detect(),SURF.compute()等来查找关键点和描述符。
首先,我们将看到一个有关如何找到SURF关键点和描述符并进行绘制的简单演示。所有示例都在Python终端中显示,因为它与SIFT相同。
>>> img = cv.imread('fly.png',0)
# 创建SURF对象。你可以在此处或以后指定参数。
# 这里设置海森矩阵的阈值为400
>>> surf = cv.xfeatures2d.SURF_create(400)
# 直接查找关键点和描述符
>>> kp, des = surf.detectAndCompute(img,None)
>>> len(kp)
699
图片中无法显示1199个关键点。我们将其减少到50左右以绘制在图像上。匹配时,我们可能需要所有这些功能,但现在不需要。因此,我们增加了海森阈值。
# 检查海森矩阵阈值
>>> 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更像是斑点检测器。它检测到蝴蝶翅膀上的白色斑点。您可以使用其他图像进行测试。
现在,我想应用U-SURF,以便它不会找到方向。
# 检查flag标志,如果为False,则将其设置为True
>>> 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
# 表示flag “extened” 为False。
>>> surf.getExtended()
False
# 因此,将其设为True即可获取128个尺寸的描述符。
>>> surf.setExtended(True)
>>> kp, des = surf.detectAndCompute(img,None)
>>> print( surf.descriptorSize() )
128
>>> print( des.shape )
(47, 128)
其余部分是匹配的,我们将在另一章中进行匹配。
原创文章,作者:磐石,如若转载,请注明出处:https://panchuang.net/2020/03/26/opencv-python-%e7%b3%bb%e5%88%97-%e4%b8%89%e5%8d%81%e4%b9%9d-surf%e7%ae%80%e4%bb%8b%ef%bc%88%e5%8a%a0%e9%80%9f%e7%9a%84%e5%bc%ba%e5%a4%a7%e5%8a%9f%e8%83%bd%ef%bc%89/