【翻译: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教程】图像金字塔

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