圖像特征-sift
圖像尺度空間
在一定的范圍內,無論物體是大還是小,人眼都可以分辨出來,然而計算機要有相同的能力卻很難,所以要讓機器能夠對物體在不同尺度下有一個統一的認知,就需要考慮圖像在不同的尺度下都存在的特點。
尺度空間的獲取通常使用高斯模糊來實現
不同σ的高斯函數決定了對圖像的平滑程度,越大的σ值對應的圖像越模糊。
多分辨率金字塔
高斯差分金字塔(DOG)
DoG空間極值檢測
為了尋找尺度空間的極值點,每個像素點要和其圖像域(同一尺度空間)和尺度域(相鄰的尺度空間)的所有相鄰點進行比較,當其大於(或者小於)所有相鄰點時,該點就是極值點。如下圖所示,中間的檢測點要和其所在圖像的3×3鄰域8個像素點,以及其相鄰的上下兩層的3×3領域18個像素點,共26個像素點進行比較。
關鍵點的精確定位
這些候選關鍵點是DOG空間的局部極值點,而且這些極值點均為離散的點,精確定位極值點的一種方法是,對尺度空間DoG函數進行曲線擬合,計算其極值點,從而實現關鍵點的精確定位。
消除邊界響應
特征點的主方向
每個特征點可以得到三個信息(x,y,σ,θ),即位置、尺度和方向。具有多個方向的關鍵點可以被復制成多份,然后將方向值分別賦給復制后的特征點,一個特征點就產生了多個坐標、尺度相等,但是方向不同的特征點。
生成特征描述
在完成關鍵點的梯度計算后,使用直方圖統計鄰域內像素的梯度和方向。
為了保證特征矢量的旋轉不變性,要以特征點為中心,在附近鄰域內將坐標軸旋轉θ角度,即將坐標軸旋轉為特征點的主方向。
旋轉之后的主方向為中心取8x8的窗口,求每個像素的梯度幅值和方向,箭頭方向代表梯度方向,長度代表梯度幅值,然后利用高斯窗口對其進行加權運算,最后在每個4x4的小塊上繪制8個方向的梯度直方圖,計算每個梯度方向的累加值,即可形成一個種子點,即每個特征的由4個種子點組成,每個種子點有8個方向的向量信息。
論文中建議對每個關鍵點使用4x4共16個種子點來描述,這樣一個關鍵點就會產生128維的SIFT特征向量。
opencv SIFT函數
import cv2 import numpy as np img = cv2.imread('test_1.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.__version__ #3.4.1.15 pip install opencv-python==3.4.1.15 pip install opencv-contrib-python==3.4.1.15
效果:
'3.4.1'
sift = cv2.xfeatures2d.SIFT_create() #得到特征點 kp = sift.detect(gray, None) 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) des.shape des[0]
效果:
(6827,) (6827, 128) 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)