我們在上個教程討論了SIFT算法用於檢測特征點,SIFT算法對旋轉、尺度縮放、亮度變化等保持不變性,對視角變換、仿射變化、噪聲也保持一定程度的穩定性,是一種非常優秀的局部特征描述算法。但是其實時性相對不高。SURF(Speeded Up Robust Features)算法改進了特征了提取和描述方式,用一種更為高效的方式完成特征點的提取和描述。
SURF算法原理
SURF特征檢測的步驟
1. 尺度空間的極值檢測:搜索所有尺度空間上的圖像,通過Hessian來識別潛在的對尺度和選擇不變的興趣點。
2. 特征點過濾並進行精確定位。
3. 特征方向賦值:統計特征點圓形鄰域內的Harr小波特征。即在60度扇形內,每次將60度扇形區域旋轉0.2弧度進行統計,將值最大的那個扇形的方向作為該特征點的主方向。
4. 特征點描述:沿着特征點主方向周圍的鄰域內,取4×4個矩形小區域,統計每個小區域的Haar特征,然后每個區域得到一個4維的特征向量。一個特征點共有64維的特征向量作為SURF特征的描述子。
構建Hessian
構建Hessian矩陣的目的是為了生成圖像穩定的邊緣點(突變點),跟Canny、拉普拉斯邊緣檢測的作用類似,為特征提取做准備。構建Hessian矩陣的過程對應着SIFT算法中的DoG過程。
黑塞矩陣(Hessian Matrix)是由一個多元函數的二階偏導數構成的方陣,描述了函數的局部曲率。由德國數學家Ludwin Otto Hessian於19世紀提出。
對於一個圖像I(x,y),其Hessian矩陣如下:
H矩陣的判別式是:
在構建Hessian矩陣前需要對圖像進行高斯濾波,經過濾波后的Hessian矩陣表達式為:
其中(x,y)為像素位置, L(x,y,σ)=G(σ)∗I(x,y),代表着圖像的高斯尺度空間,是由圖像和不同的高斯卷積得到。
我們知道在離散數學圖像中,一階導數是相鄰像素的灰度差:
二階導數是對一階導數的再次求導:
反過來看Hessian矩陣的判別式,其實就是當前點對水平方向二階偏導數乘以垂直方向二階偏導數再減去當前水平、垂直二階偏導的二次方:
通過這種方法可以為圖像中每個像素計算出其H行列式的決定值,並用這個值來判別圖像局部特征點。Hession矩陣判別式中的L(x,y)是原始圖像的高斯卷積,由於高斯核服從正太分布,從中心點往外,系數越來越小,為了提高運算速度,SURF算法使用了盒式濾波器來替代高斯濾波器L,所以在Lxy上乘了一個加權系數0.9,目的是為了平衡因使用盒式濾波器近似所帶來的誤差,則H矩陣判別式可表示為:
盒式濾波器和高斯濾波器的示意圖如下:
上面兩幅圖是9×9高斯濾波器模板分別在圖像垂直方向上二階導數Lyy和Lxy對應的值,下邊兩幅圖是使用盒式濾波器對其近似,灰色部分的像素值為0,黑色為-2,白色為1。
那么為什么盒式濾波器可以提高運算速度呢?這就涉及到積分圖的使用,盒式濾波器對圖像的濾波轉化成計算圖像上不同區域間像素的加減運算問題,這正是積分圖的強項,只需要簡單積分查找積分圖就可以完成。
構造尺度空間
同SIFT算法一樣,SURF算法的尺度空間由O組S層組成,不同的是,SIFT算法下一組圖像的長寬均是上一組的一半,同一組不同層圖像之間尺寸一樣,但是所使用的尺度空間因子(高斯模糊系數σ)逐漸增大;而在SURF算法中,不同組間圖像的尺寸都是一致的,不同的是不同組間使用的盒式濾波器的模板尺寸逐漸增大,同一組不同層圖像使用相同尺寸的濾波器,但是濾波器的尺度空間因子逐漸增大。如下圖所示:
特征點過濾並進行精確定位
SURF特征點的定位過程和SIFT算法一致,將經過Hessian矩陣處理的每個像素點(即獲得每個像素點Hessian矩陣的判別式值)與其圖像域(相同大小的圖像)和尺度域(相鄰的尺度空間)的所有相鄰點進行比較,當其大於(或者小於)所有相鄰點時,該點就是極值點。如圖所示,中間的檢測點要和其所在圖像的3×3鄰域8個像素點,以及其相鄰的上下兩層3×3鄰域18個像素點,共26個像素點進行比較。
初步定位出特征點后,再經過濾除能量比較弱的關鍵點以及錯誤定位的關鍵點,篩選出最終的穩定的特征點:
計算特征點主方向
SIFT算法特征點的主方向是采用在特征點鄰域內統計其梯度直方圖,橫軸是梯度方向的角度,縱軸是梯度方向對應梯度幅值的累加,取直方圖bin最大的以及超過最大80%的那些方向作為特征點的主方向。
而在SURF算法中,采用的是統計特征點圓形鄰域內的Harr小波特征,即在特征點的圓形鄰域內,統計60度扇形內所有點的水平、垂直Harr小波特征總和,然后扇形以0.2弧度大小的間隔進行旋轉並再次統計該區域內Harr小波特征值之后,最后將值最大的那個扇形的方向作為該特征點的主方向。該過程示意圖如下:
生成特征描述
在SIFT算法中,為了保證特征矢量的旋轉不變性,先以特征點為中心,在附近鄰域內將坐標軸旋轉θ(特征點的主方向)角度,然后提取特征點周圍4×4個區域塊,統計每小塊內8個梯度方向,這樣一個關鍵點就可以產生128維的SIFT特征向量。
SURF算法中,也是提取特征點周圍4×4個矩形區域塊,但是所取得矩形區域方向是沿着特征點的主方向,而不是像SIFT算法一樣,經過旋轉θθ角度。每個子區域統計25個像素點水平方向和垂直方向的Haar小波特征,這里的水平和垂直方向都是相對主方向而言的。該Harr小波特征為水平方向值之和、垂直方向值之和、水平方向值絕對值之和以及垂直方向絕對之和4個方向。該過程示意圖如下:
把這4個值作為每個子塊區域的特征向量,所以一共有4×4×4=64維向量作為SURF特征的描述子,比SIFT特征的描述子減少了一半。
OpenCV中的SURF算法
跟SIFT一樣,由於專利的原因,SURF目前也需要用低版本的OpenCV進行操作。
代碼與SIFT的類似:
import numpy as np import cv2 import matplotlib.pyplot as plt img = cv2.imread('test32.jpg', 0) surf = cv2.xfeatures2d.SURF_create(30000) kp = surf.detect(img, None) img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4) surf.setUpright(True) surf.setHessianThreshold(40000) kp = surf.detect(img, None) img3 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4) plt.subplot(121), plt.imshow(img2), plt.title('Dstination'), plt.axis('off') plt.subplot(122), plt.imshow(img3), plt.title('Dstination'), plt.axis('off') plt.show()
結果如下:
目前我們也發現了,SIFT與SURF算法都受到了專利保護,在高版本的OpenCV中無法使用,我們在之后會介紹一些免費的算法。