文章目录
- 0 引言
- 1 SIFT算法
- 1.1 主要目的
- 1.2 主要步骤
- 1.3 示例代码
- 2 SURF算法
- 2.1 主要目的
- 2.2 主要步骤
- 2.3 示例代码
- 3 ORB算法
- 3.1 主要步骤
- 3.2 代码示例
- 4 三者对比
0 引言
本文主要对SIFT
、SURF
和ORB
特征点检测和描述算法进行详细的学习和比较。
⚠️ ⚠️ ⚠️ :SIFT、SURF是有专利保护的算法,在
opencv-contrib-python=3.4.3
之后专利收费,可用anaconda
创建一个临时环境,安装指定版本来测试:pip install opencv-contrib-python==3.4.2.17
1 SIFT算法
SIFT
(Scale-Invariant Feature Transform
) 是一种计算机视觉算法,用于检测和描述图像中的局部特征。SIFT
算法由 David Lowe
在 1999
年提出,并在 👉 2004年的论文中详细描述。
1.1 主要目的
SIFT
算法的主要目标是提取图像中的关键点,这些关键点在不同尺度和旋转下都具有不变性。它在图像中寻找具有稳定特征的局部极值点,并计算这些关键点的描述子。这些描述子可以用于在不同图像之间进行特征匹配,从而实现图像识别、目标跟踪等应用。
1.2 主要步骤
SIFT
算法的主要步骤如下:
-
尺度空间极值检测(
Scale-space extrema detection
):通过在图像的不同尺度上应用高斯差分(Gaussian difference-of-Gaussian
)进行滤波,检测图像中的极值点。这些极值点通常对应于图像中的边缘、角点等关键位置。 -
关键点定位(
Keypoint localization
):通过在尺度空间中对极值点进行精确定位,排除低对比度和边缘响应不明确的关键点。SIFT
算法使用了尺度空间的极值点的曲率来过滤掉不稳定的关键点。 -
方向分配(
Orientation assignment
):为每个关键点分配一个主方向,用于后续计算关键点的描述子。这样可以使描述子对旋转变换具有不变性。 -
关键点描述(
Descriptor computation
):根据关键点的尺度和方向,计算关键点周围区域的描述子。描述子通常使用关键点周围的梯度方向直方图表示,具有一定的独特性和不变性。
1.3 示例代码
由于OpenCV
库中已经有对应的SIFT
算法接口,直接调用即可,如下python
代码:
import cv2
# 加载图像
image = cv2.imread('liuyf.jpg')
# 创建 SIFT 对象
sift = cv2.xfeatures2d.SIFT_create()
# 检测关键点和计算描述子
keypoints, descriptors = sift.detectAndCompute(image, None)
# 绘制关键点
image_with_keypoints = cv2.drawKeypoints(image, keypoints, None)
# 保存图像
cv2.imwrite('image_with_sift.jpg', image_with_keypoints)
# 显示图像
cv2.imshow('Image with Keypoints', image_with_keypoints)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上述代码中输入左图,输出右图,主要调用了cv2.xfeatures2d.SIFT_create()
创建SIFT
对象,然后调用sift.detectAndCompute(image, None)
检测关键点和计算描述子。
SIFT
算法的主要优点是其对尺度、旋转、仿射变换等具有较好的不变性,使得它在图像匹配、目标识别和三维重建等领域具有广泛的应用。然而,SIFT
算法计算量较大,不适用于实时应用,后续也出现了一些更快的替代算法,如SURF
(Speeded Up Robust Features
)和ORB
(Oriented FAST and Rotated BRIEF
)。
2 SURF算法
SURF
(Speeded Up Robust Features
) 是一种基于 SIFT
算法的改进版本,它在计算效率和描述子的稳健性方面进行了优化。SURF
算法由 Herbert Bay
等人于 2006
年提出,并发表👉 SURF论文。
2.1 主要目的
与 SIFT
算法相比,SURF
算法主要改进了以下两个方面:
-
尺度空间极值检测:
SURF
算法使用快速Hessian
矩阵(Fast Hessian
)来检测图像中的尺度空间极值点。相比之下,SIFT
算法使用高斯差分金字塔来检测极值点,而快速Hessian
矩阵能够更快地计算图像的尺度空间。 -
描述子计算:
SURF
算法使用了一种加速技术称为积分图像(Integral Image
),用于快速计算关键点周围区域的梯度和特征描述子。这种技术可以显著加快计算速度。
由于 SURF
算法对尺度、旋转和仿射变换具有较好的不变性,并且计算速度更快,因此在实际应用中得到了广泛的应用。与 SIFT
算法相比,SURF
算法在实时性要求较高的场景下更加适用。
2.2 主要步骤
SURF
算法的主要步骤可以概括为以下几个阶段:
-
尺度空间构建:首先,对输入图像进行尺度空间构建。这通常涉及使用高斯滤波器构建图像的金字塔,通过不同尺度的图像来检测不同尺度的特征。
-
关键点检测:在每个尺度的图像中,使用
Hessian
矩阵计算特征点的兴趣值。Hessian
矩阵描述了图像局部区域的灰度变化情况,通过检测局部最大值或最小值来确定关键点。 -
关键点定位:通过在尺度空间中插值,精确定位关键点的位置。这样做是为了提高关键点的精度,并且能够在亚像素级别进行定位。
-
方向分配:对于每个关键点,计算其主要方向。这通常通过计算特征点周围区域的梯度方向直方图来实现。主要方向用于后续的描述子计算和旋转不变性。
-
描述子计算:在关键点周围的邻域中,计算描述子来描述关键点的特征。
SURF
算法使用了一种基于哈尔小波响应的描述子计算方法。描述子捕捉了关键点周围区域的局部特征。 -
特征匹配:使用描述子比较来进行特征匹配。常见的方法是使用距离度量(如欧氏距离或汉明距离)来衡量描述子之间的相似性。匹配算法可以采用暴力匹配或更高级的方法(如最近邻搜索或
KD
树)。 -
异常值剔除:在进行特征匹配后,可能存在一些错误的匹配或异常值。通过应用一些筛选机制(如
RANSAC
算法)来剔除这些异常值,以获得更准确的匹配结果。
2.3 示例代码
由于OpenCV
库中已经有对应的SURF
算法接口,直接调用即可,如下python
代码:
import cv2
# 加载图像
image = cv2.imread('liuyf.jpg')
# 创建 SURF 对象
surf = cv2.xfeatures2d.SURF_create()
# 检测关键点和计算描述子
keypoints, descriptors = surf.detectAndCompute(image, None)
# 绘制关键点
image_with_keypoints = cv2.drawKeypoints(image, keypoints, None)
# 保存图像
cv2.imwrite('image_with_surf.jpg', image_with_keypoints)
# 显示图像
cv2.imshow('Image with Keypoints', image_with_keypoints)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上述代码中输入左图,输出右图,主要调用了cv2.xfeatures2d.SURF_create()
创建SIFT
对象,然后调用surf.detectAndCompute(image, None)
检测关键点和计算描述子。
3 ORB算法
ORB
(Oriented FAST and Rotated BRIEF
)也是一种目前常用的计算机视觉算法,用于图像特征提取和描述。它是在FAST
角点检测器和BRIEF
描述子算法的基础上进行改进的。👉 ORB论文
详细的实现版本也可参考如下的ORB-SLAM2
中的ORBextractor
。
👉 ORB-SLAM2算法8之特征点提取、生成描述子的ORBextractor
3.1 主要步骤
`ORB算法的主要步骤如下:
-
FAST
角点检测:使用FAST
(Features from Accelerated Segment Test
)算法检测图像中的角点。FAST
算法通过比较像素点与其周围邻域像素的灰度值来判断是否为角点。 -
构建金字塔:为了对不同尺度下的图像进行处理,
ORB
算法使用图像金字塔。通过对原始图像进行不断的降采样,得到一系列尺度不同的图像。 -
计算角点的方向:为了提取具有旋转不变性的特征,
ORB
算法使用灰度质心法来计算角点的方向。它计算角点周围像素的灰度质心,然后根据质心的位置计算角点的方向。 -
构建
BRIEF
描述子:使用BRIEF
(Binary Robust Independent Elementary Features
)算法构建特征描述子。BRIEF
算法通过在角点周围选择一组特定的像素点对,并比较它们的灰度值来生成一个二进制编码,用于描述特征点的特征。 -
特征点匹配:使用描述子之间的汉明距离(
Hamming Distance
)来度量两个特征点的相似性。通过比较特征点的描述子,找到最佳匹配的特征点。
3.2 代码示例
由于OpenCV
库中已经有对应的ORB
算法接口,直接调用即可,如下python
代码:
import cv2
# 读取输入图像
image = cv2.imread('liuyf.jpg')
# 创建ORB对象
orb = cv2.ORB_create()
# 检测关键点和计算描述子
keypoints, descriptors = orb.detectAndCompute(image, None)
# 可选:绘制关键点
image_with_keypoints = cv2.drawKeypoints(image, keypoints, None)
# 保存图像
cv2.imwrite('image_with_orb.jpg', image_with_keypoints)
# 显示结果
cv2.imshow('Image with Keypoints', image_with_keypoints)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上述代码中输入左图,输出右图,主要调用了cv2.ORB_create()
创建SIFT
对象,然后调用orb.detectAndCompute(image, None)
检测关键点和计算描述子。
4 三者对比
算法 | SIFT | SURF | ORB |
---|---|---|---|
原理 | SIFT 算法通过在不同尺度空间和旋转角度上检测图像中的关键点,并计算每个关键点的局部特征描述子 | SURF 算法也是基于尺度空间的特征提取方法,使用了积分图像的数据结构来加速计算,并检测图像中的兴趣点,并计算每个兴趣点的局部特征描述子 | ORB 算法结合了FAST 关键点检测器和BRIEF 描述子。FAST 用于检测关键点,BRIEF 用于计算关键点的二进制描述子 |
特征描述子 | SIFT 算法生成128 维的局部特征描述子 | SURF 算法生成64 维的局部特征描述子 | ORB 算法生成二进制 的局部特征描述子 |
计算效率 | SIFT 算法计算效率较低,尤其在计算特征描述子时需要进行大量的高斯模糊和梯度计算操作 | SURF 算法相对于SIFT 算法来说计算效率较高,主要得益于使用积分图像结构来加速计算 | ORB 算法具有较高的计算效率,主要因为FAST 关键点检测器和BRIEF 描述子都是基于快速计算的算法 |
尺度不变性 | SIFT 算法对于尺度变化具有较好的不变性 | SURF 算法也具有一定的尺度不变性 | ORB 算法在尺度变化较大的情况下可能不太稳定 |
旋转不变性 | SIFT 算法具有很好的旋转不变性 | SURF 算法也具有一定的旋转不变性 | ORB 算法在旋转角度较大的情况下可能不太稳定 |
鲁棒性 | SIFT 算法在处理光照变化、噪声等情况下具有较好的鲁棒性 | SURF 算法对于光照变化和噪声有一定的鲁棒性 | ORB 算法在光照变化和噪声较小的情况下表现较好 |
Reference:
- SIFT 论文:https://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf
- SURF 论文:https://people.ee.ethz.ch/~surf/eccv06.pdf
- ORB 论文:https://www.gwylab.com/download/ORB_2012.pdf
- ORB-SLAM2算法8之特征点提取、生成描述子的ORBextractor
⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