OPENCV(python)--初学之路(十六)SURF简介

一前言

今天还是更新了,学无止境吧。

二主要内容

SURF 简介(加速鲁棒特性)

理论

在上一章中,我们看到了使用 SIFT 算法进行特征点的检测和描述。但它相对较慢,人们需要更加快速的算法。 2006 年,Bay,H.,Tuytelaars,T.和 Van Gool,L 三人发表了另一篇论文"SURF:Speeded Up Robust Features",引入了一种名为 SURF 的新算法。顾名思义,它是 SIFT 的加速版本。

在 SIFT 中,Lowe 用高斯差分(DoG)去近似高斯拉普拉斯算子(LoG),从而构造尺度空间。 SURF 则更进一步,用盒子滤波器去近似 LoG。下图显示了这种近似。这种近似的一个很大的优点是,借助积分图像可以很容易地计算出盒子滤波器的卷积,而且可以在不同的尺度空间同时进行计算。同样,SURF 依赖于 Hessian 矩阵的行列式去计算特征点的尺度和位置。

对于主方向,在 SURF 中是对以特征点为中心的 6s(s 为特征点的尺度)为半径的圆形区域内的图像进行 Haar 小波响应运算得到的。使用高斯函数对小波响应进行加权。然后将它们绘制在下图中给出的图像中。通过计算角度为 60 度的定向滑动窗口内的所有响应的总和来估算主方向。有趣的是,任意尺度空间上的小波响应都可以很容易地使用积分图像找到。对于许多应用,不需要旋转不变性,因此无需找到此方向,从而加快了过程。 SURF 提供被称为 Upright-SURF 或 U-SURF 的功能。(其实很简单,SURF是通过削减方向判断从而加快了速度)

旋转的鲁棒性。 OpenCV 支持这两种模式,取决于upright标志位。如果标志位为 0,则计算方向。如果为 1,则不计算方向同时速度更快。

对于特征描述,SURF 在水平和垂直方向上使用小波响应(再次,使用积分图像使事情变得更容易)。在特征点周围获取大小为 20sX20s 的邻域,其中 s 是特征点尺度大小。将它分为 4x4 子区域。对于每个子区域,采用水平和垂直小波响应,并形成一个像这样的矢量,\(\langle v = \sum d_x, \sum d_y, \sum |d_x|, \sum |d_y|\rangle\)。当表示为矢量时,这就是 64 维的 SURF 特征点描述了。(与 SIFT 相比)描述子的维度降低了,计算和匹配的速度提高了,但又提供了更具有独特性的特征。

为了增加特征点的独特性,SURF 特征点描述了具有扩展的 128 维版本。在 \(\langle d_y < 0\rangle\) 和 \(\langle d_y > 0\rangle\) 分别计算 \(\langle d_x\rangle\) 和 \(\langle x^2|d_x^2\rangle\) 的和。类似地,\(|d_y\rangle\) (和 \(|d_x|\)) (的和也根据) \(d_x\) 的符号进行区分,从而使特征数量加倍,但不会增加太多的计算复杂性。OpenCV 支持将 extended 标志位的值分别设置为 0 和 1,0 为 64 维,1 为 128 维(默认为 128 维)。

SURF 采用了许多方法来提高每一步的速度。分析显示在性能相当的情况下它比 SIFT 快 3 倍。 SURF 擅长处理模糊和旋转的图像,但不善于处理视角变化和光照变化。

OpenCV 中的 SURF

OpenCV 就像 SIFT 一样提供 SURF 功能。您使用一些可选参数(如 64/128-dim 描述符,Upright / Normal SURF 等)构造 SURF 对象。所有详细信息都在文档中进行了详细说明。然后就像我们在 SIFT 中所做的那样,我们可以使用 SURF.detect(),SURF.compute()等来查找特征点和描述子。

首先,我们将看到一个关于如何查找 SURF 特征点和描述子并绘制它的简单演示。由于与 SIFT 相同因此所有示例都显示在 Python 终端中。

