特徵檢測(二):OpenCV中的SIFT尺度不變特徵變化特徵檢測技術

目標

在這一章當中,html

  • 咱們將學習SIFT算法的概念
  • 咱們將學習如何找到SIFT關鍵點和描述符。

理論

在最後幾章中,咱們看到了一些角落探測器,如哈里斯等。它們是旋轉不變的,這意味着,即便圖像旋轉了,咱們也能夠找到相同的角落。這是顯而易見的,由於角落在旋轉的圖像中也是角落。可是縮放呢?若是圖像縮放,角落可能不是角落。例如,請查看下面的簡單圖片。放大同一個窗口時,小窗口內的小圖像中的一個角落是平坦的。因此哈里斯的角落不是規模不變的。python

尺度不變性

所以,2004年,不列顛哥倫比亞大學的D.Lowe在他的論文中提出了一種新的算法 - 尺度不變特徵變換(SIFT),該算法從尺度不變關鍵點獲取特徵圖像特徵,提取關鍵點並計算其描述符。(本文很容易理解,並被認爲是SIFT上最好的資料,因此這個解釋只是本文的一個簡短摘要)算法

SIFT算法主要涉及四個步驟。咱們將逐一看到他們。數組

1.尺度空間極值檢測

從上圖中能夠看出,咱們不能使用相同的窗口來檢測不一樣比例的關鍵點。小角落也行。但要檢測更大的角落,咱們須要更大的窗口。爲此,使用縮放空間濾波。其中,高斯拉普拉斯能夠找到具備各類\西格瑪值的圖像。LoG做爲一個斑點檢測器,能夠檢測因爲變化而產生的各類大小的斑點\西格瑪。總之,\西格瑪做爲縮放參數。例如,在上面的圖像中,低的高斯內核\西格瑪爲小角部提供高值,而高斯內核高度\西格瑪適合較大的角部。所以,咱們能夠在規模和空間中找到局部最大值,這給咱們一個(X,Y,\西格馬)值列表,這意味着在(x,y)\西格瑪規模上存在潛在的關鍵點。函數

可是這個LoG有點貴,因此SIFT算法使用高斯差分,這是LoG的近似值。高斯的差做爲圖像的高斯模糊的用兩種不一樣的差獲得\西格瑪,讓它\西格瑪ķ\西格瑪。這個過程是在高斯金字塔的不一樣八度的圖像中完成的。它在下面的圖像中表示:學習

高斯差分

一旦找到這個DoG,圖像就會在比例和空間上搜索到局部極值。例如,圖像中的一個像素與其8個鄰居以及下一個尺度的9個像素和先前尺度的9個像素相比較。若是它是一個局部極值,這是一個潛在的關鍵點。它基本上意味着這個關鍵點最能體如今這個尺度上。它顯示在下面的圖像中:spa

高斯差分

關於不一樣的參數,給出這能夠歸納爲,八度= 4,等級水平= 5,初始的數目的數目一些經驗數據\西格瑪= 1.6K = \ SQRT {2}等等做爲最佳值。code

2.關鍵點本地化

一旦找到潛在的關鍵點位置,就必須對其進行改進以得到更準確的結果。他們使用泰勒級數展開的尺度空間來得到更精確的極值位置,而且若是這個極值的強度小於閾值(根據紙張爲0.03),它將被拒絕。該閾值在OpenCV中稱爲contrastThresholdhtm

DoG對邊緣有更高的響應,因此邊緣也須要去除。爲此,使用了相似於Harris角點檢測器的概念。他們用2×2 Hessian矩陣(H)來計算市政曲率。咱們從Harris角點檢測器知道,對於邊緣,一個特徵值比另外一個大。因此這裏他們使用了一個簡單的函數對象

若是此比率大於閾值(在OpenCV中稱爲edgeThreshold),則丟棄該關鍵點。在紙上給出10。

所以它消除了任何低對比度關鍵點和邊緣關鍵點,而且仍然存在強烈的興趣點。

3.方向分配

如今爲每一個關鍵點分配一個方向以實現圖像旋轉的不變性。根據規模在關鍵點位置周圍採起鄰居關係,並在該地區計算梯度大小和方向。建立一個方向直方圖,其中36個方框覆蓋360度。(它經過梯度幅度和高斯加權圓窗口\西格瑪等於關鍵點尺度的1.5倍進行加權,得到直方圖中的最高峯值,而且任何高於80%的峯值也被認爲是計算方向,它建立關鍵點具備相同的位置和規模,但方向不一樣,有助於匹配的穩定性。

4.關鍵點描述符

如今建立關鍵點描述符。關鍵點周圍有一個16x16的街區。它分爲16個4x4大小的子塊。對於每一個子塊,建立8個方向直方圖。因此共有128個bin值可用。它被表示爲造成關鍵點描述符的向量。除此以外,還採起了幾項措施來實現對光照變化,旋轉等的魯棒性。

5.關鍵點匹配

兩幅圖像之間的關鍵點經過識別它們最近的鄰居來匹配。但在某些狀況下,第二個最接近的匹配可能很是接近第一個。這多是因爲噪音或其餘緣由。在那種狀況下,採用最近距離與第二近距離的比率。若是它大於0.8,則被拒絕。根據論文,它排除了大約90%的錯誤匹配,而丟棄只有5%的匹配正確。

因此這是SIFT算法的總結。欲瞭解更多細節和理解,強烈建議閱讀原文。記住一件事,這個算法是得到專利的。因此這個算法被包含在OpenCV中的非自由模塊中。

OpenCV中的

如今讓咱們看看OpenCV中提供的SIFT功能。讓咱們從關鍵點檢測開始並繪製它們。首先,咱們必須構建一個SIFT對象。咱們能夠將不一樣的參數傳遞給它,這些參數是可選的,而且在文檔中有很好的解釋。

import cv2
import numpy as np

img = cv2.imread('home.jpg')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

sift = cv2.SIFT()
kp = sift.detect(gray,None)

img=cv2.drawKeypoints(gray,kp)

sift.detect()函數在圖像中查找關鍵點。若是您只想搜索圖像的一部分,則能夠傳遞掩碼。每一個關鍵點都是一個特殊的結構,它具備許多屬性,如它的(x,y)座標,有意義的鄰域的大小,指定其方向的角度,指定關鍵點強度的響應等。

 

OpenCV還提供cv2.drawKeyPoints()函數,用於繪製關鍵點位置上的小圓圈。若是你傳遞一個標誌cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS給它,它將繪製一個尺寸爲關鍵點的圓,它甚至會顯示它的方向。看下面的例子。

img=cv2.drawKeypoints(gray,kp,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imwrite('sift_keypoints.jpg',img)

看到下面的兩個結果:

SIFT關鍵點

如今計算描述符,OpenCV提供了兩種方法。

  1. 既然你已經找到了關鍵點,你能夠調用sift.compute()來計算咱們找到的關鍵點的描述符。例如:kp,des = sift.compute(gray,kp)
  2. 若是您沒有找到關鍵點,可使用函數sift.detectAndCompute()在一個步驟中直接找到關鍵點和描述符。

咱們將看到第二種方法:

sift = cv2.SIFT()
kp, des = sift.detectAndCompute(gray,None)

這裏kp將是一個關鍵點列表,des是一個形狀不規則的數組Number \ _of \ _Keypoints \ times 128

參考:

http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.html

 

轉載註明出處!!!

相關文章
相關標籤/搜索