详解SIFT、SURF和ORB特征点检测和描述算法

0 引言

本文主要对SIFTSURFORB特征点检测和描述算法进行详细的学习和比较。

⚠️ ⚠️ ⚠️ :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 Lowe1999 年提出,并在 👉 2004年的论文中详细描述。

1.1 主要目的

SIFT 算法的主要目标是提取图像中的关键点,这些关键点在不同尺度和旋转下都具有不变性。它在图像中寻找具有稳定特征的局部极值点,并计算这些关键点的描述子。这些描述子可以用于在不同图像之间进行特征匹配,从而实现图像识别、目标跟踪等应用。

1.2 主要步骤

SIFT 算法的主要步骤如下:

  1. 尺度空间极值检测(Scale-space extrema detection):通过在图像的不同尺度上应用高斯差分Gaussian difference-of-Gaussian)进行滤波,检测图像中的极值点。这些极值点通常对应于图像中的边缘、角点等关键位置。

  2. 关键点定位(Keypoint localization):通过在尺度空间中对极值点进行精确定位,排除低对比度和边缘响应不明确的关键点。SIFT 算法使用了尺度空间的极值点的曲率来过滤掉不稳定的关键点。

  3. 方向分配(Orientation assignment):为每个关键点分配一个主方向,用于后续计算关键点的描述子。这样可以使描述子对旋转变换具有不变性。

  4. 关键点描述(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 算法计算量较大,不适用于实时应用,后续也出现了一些更快的替代算法,如SURFSpeeded Up Robust Features)和ORBOriented FAST and Rotated BRIEF)。

2 SURF算法

SURF (Speeded Up Robust Features) 是一种基于 SIFT 算法的改进版本,它在计算效率和描述子的稳健性方面进行了优化。SURF 算法由 Herbert Bay 等人于 2006 年提出,并发表👉 SURF论文

2.1 主要目的

SIFT 算法相比,SURF 算法主要改进了以下两个方面:

  1. 尺度空间极值检测:SURF 算法使用快速Hessian矩阵(Fast Hessian)来检测图像中的尺度空间极值点。相比之下,SIFT 算法使用高斯差分金字塔来检测极值点,而快速Hessian矩阵能够更快地计算图像的尺度空间。

  2. 描述子计算:SURF 算法使用了一种加速技术称为积分图像(Integral Image),用于快速计算关键点周围区域的梯度和特征描述子。这种技术可以显著加快计算速度。

由于 SURF 算法对尺度、旋转和仿射变换具有较好的不变性,并且计算速度更快,因此在实际应用中得到了广泛的应用。与 SIFT 算法相比,SURF 算法在实时性要求较高的场景下更加适用

2.2 主要步骤

SURF算法的主要步骤可以概括为以下几个阶段:

  1. 尺度空间构建:首先,对输入图像进行尺度空间构建。这通常涉及使用高斯滤波器构建图像的金字塔,通过不同尺度的图像来检测不同尺度的特征。

  2. 关键点检测:在每个尺度的图像中,使用Hessian矩阵计算特征点的兴趣值。Hessian矩阵描述了图像局部区域的灰度变化情况,通过检测局部最大值或最小值来确定关键点。

  3. 关键点定位:通过在尺度空间中插值,精确定位关键点的位置。这样做是为了提高关键点的精度,并且能够在亚像素级别进行定位。

  4. 方向分配:对于每个关键点,计算其主要方向。这通常通过计算特征点周围区域的梯度方向直方图来实现。主要方向用于后续的描述子计算和旋转不变性。

  5. 描述子计算:在关键点周围的邻域中,计算描述子来描述关键点的特征。SURF算法使用了一种基于哈尔小波响应的描述子计算方法。描述子捕捉了关键点周围区域的局部特征。

  6. 特征匹配:使用描述子比较来进行特征匹配。常见的方法是使用距离度量(如欧氏距离或汉明距离)来衡量描述子之间的相似性。匹配算法可以采用暴力匹配或更高级的方法(如最近邻搜索或KD树)。

  7. 异常值剔除:在进行特征匹配后,可能存在一些错误的匹配或异常值。通过应用一些筛选机制(如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算法

ORBOriented FAST and Rotated BRIEF)也是一种目前常用的计算机视觉算法,用于图像特征提取和描述。它是在FAST角点检测器和BRIEF描述子算法的基础上进行改进的。👉 ORB论文

详细的实现版本也可参考如下的ORB-SLAM2中的ORBextractor

👉 ORB-SLAM2算法8之特征点提取、生成描述子的ORBextractor

3.1 主要步骤

`ORB算法的主要步骤如下:

  1. FAST角点检测:使用FASTFeatures from Accelerated Segment Test)算法检测图像中的角点。FAST算法通过比较像素点与其周围邻域像素的灰度值来判断是否为角点。

  2. 构建金字塔:为了对不同尺度下的图像进行处理,ORB算法使用图像金字塔。通过对原始图像进行不断的降采样,得到一系列尺度不同的图像。

  3. 计算角点的方向:为了提取具有旋转不变性的特征,ORB算法使用灰度质心法来计算角点的方向。它计算角点周围像素的灰度质心,然后根据质心的位置计算角点的方向。

  4. 构建BRIEF描述子:使用BRIEFBinary Robust Independent Elementary Features)算法构建特征描述子。BRIEF算法通过在角点周围选择一组特定的像素点对,并比较它们的灰度值来生成一个二进制编码,用于描述特征点的特征。

  5. 特征点匹配:使用描述子之间的汉明距离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 三者对比

算法SIFTSURFORB
原理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:




须知少时凌云志,曾许人间第一流。



⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔

  • 19
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZPILOTE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值