简介
本节为《OpenCV计算机视觉实战(Python)》版第12讲,SIFT图形特征,的总结。
总结
1. SIFT介绍
SIFT全称:Scale Invariant Feature Transform
首先介绍图像尺度空间的定义。
图像尺度空间
在一定的范围内,无论物体是大还是小,人眼都可以分辨出来,然而计算机要有相同的能力却很难,所以要让机器能够对物体在不同尺度下有一个统一的认知,就需要考虑图像在不同的尺度下都存在的特点。
尺度空间的获取通常使用高斯模型来实现:
其中,GG是高斯函数。
如图所示:
\sigma 参数,控制的是核模糊的程度。不同的\sigma的高斯函数决定了图像的平滑程度,越大的\sigma值对应的图像越模糊。
多分辨率金字塔
尺度空间->金字塔
每一个金字塔都能做多分辨率特征,因此可以获得多分辨率金字塔。
高斯差分金字塔(DOG)
金字塔->高斯差分金字塔
如果每一层特征差异不大,那么意义不大;如果两层之间特征差异比较大,那么这个差异性结果可以作为一个有用的信息。
DOG数学定义:
该公式需要三个参数:位置:(x,y),高斯模糊参数\sigma。
找到极值点:
将第二层的中间点,与同一层的8个临近点,和上层和下层的9个临近点(总共是26个点)做比较,得到极值点(极大值和极小值)f。
可以看出,第一层和最后一层是没有办法做DOG运算的。
DOG得到的值是一系列离散的点。
离散点需要拟合成真实的点。
关键点的精确定位
离散DOG值->拟合
这些候选关键点是DOG空间的局部极值点,而且这些极值点均为离散的点,精确定位极值点的一种方法是,对尺度空间DOG函数进行曲线拟合,计算其极值点,从而实现关键点的精确定位。
三维的数学公式:
从这个公式中可以对极值点进行修正,得到真正精确的极值点。
消除边界相应
极值点->消除边界相应
Hessian矩阵:
Hessian矩阵的特征值为R1,R2,当R1、R2差别过大的时候为边界。
论文中给出的R1/R2的比值为10,认为比值大于10的为边界。
得到关键点后,如何让计算机认识关键点?
将关键点转换为数值!
在后续的改进中,消除的相应更多,不止边界相应。
特征点的主方向
关键点->数值表示的关键点
每个点L(x,y)的梯度的模m(x,y)以及方向theta(x,y):
需要位置、尺度和方向,三个特征。
每个特征点可以得到三个信息(x,y,sigma, theta),也就是位置、尺度和方向。具有多个方向的关键点可以被复制成多份,然后将方向值分别赋给复制后的特征点,一个特征点就产生了多个坐标、尺度相等,但是方向不同的特征点。
生成特征描述
在完成关键点的梯度计算后,使用直方图统计邻域内像素的梯度和方向(只统计了8个方向)。
主方向:最高
次方向:第二高
相当于两个特征向量。
为了保证矢量的旋转不变形,要以特征点为中心,在附近邻域内将坐标旋转theta角度,即将坐标轴旋转为特征点的主方向。
旋转:保证特征具有不变形
构造特征
旋转之后的主方向为中心去88的窗口,求每个像素的梯度幅值和方向。
箭头方向代表梯度方向,长度代表梯度幅值,然后利用高斯窗口对其进行加权运算。
最后在每个44的小块上绘制8个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,即每个特征的由4个种子点组成,每个种子点有8个方向的向量信息。
论文中建议对每个关键点使用4*4共16个种子点来描述,这样一个关键点就会产生128组的SIFT特征向量。
通常写为:(4,4,8)
2. OpenCV程序
OpenCV的版本,3.4.3以上的版本,存在专利保护现象,因此如果调用OpenCV的SIFT函数的话,需要将版本降到3.4.3以下。
程序给出的OpenCV版本为:3.4.1
import cv2
img = cv2.imread('test.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 得到特征点
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None) # kp就表示关键点,封装好的类型
img = cv2.drawKeypoints(gray, kp, img) # 绘制关键点
cv2.imshow('drawKeypoints', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 计算特征
kp, des = sift.compute(gray, kp)
print(np.array(kp).shape) # (6827,)
print(des.shape) # (6827,128)