📜  使用Python的 SIFT 兴趣点检测器 – OpenCV

📅  最后修改于: 2022-05-13 01:55:33.225000             🧑  作者: Mango

使用Python的 SIFT 兴趣点检测器 – OpenCV

SIFT(尺度不变傅立叶变换)检测器用于检测输入图像上的兴趣点。它允许识别图像中的局部特征,这在以下应用中是必不可少的:

  • 图像中的物体识别
  • 路径检测和避障算法
  • 手势识别、马赛克生成等

与依赖于图像属性(如视点、深度和尺度)的Harris Detector不同,SIFT 可以独立于图像的这些属性执行特征检测。这是通过将图像数据转换为尺度不变坐标来实现的。据说 SIFT 检测器是灵长类视觉系统中使用的系统的近似。

提取兴趣点的步骤

SIFT 检测器步骤

图 01: SIFT Detector 中遵循的步骤顺序

第一阶段:尺度空间峰选择

尺度空间的概念涉及将连续范围的高斯滤波器应用于目标图像,以便所选的高斯滤波器具有不同的 sigma 参数值。这样得到的图称为尺度空间。尺度空间峰值选择取决于空间重合假设。据此,如果在多个尺度(由尺度空间中的零交叉表示)在同一位置检测到边缘,那么我们将其归类为实际边缘。

SIFT 尺度空间峰选择

图 02:跨尺度选择峰值。

在二维图像中,我们可以使用高斯拉普拉斯算子尺度空间中的局部最大值/最小值来检测兴趣点。对于给定的 sigma 值,潜在的 SIFT 兴趣点是通过选择潜在的兴趣点并考虑上层(具有较高 sigma)、相同水平和下层(sigma 低于当前 sigma 水平)中的像素来确定的。如果该点是所有这 26 个相邻点的最大值/最小值,则它是一个潜在的 SIFT 兴趣点 - 它充当兴趣点检测的起点。

第二阶段:关键点定位

关键点定位涉及对前一阶段选择的关键点进行细化。低对比度关键点、不稳定关键点和位于边缘的关键点被消除。这是通过计算在前一阶段找到的关键点的拉普拉斯算子来实现的。极值计算如下:

{z = {-\frac{\partial^{2} {D}^{-1}}{\partial x^{2}}}{{\frac{\partial D}{\partial x}}}}

上式中,D代表高斯差。为了去除不稳定的关键点,计算z的值,如果 z 处的函数值低于阈值,则排除该点。

关键点定位后的关键点细化

图 03关键点定位后的关键点细化

第三阶段:为关键点分配方向

为了实现相对于图像旋转不变的检测,需要计算关键点的方向。这是通过考虑关键点的邻域并计算邻域梯度的大小和方向来完成的。根据获得的值,构建一个包含 36 个 bin 的直方图来表示 360 度的方向(每个 bin 10 度)。因此,如果某个点的梯度方向是 67.8 度,则与该点的梯度幅度成正比的值被添加到表示 60-70 度的 bin。 80% 以上的直方图峰值被转换为新的关键点,用于决定原始关键点的方向。

为邻域分配方向并创建方向直方图

图 04:为邻域分配方向并创建方向直方图

第四阶段:关键点描述符

最后,对于每个关键点,使用关键点邻域创建一个描述符。这些描述符用于匹配图像中的关键点。关键点的 16×16 邻域用于定义该关键点的描述符。这个 16×16 的邻域被划分为子块。每个这样的子块都是一个不重叠的、连续的、4×4 的邻域。随后,对于每个子块,与方向分配中讨论的类似,创建 8 个 bin 方向。这 128 个 bin 值(16 个子块 * 每块 8 个 bin)表示为向量以生成关键点描述符。

示例: Python中的 SIFT 检测器

在同一目录中使用名为“geeks.jpg”的文件运行以下脚本会生成“image-with-keypoints.jpg”,其中包含使用 OpenCV 中的 SIFT 模块检测到的兴趣点,并使用圆形叠加进行标记。

下面是实现:

Python3
# Important NOTE:  Use opencv <= 3.4.2.16 as
# SIFT is no longer available in
# opencv > 3.4.2.16
import cv2
  
# Loading the image
img = cv2.imread('geeks.jpg')
  
 # Converting image to grayscale
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  
# Applying SIFT detector
sift = cv2.xfeatures2d.SIFT_create() 
kp = sift.detect(gray, None)
  
# Marking the keypoint on the image using circles
img=cv2.drawKeypoints(gray ,
                      kp ,
                      img ,
                      flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
  
cv2.imwrite('image-with-keypoints.jpg', img)


输出:

左图为原图,右图为图像上突出显示的各个兴趣点

左图为原图,右图为图像上突出显示的各个兴趣点