OpenCV-Python SURF簡介

目標

在這一章當中,

  • 我們將瞭解SURF的基礎
  • 我們將在OpenCV中看到SURF函數

理論

在上一章中,我們看到了SIFT用於關鍵點檢測和描述符。但相對緩慢,人們需要更多的加速版本。2006年,三個人,H .Tuytelaars,T. and Van Gool,L,發表了另一篇論文,“SURF:加速健壯的特徵”,引入了一種名為“SURF”的新算法。正如名字所表明的那樣,它是一個加速版本的SIFT。

在SIFT中,Lowe用高斯差近似高斯的拉普拉斯算子來尋找尺度空間。SURF走得更遠,使用Box Filter近似LoG。下圖顯示了這種近似值的演示。這種近似的一大優點是,藉助積分圖像可以輕鬆地計算出帶盒濾波器的卷積。並且可以針對不同規模並行執行。SURF還依賴於Hessian矩陣的行列式來確定尺度和位置。

OpenCV-Python SURF簡介 | 四十

對於方向分配,SURF在水平和垂直方向上對大小為6s的鄰域使用小波響應。適當的高斯權重也適用於它。然後將它們繪製在下圖所示的空間中。通過計算角度為60度的滑動方向窗口內所有響應的總和,可以估算主導方向。有趣的是,小波響應可以很容易地使用積分圖像在任何規模下發現。對於許多應用,不需要旋轉不變性,因此無需查找此方向,從而加快了過程。SURF提供了稱為Upright-SURF或U-SURF的功能。它提高了速度,並具有高達$pm 15^{circ}$的魯棒性。OpenCV根據標誌支持兩種方式。如果為0,則計算方向。如果為1,則不計算方向並且速度更快。

OpenCV-Python SURF簡介 | 四十

對於功能描述,SURF在水平和垂直方向上使用小波響應(同樣,使用積分圖像使事情變得更容易)。在s是大小的關鍵點周圍採用大小為20sX20s的鄰域。它分為4x4子區域。對於每個子區域,獲取水平和垂直小波響應,並像這樣形成向量,$v =(sum dx,sum dy,sum |dx|,sum |dy|)$。當表示為向量時,這將為SURF特徵描述符提供總共64個維度。尺寸越小,計算和匹配速度越快,但特徵的區分性更好。

為了更加獨特,SURF特徵描述符具有擴展的128維版本。dx和$|dx|$的和分別針對$dy < 0$ 和 $dy≥0$進行計算。同樣,$dy$和$|dy|$的總和 根據$dx$的符號進行拆分,從而使特徵數量加倍。它不會增加太多的計算複雜性。OpenCV通過將分別為64-dim和128-dim(默認值為128-dim)的標誌的值設置為0和1來支持這兩者(默認為128-dim)。

另一個重要的改進是對基礎興趣點使用了Laplacian算符(海森矩陣的跡)。它不增加計算成本,因為它已在檢測期間進行了計算。拉普拉斯算子的標誌將深色背景上的明亮斑點與相反的情況區分開。在匹配階段,我們僅比較具有相同對比類型的特徵(如下圖所示)。這些最少的信息可加快匹配速度,而不會降低描述符的性能。

OpenCV-Python SURF簡介 | 四十

簡而言之,SURF添加了許多功能來提高每一步的速度。分析表明,它的速度是SIFT的3倍,而性能卻與SIFT相當。SURF擅長處理具有模糊和旋轉的圖像,但不擅長處理視點變化和照明變化。

OpenCV中的SURF

OpenCV提供類似於SIFT的SURF功能。您可以使用一些可選條件(例如64 / 128-dim描述符,Upright / Normal SURF等)來啟動SURF對象。所有詳細信息在docs中都有詳細說明。然後,就像在SIFT中所做的那樣,我們可以使用SURF.detect(),SURF.compute()等來查找關鍵點和描述符。

首先,我們將看到一個有關如何找到SURF關鍵點和描述符並進行繪製的簡單演示。所有示例都在Python終端中顯示,因為它與SIFT相同。

<code>>>> img = cv.imread('fly.png',0)# 創建SURF對象。你可以在此處或以後指定參數。# 這裡設置海森矩陣的閾值為400>>> surf = cv.xfeatures2d.SURF_create(400)# 直接查找關鍵點和描述符>>> kp, des = surf.detectAndCompute(img,None)>>> len(kp) 699/<code>

圖片中無法顯示1199個關鍵點。我們將其減少到50左右以繪製在圖像上。匹配時,我們可能需要所有這些功能,但現在不需要。因此,我們增加了海森閾值。

<code># 檢查海森矩陣閾值>>> print( surf.getHessianThreshold() )400.0# 我們將其設置為50000。記住,它僅用於表示圖片。 # 在實際情況下,最好將值設為300-500>>> surf.setHessianThreshold(50000)# 再次計算關鍵點並檢查其數量。>>> kp, des = surf.detectAndCompute(img,None)>>> print( len(kp) )47/<code> 

它小於50。讓我們在圖像上繪製它。

<code>>>> img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)>>> plt.imshow(img2),plt.show()/<code>

請參閱下面的結果。您可以看到SURF更像是斑點檢測器。它檢測到蝴蝶翅膀上的白色斑點。您可以使用其他圖像進行測試。

OpenCV-Python SURF簡介 | 四十

現在,我想應用U-SURF,以便它不會找到方向。

<code># 檢查flag標誌,如果為False,則將其設置為True>>> print( surf.getUpright() )False>>> surf.setUpright(True)# 重新計算特徵點並繪製>>> kp = surf.detect(img,None)>>> img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)>>> plt.imshow(img2),plt.show()/<code> 

參見下面的結果。所有的方向都顯示在同一個方向上。它比以前更快了。如果你工作的情況下,方向不是一個問題(如全景拼接)等,這是更好的。

OpenCV-Python SURF簡介 | 四十

最後,我們檢查描述符的大小,如果只有64維,則將其更改為128。

<code># 找到算符的描述>>> print( surf.descriptorSize() )64# 表示flag “extened” 為False。>>> surf.getExtended() False# 因此,將其設為True即可獲取128個尺寸的描述符。>>> surf.setExtended(True)>>> kp, des = surf.detectAndCompute(img,None)>>> print( surf.descriptorSize() )128>>> print( des.shape )(47, 128)/<code>

其餘部分是匹配的,我們將在另一章中進行匹配。


分享到:


相關文章: