在OpenCV里使用SURF

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/caimouse/article/details/102658887

目标:学习SURF基本知识

 

理论:

在前面学习过SIFT,明白了关键点检测和描述,但是SIFT的计算量比较大,并且运行有点慢,因此人们开始思考能否进行改善,让速度更快一些。在2006年,Bay,H.,Tuytelaars,T. 和 Van Gool,L发表论文《SURF: Speeded Up Robust Features》,在这里引用一个新的算法,叫做SURF,它是一种加速版本的SIFT。

在SIFT里,采用DoG来替换LoG实现一些加速,而在SURF里使用窗口平滑来替换LoG,下图就是用来说明窗口平滑怎么样起作用:

上图左边是高斯二阶微分结果,右边是采用窗口平滑Box Filter近似。使用这个滤波之后,有一个大优势:可以采用积分图像来替换卷积运算,并且可以平行处理不同尺度空间里的图片,而在SIFT里每一层图像依赖上一层图像,不能进行并行处理。并且SURF计算关键点的尺度和位置也只是依赖与 Hessian 矩阵行列式。

在方向分配方面,为了保证旋转不变性,首先以特征点为中心,计算半径为6s(S为特征点所在的尺度值)的邻域内的点在z、y方向的Haar小波(Haar小波边长取4s)响应,并给这些响应值赋高斯权重系数,使得靠近特征点的响应贡献大,而远离特征点的响应贡献小,其次将60。范围内的响应相加以形成新的矢量,遍历整个圆形区域,选择最长矢量的方向为该特征点的主方向。这样,通过特征点逐个进行计算,得到每一个特征点的主方向。

关键点描述方面,SURF采用计算图像的垂直和水平方向的Haar小波响应(用积分图像计算更加容易)。在一个矩形的区域内,以特征点为中心,沿主方向将 20s*20s 的图像划分成 4*4 个子块,每个子块利用尺寸 2s 的 Haar 小波模版进行响应计算,然后对响应值进行统计,组成向量 。这个描述符的长度为 64。降低的维度可以加速计算和匹配,但又能提供更容易区分的特征。为了增加特征点的独特性,SURF 还提供了一个加强版 128 维的特征描述符。当 dy 大于 0 和小于 0 时分别对 dx 和 |dx| 的和进行计算,计算 dy和 |dy| 时也进行区分,这样获得特征就会加倍,但又不会增加计算的复杂度。OpenCV 同样提供了这种功能,当参数 extended 设置为 1 时为 128 维,当参数为 0 时为 64 维,默认情况为 128 维。在检测特征点的过程中计算了 Hessian 矩阵的行列式,与此同时,计算得到了 Hessian 矩阵的迹,矩阵的迹为对角元素之和。

 

按照亮度的不同,可以将特征点分为两种,第一种为特征点迹其周围小邻域的亮度比背景区域要亮, Hessian 矩阵的迹为正;另外一种为特征点迹其周围小邻域的亮度比背景区域要暗, Hessian 矩阵为负值。根据这个特性,首先对两个特征点的 Hessian 的迹进行比较。如果同号,说明两个特征点具有相同的对比度;如果异号的话,说明两个特征点的对比度不同,放弃特征点之间的后续的相似性度量。只比较相同亮度的点,如下图:

对于SIRF和SURF进行比较,可见SURF在每一步里都加速了运算速度。简单来说 SURF 算法采用了很多方法来对每一步进行优化从而提高速度。分析显示在结果效果相当的情况下 SURF 的速度是 SIFT 的 3 倍。 SURF 处理具有模糊和旋转的图像有优势,但缺点是处理视角变化和光照变化的图像不足。

from __future__ import print_function

import cv2 as cv

import numpy as np

import argparse



parser = argparse.ArgumentParser(description='Code for Feature Detection tutorial.')

parser.add_argument('--input1', help='Path to input image 1.', default='box.png')

parser.add_argument('--input2', help='Path to input image 2.', default='box_in_scene.png')

args = parser.parse_args()



img1 = cv.imread(cv.samples.findFile(args.input1), cv.IMREAD_GRAYSCALE)

img2 = cv.imread(cv.samples.findFile(args.input2), cv.IMREAD_GRAYSCALE)

if img1 is None or img2 is None:

    print('Could not open or find the images!')

    exit(0)



#-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors

minHessian = 400

detector = cv.xfeatures2d_SURF.create(hessianThreshold=minHessian)

keypoints1, descriptors1 = detector.detectAndCompute(img1, None)

keypoints2, descriptors2 = detector.detectAndCompute(img2, None)



#-- Step 2: Matching descriptor vectors with a brute force matcher

# Since SURF is a floating-point descriptor NORM_L2 is used

matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)

matches = matcher.match(descriptors1, descriptors2)



#-- Draw matches

img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)

cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)



#-- Show detected matches

cv.imshow('Matches', img_matches)



cv.waitKey()

https://blog.csdn.net/caimouse/article/details/51749579

猜你喜欢

转载自blog.csdn.net/caimouse/article/details/102658887