注意在opencv3.4.1.15以后的版本涉及这个部分的函数已经用不了了,需要在网上找教程
原理:
1.图像尺度空间
一个物体不论是近处人们可以分辨出来,远处也可通过轮廓进行分辨,图像尺度空间就是通过制造模糊程度不同的图像,即不同的尺度,让计算机对不同尺度下的物体有一个统一的认知

不同尺度的效果如下:

不同σ的高斯函数决定了对图像的平滑程度,越大的σ值对应的图像越模糊。
2.多分辨率金字塔
由于要在远处,即物体比较小的时候也能分辨出来,只做一个同样大小的尺度远远不够,因此还要做一个多分辨率金字塔。
图像的不同尺度是为了在相同的大小下让计算机能够识别出来物体,多分辨率金字塔是为了让计算机能在远近不同导致物体大小不同模糊程度不同的情况下得到物体统一的特征,从而识别出来。
先用高斯金字塔做出不同大小的图像,再对每一层用高斯滤波做5个尺度。(因为前面也做了5个尺度,不包括原始图像)

3.高斯差分金字塔(DOG)
对于两个物体,有的特征会非常接近,有的特征相差很大,只有相差很大的特征才是有价值的。因此这里就要用高斯差分金字塔。


下面是如何找出极值点
对于得出的DOG,图像的每一点除了要和自己周围的点比较,还要和上下不同尺度的点比较
以打叉的点为例,蓝色部分为其要比较的点

由于比较一定要上下都有,因此每一层的第一张和第二张是无法比较的,这里根据想得出多少个结果要注意自己的尺度的数量,比如2个结果就要做3个不同尺度,也就是每层有四张图。
4.关键点的精确定位
这些候选关键点是DOG空间的局部极值点,而且这些极值点均为离散的点,精确定位极值点的一种方法是,对尺度空间DoG函数进行曲线拟合,计算其极值点,从而实现关键点的精确定位。

对于三维的式子,即上面的图像是一个三维函数的结果,计算方法如下

5.消除边界响应
用高斯滤波后可能会产生一些边界响应,这里消除的方法和角点检测基本一样。

6.将上面得出的点转为向量
(1)特征点的主方向
每个特征点可以得到三个信息(x,y,σ,θ),即位置、尺度和方向。具有多个方向的关键点可以被复制成多份,然后将方向值分别赋给复制后的特征点,一个特征点就产生了多个坐标、尺度相等,但是方向不同的特征点。

(2)生成特征描述
在完成关键点的梯度计算后,使用直方图统计邻域内像素的梯度和方向。由于方向是无数的,这里划分为8个方向。取最多的方向为主方向。有时可能会出现2个以上的方向数量非常相近,则会有两个特征向量

为了保证特征矢量的旋转不变性,要以特征点为中心,在附近邻域内将坐标轴旋转θ角度,即将坐标轴旋转为特征点的主方向。

旋转之后的主方向为中心取8x8的窗口,求每个像素的梯度幅值和方向,箭头方向代表梯度方向,长度代表梯度幅值,然后利用高斯窗口对其进行加权运算,最后在每个4x4的小块上绘制8个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,即每个特征的由4个种子点组成,每个种子点有8个方向的向量信息。
长度代表数量

论文中建议对每个关键点使用4x4共16个种子点来描述,这样一个关键点就会产生128维的SIFT特征向量。

代码如下:
注意在opencv3.4.1.15以后的版本涉及这个部分的函数已经用不了了,需要在网上找教程
import cv2
import numpy as np
img = cv2.imread('test_1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#下面得到特征点
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None) #kp就是key point特征点,这里是封装好了的
img = cv2.drawKeypoints(gray, kp, img)
cv2.imshow('drawKeypoints', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果如下:

下面就是计算特征点的特征向量
kp, des = sift.compute(gray, kp) #这里两个kp都是指的关键点,函数返回的kp是关键点的list,des是关键点对应的128维的向量
print (np.array(kp).shape) #(6827,)
print(des.shape) #(6827, 128)
des[0]
返回:
array([ 0., 0., 0., 0., 0., 0., 0., 0., 21., 8., 0.,
0., 0., 0., 0., 0., 157., 31., 3., 1., 0., 0.,
2., 63., 75., 7., 20., 35., 31., 74., 23., 66., 0.,
0., 1., 3., 4., 1., 0., 0., 76., 15., 13., 27.,
8., 1., 0., 2., 157., 112., 50., 31., 2., 0., 0.,
9., 49., 42., 157., 157., 12., 4., 1., 5., 1., 13.,
7., 12., 41., 5., 0., 0., 104., 8., 5., 19., 53.,
5., 1., 21., 157., 55., 35., 90., 22., 0., 0., 18.,
3., 6., 68., 157., 52., 0., 0., 0., 7., 34., 10.,
10., 11., 0., 2., 6., 44., 9., 4., 7., 19., 5.,
14., 26., 37., 28., 32., 92., 16., 2., 3., 4., 0.,
0., 6., 92., 23., 0., 0., 0.], dtype=float32)
本文详细介绍了SIFT(尺度不变特征变换)算法的原理和步骤,包括图像尺度空间、多分辨率金字塔、高斯差分金字塔(DOG)、关键点的精确定位、消除边界响应以及将关键点转换为向量的过程。特别指出在OpenCV 3.4.1.15之后的版本中相关函数已不可用,需参考其他教程。
2640

被折叠的 条评论
为什么被折叠?



