【翻譯:OpenCV-Python教程】SURF (Speeded-Up Robust Features) 介紹

⚠️由於自己的拖延症,3.4.3翻到一半,OpenCV發佈了4.0.1了正式版,所以接下來是按照4.0.1翻譯的。

⚠️除了版本之外,其他還是照舊,Introduction to SURF (Speeded-Up Robust Features),原文

目標

在本章中,

  • 我們將看到SURF的基本知識
  • 我們將在OpenCV中看到SURF功能

理論

在上一章,我們看到了用於關鍵點檢測和描述的SIFT算法。但它的速度相對較慢,人們需要一個更加速的版本。在2006年,三個人,Bay H.,Tuytelaars T. 還有 Van Gool L,發表了另外一個論文,"SURF:Speeded Up Robust Features",它引入了一種叫做SURF的新算法。就好像這個算法名字提出的那樣,它是一個SIFT加速以後的版本(speeded-up version of SIFT)。

在SIFT算法中,Lowe(譯者注:上篇裏提到的論文作者之一) 的方案是用高斯差分算子近似計算拉普拉斯-高斯算子。SURF算法則更進一步,選擇使用箱式過濾器來近視計算拉普拉斯-高斯算子。下圖展示了這種近似的演示。這種近似計算有一個很大的優點,盒式過濾器的卷積可以在積分圖像的幫助下非常容易的計算。而且它可以在不同的放縮比下並行進行。而且SURF在放縮和位置上都依賴於海塞矩陣的行列式。

surf_boxfilter.jpg

而對於方向指定,SURF使用在水平和垂直方向上對半徑爲6s(譯者注:這裏s應該是指放縮比)領域內的微波響應。適當的高斯權重也應用在它上面。然後它們被繪製在如下圖所示的空間中。主導的方向通過計算所有60度滑動方向窗口內響應的總和來估計算。

有趣的是,微波響應在任何放縮比上都可以用積分圖像輕易的算出來。對於許多應用場景,旋轉不變性不是必需的,因此不需要找到這個方向,從而加快了這個過程。SURF 這樣的一個功能被稱作是 Upright-SURF 或者是 U-SURF。It improves speed and is robust upto ±15°(譯者注,這句保留的原文,大意是說它提升了速度和保證了健壯性,但沒太明白±和°這個兩個符號的意義是什麼)。

OpenCV根據標識upright的不同,將兩者都支持,如果標識爲0,則計算方向,如果爲1,則不計算方向並且速度更快。(譯者注:如果不需要旋轉不變性就傳入1)。

surf_orientation.jpg

爲了描述功能,SURF使用水平和垂直方向的微波響應(再重申,使用積分圖像使事情更容易)。取一個圍繞着關鍵點的 20sX20s 的鄰域,這裏s是指大小。

A neighbourhood of size 20sX20s is taken around the keypoint where s is the size. It is divided into 4x4 subregions. For each subregion, horizontal and vertical wavelet responses are taken and a vector is formed like this, v=(∑dx,∑dy,∑|dx|,∑|dy|). This when represented as a vector gives SURF feature descriptor with total 64 dimensions. Lower the dimension, higher the speed of computation and matching, but provide better distinctiveness of features.

For more distinctiveness, SURF feature descriptor has an extended 128 dimension version. The sums of dx and |dx| are computed separately for dy<0 and dy≥0. Similarly, the sums of dy and |dy| are split up according to the sign of dx , thereby doubling the number of features. It doesn't add much computation complexity. OpenCV supports both by setting the value of flag extended with 0 and 1 for 64-dim and 128-dim respectively (default is 128-dim)

Another important improvement is the use of sign of Laplacian (trace of Hessian Matrix) for underlying interest point. It adds no computation cost since it is already computed during detection. The sign of the Laplacian distinguishes bright blobs on dark backgrounds from the reverse situation. In the matching stage, we only compare features if they have the same type of contrast (as shown in image below). This minimal information allows for faster matching, without reducing the descriptor's performance.

surf_matching.jpg

image

In short, SURF adds a lot of features to improve the speed in every step. Analysis shows it is 3 times faster than SIFT while performance is comparable to SIFT. SURF is good at handling images with blurring and rotation, but not good at handling viewpoint change and illumination change.

SURF in OpenCV

OpenCV provides SURF functionalities just like SIFT. You initiate a SURF object with some optional conditions like 64/128-dim descriptors, Upright/Normal SURF etc. All the details are well explained in docs. Then as we did in SIFT, we can use SURF.detect(), SURF.compute() etc for finding keypoints and descriptors.

First we will see a simple demo on how to find SURF keypoints and descriptors and draw it. All examples are shown in Python terminal since it is just same as SIFT only.

>>> img = cv.imread('fly.png',0)

# Create SURF object. You can specify params here or later.

# Here I set Hessian Threshold to 400

>>> surf = cv.xfeatures2d.SURF_create(400)

# Find keypoints and descriptors directly

>>> kp, des = surf.detectAndCompute(img,None)

>>> len(kp)

699

1199 keypoints is too much to show in a picture. We reduce it to some 50 to draw it on an image. While matching, we may need all those features, but not now. So we increase the Hessian Threshold.

# Check present Hessian threshold

>>> print( surf.getHessianThreshold() )

400.0

# We set it to some 50000. Remember, it is just for representing in picture.

# In actual cases, it is better to have a value 300-500

>>> surf.setHessianThreshold(50000)

# Again compute keypoints and check its number.

>>> kp, des = surf.detectAndCompute(img,None)

>>> print( len(kp) )

47

It is less than 50. Let's draw it on the image.

>>> img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)

>>> plt.imshow(img2),plt.show()

See the result below. You can see that SURF is more like a blob detector. It detects the white blobs on wings of butterfly. You can test it with other images.

surf_kp1.jpg

image

Now I want to apply U-SURF, so that it won't find the orientation.

# Check upright flag, if it False, set it to True

>>> print( surf.getUpright() )

False

>>> surf.setUpright(True)

# Recompute the feature points and draw it

>>> kp = surf.detect(img,None)

>>> img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)

>>> plt.imshow(img2),plt.show()

See the results below. All the orientations are shown in same direction. It is faster than previous. If you are working on cases where orientation is not a problem (like panorama stitching) etc, this is better.

surf_kp2.jpg

image

Finally we check the descriptor size and change it to 128 if it is only 64-dim.

# Find size of descriptor

>>> print( surf.descriptorSize() )

64

# That means flag, "extended" is False.

>>> surf.getExtended()

False

# So we make it to True to get 128-dim descriptors.

>>> surf.setExtended(True)

>>> kp, des = surf.detectAndCompute(img,None)

>>> print( surf.descriptorSize() )

128

>>> print( des.shape )

(47, 128)

Remaining part is matching which we will do in another chapter.

Additional Resources

Exercises


上篇:【翻譯:OpenCV-Python教程】SIFT(Scale-Invariant Feature Transform) 介紹

下篇:【翻譯:OpenCV-Python教程】圖像金字塔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章