![]() |
OpenCV 4.12.0
开源计算机视觉
|
在本章中,
在上一章中,我们了解了用于关键点检测和描述的 SIFT。但它相对较慢,人们需要更快的版本。2006 年,Bay, H.、Tuytelaars, T. 和 Van Gool, L 三人发表了另一篇论文“SURF:加速稳健特征”,其中介绍了一种名为 SURF 的新算法。顾名思义,它是 SIFT 的加速版本。
在 SIFT 中,Lowe 使用高斯差分来近似高斯拉普拉斯算子,以寻找尺度空间。SURF 更进一步,使用盒式滤波器近似 LoG。下图显示了这种近似的演示。这种近似的一个巨大优势是,借助积分图像可以轻松计算与盒式滤波器的卷积。并且可以并行针对不同的尺度进行计算。此外,SURF 依赖于 Hessian 矩阵的行列式来确定尺度和位置。
对于方向分配,SURF 在大小为 6s 的邻域中使用水平和垂直方向的小波响应。还应用了适当的高斯权重。然后将它们绘制在如下面的图像中给出的空间中。通过计算 60 度角的滑动方向窗口内的所有响应之和来估计主要方向。有趣的是,可以使用积分图像在任何尺度上非常容易地找出小波响应。对于许多应用来说,不需要旋转不变性,因此不需要找到这个方向,这加快了处理速度。SURF 提供了一种名为 Upright-SURF 或 U-SURF 的功能。它可以提高速度,并且对于 \(\pm 15^{\circ}\) 是稳健的。OpenCV 支持这两种模式,具体取决于标志 upright。如果它为 0,则计算方向。如果它为 1,则不计算方向,并且速度更快。
对于特征描述,SURF 使用水平和垂直方向的小波响应(同样,积分图像的使用使事情变得更容易)。在关键点周围取一个大小为 20sX20s 的邻域,其中 s 是大小。它被分成 4x4 个子区域。对于每个子区域,获取水平和垂直小波响应,并形成如下向量,\(v=( \sum{d_x}, \sum{d_y}, \sum{|d_x|}, \sum{|d_y|})\)。当表示为向量时,它给出了具有总共 64 维的 SURF 特征描述符。维度越低,计算和匹配的速度越快,但提供更好的特征区分度。
为了获得更强的区分度,SURF 特征描述符具有扩展的 128 维版本。分别针对 \(d_y < 0\) 和 \(d_y \geq 0\) 计算 \(d_x\) 和 \(|d_x|\) 的总和。类似地,\(d_y\) 和 \(|d_y|\) 的总和根据 \(d_x\) 的符号进行拆分,从而使特征数量加倍。它没有增加太多计算复杂度。OpenCV 通过将标志 extended 的值设置为 0 和 1 分别支持 64 维和 128 维(默认值为 128 维)
另一个重要的改进是使用拉普拉斯算子的符号(Hessian 矩阵的迹)作为底层兴趣点。它不会增加计算成本,因为它已经在检测期间计算过了。拉普拉斯算子的符号区分了深色背景上的明亮斑点与相反的情况。在匹配阶段,我们仅比较具有相同对比度类型的特征(如下面的图像所示)。这种最小的信息允许更快的匹配,而不会降低描述符的性能。
简而言之,SURF 添加了许多功能以提高每个步骤的速度。分析表明,它比 SIFT 快 3 倍,而性能与 SIFT 相当。SURF 擅长处理模糊和旋转的图像,但不擅长处理视点变化和光照变化。
OpenCV 提供了与 SIFT 类似的功能。您可以初始化一个 SURF 对象,其中包含一些可选条件,例如 64/128 维描述符、Upright/Normal SURF 等。所有细节都在文档中得到了很好的解释。然后,正如我们在 SIFT 中所做的那样,我们可以使用 SURF.detect()、SURF.compute() 等来查找关键点和描述符。
首先,我们将看到一个简单的演示,演示如何查找 SURF 关键点和描述符并绘制它。所有示例都在 Python 终端中显示,因为它与 SIFT 相同。
1199 个关键点太多,无法在图片中显示。我们将其减少到大约 50 个,以将其绘制在图像上。匹配时,我们可能需要所有这些特征,但现在不需要。所以我们增加了 Hessian 阈值。
它小于 50。让我们将其绘制在图像上。
请参阅下面的结果。您可以看到 SURF 更像是一个斑点检测器。它检测蝴蝶翅膀上的白色斑点。您可以使用其他图像对其进行测试。
现在我想应用 U-SURF,这样它就不会找到方向。
请参阅下面的结果。所有方向都显示在同一方向上。它比以前更快。如果您正在处理方向不是问题的案例(如全景拼接)等,则此方法更好。
最后,我们检查描述符大小,如果它只有 64 维,则将其更改为 128。
剩余部分是匹配,我们将在另一章中进行。