机器学习图像处理 SIFT 特征关键点检测
SIFT简介
SIFT 的全称是 Scale Invariant Feature Transform,尺度不变特征变换,由加拿大教授 David G.Lowe 提出的。SIFT 特征对旋转、尺度缩放、亮度变化等保持不变性,是一种非常稳定的局部特征
SIFT 算法具的特点
-
图像的局部特征,对旋转、尺度缩放、亮度变化保持不变,对视角变化、仿射变换、噪声也保持一定程度的稳定性
-
独特性好,信息量丰富,适用于海量特征库进行快速、准确的匹配
-
多量性,即使是很少几个物体也可以产生大量的SIFT特征
-
高速性,经优化的SIFT匹配算法甚至可以达到实时性
-
扩招性,可以很方便的与其他的特征向量进行联合
SIFT 特征检测的步骤
-
尺度空间的极值检测: 搜索所有尺度空间上的图像,通过高斯微分函数来识别潜在的对尺度和选择不变的兴趣点
-
特征点定位: 在每个候选的位置上,通过一个拟合精细模型来确定位置尺度,关键点的选取依据他们的稳定程度
-
特征方向赋值: 基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向,后续的所有操作都是对于关键点的方向、尺度和位置进行变换,从而提供这些特征的不变性
-
特征点描述: 在每个特征点周围的邻域内,在选定的尺度上测量图像的局部梯度,这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变换
尺度空间
在一定的范围内,无论物体是大还是小,人眼都可以分辨出来。然而计算机要有相同的能力却不是那么的容易,在未知的场景中,计算机视觉并不能提供物体的尺度大小,其中的一种方法是把物体不同尺度下的图像都提供给机器,让机器能够对物体在不同的尺度下有一个统一的认知。在建立统一认知的过程中,要考虑的就是在图像在不同的尺度下都存在的特征点
多分辨率图像金字塔
在早期图像的多尺度通常使用图像金字塔表示形式。图像金字塔是同一图像在不同的分辨率下得到的一组结果,其生成过程一般包括两个步骤:
-
对原始图像进行平滑
-
对处理后的图像进行降采样(通常是水平、垂直方向的1/2)降采样后得到一系列不断尺寸缩小的图像。显然,一个传统的金字塔中,每一层的图像是其上一层图像长、高的各一半。多分辨率的图像金字塔虽然生成简单,但其本质是降采样,图像的局部特征则难以保持,也就是无法保持特征的尺度不变性
高斯尺度空间
我们还可以通过图像的模糊程度来模拟人在距离物体由远到近时物体在视网膜上成像过程,距离物体越近其尺寸越大图像也越模糊,这就是高斯尺度空间,使用不同的参数模糊图像(分辨率不变),是尺度空间的另一种表现形式。
我们知道图像和高斯函数进行卷积运算能够对图像进行模糊,使用不同的“高斯核”可得到不同模糊程度的图像。一副图像其高斯尺度空间可由其和不同的高斯卷积得到:
其中,G(x,y,σ) 是高斯核函数
σ称为尺度空间因子,它是高斯正态分布的标准差,反映了图像被模糊的程度,其值越大图像越模糊,对应的尺度也就越大。L(x,y,σ)代表着图像的高斯尺度空间
构建尺度空间的目的是为了检测出在不同的尺度下都存在的特征点,而检测特征点较好的算子是 (高斯拉普拉斯,LoG)
使用 LoG 虽然能较好的检测到图像中的特征点,但是其运算量过大,通常可使用 DoG(差分高斯,Difference of Gaussina)来近似计算 LoG[Marr and Hidreth]
设 k 为相邻两个高斯尺度空间的比例因子,则 DoG 的定义:
其中,L(x,y,σ) 是图像的高斯尺度空间
从上式可以知道,将相邻的两个高斯空间的图像相减就得到了 DoG 的响应图像。为了得到 DoG 图像,先要构建高斯尺度空间,而高斯的尺度空间可以在图像金字塔降采样的基础上加上高斯滤波得到,也就是对图像金字塔的每层图像使用不同的参数σ进行高斯模糊,使每层金字塔有多张高斯模糊过的图像
高斯金字塔构建成功后,将每一组相邻的两层相减就可以得到 DoG 金字塔
DoG 空间极值检测
为了寻找尺度空间的极值点,每个像素点要和其图像域(同一尺度空间)和尺度域(相邻的尺度空间)的所有相邻点进行比较,当其大于(或者小于)所有相邻点时,改点就是极值点。如图所示,中间的检测点要和其所在图像的 3×3 邻域 8 个像素点,以及其相邻的上下两层的 3×3 领域 18 个像素点,共 26 个像素点进行比较
从上面的描述中可以知道,每组图像的第一层和最后一层是无法进行比较取得极值的。为了满足尺度变换的连续性,在每一组图像的顶层继续使用高斯模糊生成 3 幅图像
删除不好的极值点(特征点)
通过比较检测得到的 DoG 的局部极值点所在离散的空间搜索得到的,由于离散空间是对连续空间采样得到的结果,因此在离散空间找到的极值点不一定是真正意义上的极值点,因此要设法将不满足条件的点剔除掉。可以通过尺度空间DoG函数进行曲线拟合寻找极值点,这一步的本质是去掉 DoG 局部曲率非常不对称的点
要剔除掉的不符合要求的点主要有两种:
-
低对比度的特征点
-
不稳定的边缘响应点
剔除低对比度的特征点
剔除不稳定的边缘响应点
求取特征点的主方向
经过上面的步骤已经找到了在不同尺度下都存在的特征点,为了实现图像旋转不变性,需要给特征点的方向进行赋值。利用特征点邻域像素的梯度分布特性来确定其方向参数,再利用图像的梯度直方图求取关键点局部结构的稳定方向
找到了特征点,也就可以得到该特征点的尺度 σ,也就可以得到特征点所在的尺度图像
计算以特征点为中心、以 为半径的区域图像的幅角和幅值,每个点 的梯度的模 以及方向 可通过下面公司求得
计算得到梯度方向后,就要使用直方图统计特征点邻域内像素对应的梯度方向和幅值。梯度方向的直方图的横轴是梯度方向的角度(梯度方向的范围是 0 到 360 度,直方图每 36 度一个柱共 10 个柱,或者没 45 度一个柱共 8 个柱),纵轴是梯度方向对应梯度幅值的累加,在直方图的峰值就是特征点的主方向。在 Lowe 的论文还提到了使用高斯函数对直方图进行平滑以增强特征点近的邻域点对关键点方向的作用,并减少突变的影响。为了得到更精确的方向,通常还可以对离散的梯度直方图进行插值拟合。具体而言,关键点的方向可以由和主峰值最近的三个柱值通过抛物线插值得到。在梯度直方图中,当存在一个相当于主峰值 80% 能量的柱值时,则可以将这个方向认为是该特征点辅助方向。所以,一个特征点可能检测到多个方向(也可以理解为,一个特征点可能产生多个坐标、尺度相同,但是方向不同的特征点)。Lowe 在论文中指出:15% 的关键点具有多方向,而且这些点对匹配的稳定性很关键
得到特征点的主方向后,对于每个特征点可以得到三个信息(x,y,σ,θ),即位置、尺度和方向。由此可以确定一个 SIFT 特征区域,一个 SIFT 特征区域由三个值表示,中心表示特征点位置,半径表示关键点的尺度,箭头表示主方向。具有多个方向的关键点可以被复制成多份,然后将方向值分别赋给复制后的特征点,一个特征点就产生了多个坐标、尺度相等,但是方向不同的特征点
生成特征描述
通过以上的步骤已经找到了 SIFT 特征点位置、尺度和方向信息,下面就需要使用一组向量来描述关键点也就是生成特征点描述子,这个描述符不只包含特征点,也含有特征点周围对其有贡献的像素点。描述子应具有较高的独立性,以保证匹配率
特征描述符的生成大致有三个步骤:
-
校正旋转主方向,确保旋转不变性
-
生成描述子,最终形成一个 128 维的特征向量
-
归一化处理,将特征向量长度进行归一化处理,进一步去除光照的影响
为了保证特征矢量的旋转不变性,要以特征点为中心,在附近邻域内将坐标轴旋转 θ(特征点的主方向)角度,即将坐标轴旋转为特征点的主方向。旋转后邻域内像素的新坐标为:
旋转后以主方向为中心取 8×8 的窗口。下图所示,左图的中央为当前关键点的位置,每个小格代表为关键点邻域所在尺度空间的一个像素,求取每个像素的梯度幅值与梯度方向,箭头方向代表该像素的梯度方向,长度代表梯度幅值,然后利用高斯窗口对其进行加权运算。最后在每个 4×4 的小块上绘制 8 个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,如右图所示。每个特征点由 4 个种子点组成,每个种子点有 8 个方向的向量信息。这种邻域方向性信息联合增强了算法的抗噪声能力,同时对于含有定位误差的特征匹配也提供了比较理性的容错性
与求主方向不同,此时每个种子区域的梯度直方图在 0-360 之间划分为8个方向区间,每个区间为 45 度,即每个种子点有 8 个方向的梯度强度信息
在实际的计算过程中,为了增强匹配的稳健性,Lowe 建议
对每个关键点使用 4×44×4 共 16 个种子点来描述,这样一个关键点就可以产生 128 维的 SIFT 特征向量
通过对特征点周围的像素进行分块,计算块内梯度直方图,生成具有独特性的向量,这个向量是该区域图像信息的一种抽象,具有唯一性
总结
SIFT 特征以其对旋转、尺度缩放、亮度等保持不变性,是一种非常稳定的局部特征,在图像处理和计算机视觉领域有着很重要的作用,其本身也是非常复杂的,下面对其计算过程做一个粗略总结
-
DoG 尺度空间的极值检测: 首先是构造 DoG 尺度空间,在 SIFT 中使用不同参数的高斯模糊来表示不同的尺度空间。而构造尺度空间是为了检测在不同尺度下都存在的特征点,特征点的检测比较常用的方法是 Δ2G(高斯拉普拉斯 LoG),但是 LoG 的运算量是比较大的,Marr 和 Hidreth 曾指出,可以使用 DoG(差分高斯)来近似计算 LoG,所以在 DoG 的尺度空间下检测极值点
-
删除不稳定的极值点:主要删除两类:低对比度的极值点以及不稳定的边缘响应点
-
确定特征点的主方向:以特征点的为中心、以 3×1.5σ 为半径的领域内计算各个像素点的梯度的幅角和幅值,然后使用直方图对梯度的幅角进行统计。直方图的横轴是梯度的方向,纵轴为梯度方向对应梯度幅值的累加值,直方图中最高峰所对应的方向即为特征点的方向
-
生成特征点的描述子: 首先将坐标轴旋转为特征点的方向,以特征点为中心的 16×16 的窗口的像素的梯度幅值和方向,将窗口内的像素分成 16 块,每块是其像素内 8 个方向的直方图统计,共可形成 128 维的特征向量
代码测试
- #导入标准库os
- import os
- #导入numpy
- import numpy as np
- #导入matplotlib
- from matplotlib import pyplot as plt
- #导入OpenCV
- import cv2 as cv
-
- src = cv.imread('test.png')
- #绘制热图
- plt.imshow(src)
- #图片显示
- plt.show()
- sift = cv.xfeatures2d.SIFT_create()
- kps = sift.detect(src)
- result = cv.drawKeypoints(src, kps, None, (0, 0, 255), cv.DrawMatchesFlags_DEFAULT)
- #绘制热图
- plt.imshow(result)
- #图片显示
- plt.show()
- cv.waitKey(0)
- cv.destroyAllWindows()
解释
SIFT特征提取是图像特征提取中最经典的一个算法,归纳起来SIFT特征提取主要有如下几步:
-
构建高斯多尺度金字塔
-
关键点查找/过滤与精准定位
-
窗口区域角度方向直方图
-
描述子生成
SIFT特征是非常稳定的图像特征,在图像搜索、特征匹配、图像分类检测等方面应用十分广泛,但是它的缺点也是非常明显,就是计算量比较大,很难实时,所以对一些实时要求比较高的常见SIFT算法还是无法适用。如今SIFT算法在深度学习特征提取与分类检测网络大行其道的背景下,已经越来越有鸡肋的感觉,但是它本身的算法知识还是很值得我们学习,对我们也有很多有益的启示,本质上SIFT算法是很多常见算法的组合与巧妙衔接,这个思路对我们自己处理问题可以带来很多有益的帮助。今天我们首先高清楚SIFT特征提取的前面两个步骤,尺度空间金字塔与关键点过滤。
OpenCV 已经实现了 SIFT 算法,但是在OpenCV3.0之后因为专利授权问题,该算法在扩展模块xfeature2d中,需要自己编译才可以使用,OpenCV Python中从3.4.2之后扩展模块也无法使用,需要自己单独编译python SDK才可以使用。其使用方法与我们前面介绍的ORB完全一致。在Python3.7中使用pip install opencv-contrib-python==3.4.2.17来使用。都是遵循下面的步骤
-
创建对象
-
通过detect方法提取对象关键点
-
同drawKeypoints绘制关键点
-
构建多尺度高斯金字塔
为了在每组图像中检测 S 个尺度的极值点,DoG 金字塔每组需 S+2 层图像,因为每组的第一层和最后一层图像上不能检测极值,DoG 金字塔由高斯金字塔相邻两层相减得到,则高斯金字塔每组最少需 S+3 层图像,实际计算时 S 通常在2到5之间。