OpenCV-Python SIFT 简介(尺度不变特征变换)

在这一章当中,

  • 我们将了解 SIFT 算法的概念
  • 我们将学习如何找到 SIFT 特征点和描述子。

SIFT 算法理论

在前几章中,我们看到了一些角点检测器,如 Harris 等。它们具有旋转不变性,这意味着,即使图像旋转,我们也可以找到相同的角点。很明显,因为角点在旋转图像中也是角点。但是缩放呢?如果图像缩放,角点可能就不再是角点。以下图为例,在小图像中使用一个小窗口能够检测出角点,然而将图像放大后,在同一窗口中的图像变得平坦,无法检测出角点。所以 Harris 角点不是尺度不变的。

SIFT 算法理论

因此,在 2004 年,不列颠哥伦比亚大学的 D.Lowe 在他的论文Distinctive Image Features from Scale-Invariant Keypoints中提出了一种新算法,尺度不变特征变换(SIFT),用以提取特征点并计算其描述子。 (这篇论文易于理解,被认为关于 SIFT 的最佳材料。以下解释只是对该论文的简短摘要)

SIFT 算法主要涉及四个步骤。我们将逐一看到它们。

尺度空间极值检测

从上图可以看出,我们不能使用同一个窗口来检测不同尺度空间中的角点。检测小的角点可以用小的窗口,但检测更大的角点则需要更大的窗口。为此需要进行尺度空间滤波。使用不同$$\sigma$$值的高斯拉普拉斯算子(LoG)对图像进行卷积。 具有不同$$\sigma$$值的 LoG 可以检测不同大小的斑点。简而言之,$$\sigma$$相当于一个尺度变换因子。例如,在上图中,使用具有低$$\sigma$$的高斯核可以检测出小的角点,而具有高$$\sigma$$的高斯核则适合于检测大的角点。因此,我们可以在尺度空间和二维平面中找到局部最大值$$(x, y, \sigma)$$,这意味着在$$\sigma$$尺度中的(x,y)处有一个潜在的特征点。

但是 LoG 的计算量非常大,因此 SIFT 算法使用高斯差分,这是 LoG 的近似值。分别使用方差值为$$\sigma$$和$$k\sigma$$的高斯核对图像进行模糊,对所得的结果再求二者的差值就是 DoG。如下图所示:

尺度空间极值检测

找到 DoG 后,搜索不同尺度空间和二维平面中的局部最大值。例如,将图像中的一个像素与其 8 领域、尺度空间上一层中相邻的 9 个像素以及尺度空间下一层中相邻的 9 个像素做比较。如果它是一个局部最大值,那么它就是一个潜在的特征点。基本上可以说特征点是相应尺度空间的最佳代表。如下图所示:

尺度空间极值检测

对于参数的取值论文中给出了一些经验数据,可以概括为:octaves= 4,尺度等级数为 5,初始$$\sigma$$ = 1.6 ,$$k = \sqrt {2} $$作为最佳值。

特征点定位

一旦找到潜在的特征点,就必须对其进行细化以获得更准确的结果。论文作者使用尺度空间的泰勒展开来获得更准确的极值位置,并且如果此极值处的强度小于阈值(0.03),则将其忽略。该阈值在 OpenCV 中被称为contrastThreshold

DoG 对边缘更加敏感,因此需要去除边缘。为此,使用了类似于 Harris 角点检测的思路。论文作者使用 2x2 Hessian 矩阵(H)来计算主曲率。我们从 Harris 角点检测得知,当一个特征值大于另一个特征值时检测到的是边界。所以这里论文作者使用了一个简单的函数,如果比率大于阈值则丢弃该特征点,在 OpenCV 中这个比率被称为 edgeThreshold 。论文中给出的边界阈值是 10。

所以,任何低对比度特征点点和边缘特征点被去除后,剩下的就是我们所感兴趣的特征点。

指定方向

现在,为每个特征点指定方向,以实现图像旋转的不变性。获取特征点所在的尺度空间的领域,并且在计算该区域的梯度大小和方向。创建了一个包含 36 个 bins(每 10°一个 bin,覆盖了 360°)的方向直方图(由梯度幅度和圆形高斯窗口加权,其中高斯窗口的$$\sigma$$等于当前特征点尺度空间$$\sigma$$的 1.5 倍)。采用直方图中的最高峰为主方向,同时也考虑其余任何高于最高峰 80%的峰来计算方向。这就会创建具有相同位置和尺度空间但不同方向的特征点。这样做有助于匹配的稳定性。

特征点描述子

现在创建特征点描述子。在关键点周围选取 16x16 的邻域。将它为 16 个 4x4 大小的子块。对于每个子块,创建包含 8 个 bin 的方向直方图。因此总共有 128 个 bin 值可用。由这 128 个形成的向量构成了特征点描述子。除此之外,还采取了一些措施来实现对光照变化,旋转等的鲁棒性。

特征点匹配

通过识别两幅图像中距离最近的特征点来进行特征点匹配。但在某些情况下,第二个最接近的匹配可能非常接近第一个。它可能由噪音或其他原因而引起。在这种情况下,计算最近距离与第二最近距离的比率。如果比率大于 0.8,则忽略它们。根据论文,这样做消除了大约 90%的错误匹配,而同时只去除了 5%的正确匹配。

以上是 SIFT 算法的总结。关于更多详细信息和理解,强烈建议阅读原始论文。记住一件事,这个算法受到专利保护,所以这个算法被包含在 opencv contrib repo 中。

OpenCV 中的 SIFT

现在让我们看看 OpenCV 中提供的 SIFT 函数。让我们从特征点检测及绘制开始。首先,我们必须构造一个 SIFT 对象。我们可以使用不同的参数,这不是必须的,关于参数的解释可参考文档。

import numpy as np
import cv2 as cv
img = cv.imread('home.jpg')
gray= cv.cvtColor(img,cv.COLOR_BGR2GRAY)
sift = cv.xfeatures2d.SIFT_create()
kp = sift.detect(gray,None)
img=cv.drawKeypoints(gray,kp,img)
cv.imwrite('sift_keypoints.jpg',img)

sift.detect()函数查找图像中的特征点。如果只想搜索图像的一部分,则可以传递一个掩模。返回的每个特征点都是一个特殊的结构,它有许多属性,如(x,y)坐标,有意义邻域的大小,指定方向的角度,指定特征点强度的响应等。

OpenCV 还提供 cv.drawKeyPoints()函数,该函数在特征点的位置上绘制小圆圈。如果您向其传递一个标志 cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ,它将绘制一个特征点大小的圆圈,它甚至会显示其方向。见下面的例子。

img=cv.drawKeypoints(gray,kp,img,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv.imwrite('sift_keypoints.jpg',img)

请参阅以下两个结果:

OpenCV 中的 SIFT

现在要计算描述子,OpenCV 提供了两种方法。

  1. 既然你已经找到了特征点,你可以调用 sift.compute()来计算我们找到的特征点的描述子。例如:kp,des = sift.compute(gray,kp)。
  2. 如果您没有找到特征点,请使用函数 sift.detectAndCompute()在一个步骤中直接查找特征点和描述子。

我们将看到第二种方法:

sift = cv.xfeatures2d.SIFT_create()
kp, des = sift.detectAndCompute(gray,None)

这里 kp 是一个特征点列表,des 是一个 numpy 数组,该数组大小是特征点数目乘 128。

所以我们得到了特征点,描述子等。现在我们想看看如何匹配不同图像中的特征点。我们将在接下来的章节中学习。

赞(1)
未经允许不得转载:极客笔记 » OpenCV-Python SIFT 简介(尺度不变特征变换)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
OpenCV-Python介绍
OpenCV-Python 教程在Windows安装OpenCV-Python在Fedora上安装OpenCV-Python在Ubuntu系统中安装OpenCV—Python
OpenCV-Python GUI功能
OpenCV-Python图像入门OpenCV-Python视频入门OpenCV-Python绘图功能OpenCV-Python鼠标作为画笔OpenCV-Python作为调色板的跟踪栏
OpenCV-Python 核心操作
OpenCV-Python图像基本操作OpenCV-Python图像的算术运算OpenCV-Python性能测量和改进技术
OpenCV-Python 图像处理
OpenCV-Python改变颜色空间OpenCV-Python图像的几何变换OpenCV-Python图像阈值OpenCV-Python平滑图像OpenCV-Python形态转换OpenCV-Python图像梯度OpenCV-Python Canny边缘检测OpenCV-Python图像金字塔OpenCV-Python轮廓入门OpenCV-Python轮廓特征OpenCV-Python轮廓属性OpenCV-Python更多轮廓功能OpenCV-Python轮廓层次结构OpenCV-Python直方图-查找,绘图,分析OpenCV-Python直方图均衡OpenCV-Python 2D直方图OpenCV-Python直方图反投影OpenCV-Python图像转换OpenCV-Python模板匹配OpenCV-Python霍夫线变换OpenCV-Python霍夫圆变换OpenCV-Python基于分水岭算法的图像分割OpenCV-Python基于 GrabCut 算法的交互式前景提取
OpenCV-Python 特征检测
OpenCV-Python理解特征OpenCV-Python Harris 角点检测OpenCV-Python Shi-Tomasi 角点检测和追踪的良好特征OpenCV-Python SIFT 简介(尺度不变特征变换)OpenCV-Python SURF 简介(加速鲁棒特性)OpenCV-Python角点检测的 FAST 算法OpenCV-Python BRIEF(二进制鲁棒独立基本特征)OpenCV-Python ORB算法OpenCV-Python特征匹配OpenCV-Python特征匹配+单应性查找对象
OpenCV-Python 视频分析
OpenCV-Python Meanshift 和 CamshiftOpenCV-Python光流OpenCV-Python背景减法
OpenCV-Python 相机校准和3D重建
OpenCV-Python相机校准OpenCV-Python姿势估计OpenCV-Python线性几何OpenCV-Python立体图像的深度图
OpenCV-Python 机器学习
OpenCV-Python K-最近邻算法OpenCV-Python 使用 kNN 进行手写识别OpenCV-Python 理解 SVMOpenCV-Python 使用 SVM 进行手写数据识别OpenCV-Python 理解 K-Means 聚类OpenCV-Python 中的 K-Means 聚类
OpenCV-Python 计算摄影
OpenCV-Python 图像去噪OpenCV-Python 图像修复OpenCV-Python 高动态范围(HDR)