python 复制代码
import cv2 as cv

# 读取图像,第二个参数0表示以灰度模式读取
img = cv.imread('fly.png', 0)

# 创建SURF对象,设置Hessian阈值为400
# Hessian阈值用于控制特征点检测的灵敏度
# 值越高,检测到的特征点越少但更稳定
surf = cv.xfeatures2d.SURF_create(400)

# 检测关键点并计算描述子
# kp: 关键点列表(包含位置、尺度、方向等信息)
# des: 描述子矩阵(每行是一个特征点的描述向量)
kp, des = surf.detectAndCompute(img, None)

# 打印检测到的关键点数量
print(len(kp))  # 输出:699
 

1199 个关键点太多,无法在图片中显示。我们将它减少到大约 50 以将其绘制在图像上。在匹配时,我们可能需要所有这些功能,但现在不需要。所以我们增加了 Hessian 阈值。

python 复制代码
import cv2

# 读取图像
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 初始化SURF检测器
surf = cv2.xfeatures2d.SURF_create()

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

# 设置新的Hessian阈值
surf.setHessianThreshold(50000)

# 检测关键点和计算描述子
kp, des = surf.detectAndCompute(img, None)

# 输出关键点数量
print(len(kp))
 

关键点数量变化分析

阈值 检测到的关键点数量 说明
400 699个 正常设置,检测到较多特征点
50000 47个 极高阈值,只检测到最显著的特征点

你可以看到 SURF 更像是斑点检测器。它检测到蝴蝶翅膀上的白色斑点

现在我想试一下 U-SURF,不检测特征点的方向。

python 复制代码
import cv2
import matplotlib.pyplot as plt

# 读取图像
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 创建 SURF 对象
surf = cv2.xfeatures2d.SURF_create()

# 检查 upright 标志
print(surf.getUpright())

# 如果 upright 为 False,设置为 True
if not surf.getUpright():
    surf.setUpright(True)

# 重新计算特征点
kp = surf.detect(img, None)

# 绘制特征点
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)

# 显示结果
plt.imshow(img2)
plt.show()
 

效果如下,所有方向都以相同的方向显示。它比以前更快。如果您的工作中不需要检测方向(如全景拼接)等,这种方法更好。

今天的代码最好都在python的编译环境下进行,因为我已经试了很多次了,想在虚拟环境直接运行行不通,是无法运行的。

三最后一语

今天更新少一点,大家多理解之前的内容。

我们终此一生,就是要摆脱他人的期待,找到真正的自己。------ 伍绮诗《无声告白》

感谢观看,共勉!!

相关推荐
brave and determined8 小时前
传感器学习(day04):红外感知:从经典热释电开关到智能时代的隐形慧眼
嵌入式硬件·算法·传感器·红外·嵌入式设计·红外矩阵·人体红外
lxh01138 小时前
合并区间题解
数据结构·算法·leetcode
Q_Q5110082858 小时前
python+django/flask+vue基于深度学习的图书推荐系统
spring boot·python·django·flask·node.js·php
sugar椰子皮8 小时前
【爬虫框架-5】实现一下之前的思路
开发语言·爬虫·python
码界奇点8 小时前
基于Flask与Vue.js的百度网盘自动转存系统设计与实现
vue.js·python·flask·自动化·毕业设计·源代码管理
yongui478348 小时前
基于MATLAB的轴承表面织构油膜参数计算程序
数据结构·算法·matlab
闲人编程8 小时前
Flask扩展开发:从零编写自己的Flask扩展
后端·python·flask·sqlalchemy·config·login·codecapsule
猎板PCB黄浩8 小时前
多层电路板技术深度解析:高密度集成时代的核心支撑
网络·人工智能·算法
leoufung8 小时前
LeetCode 39. Combination Sum 题解(回溯 / DFS)
算法·leetcode·深度优先