OpenCV-Python系列之BRIEF算法
之前讨论过的SIFT算法以及SURF算法由于受到了专利的保护,在高版本的OpenCV中是没法使用的,这就有些强人所难了,但今天我们介绍一种算法,不仅更加简单,而且是免费使用的。
原理
在SIFT算法使用128维的描述符,因为使用float类型描述,所以需要512字节的内存。
在SURF算法中,以64维描述符来计算,至少需要256字节的内存。
在创建一个含有数千个特征的向量会消耗大量的内存,这种情况在资源的有限的设备上不实用,尤其是嵌入式设备。 此外,它们计算时间也非常漫长。
但是在实际的匹配过程中,不是所有的维数都需要。我们可以使用一些方法来对维数进行压缩,例如PCA(主成分分析)算法,和LDA(线性判别式分析)算法等等。甚至使用LSH(局部敏感哈希)算法,把SIFT的描述符从浮点数类型转化成二进制字符串,然后对这些字符串使用汉明距离来进行匹配。由于韩明距离的计算方法只需要使用亦或位运算和位计数,在带有SSE指令的现代的CPU上计算速度很快。
BRIEF算法由此产生,该算法提供了一个很简介的手段在不寻找描述符的情况下,去寻找二进制字符串。
大致过程如下:
1、为减少噪声干扰,先对图像进行高斯滤波(方差为2,高斯窗口为9x9)
2、以特征点为中心,取SxS的邻域大窗口。在大窗口中随机选取一对(两个)5x5的子窗口,比较子窗口内的像素和(可用积分图像完成),进行二进制赋值.(一般S=31)
其中,p(x),p(y)分别随机点x=(u1,v1),y=(u2,v2)所在5x5子窗口的像素和.
3、在大窗口中随机选取N对子窗口,重复步骤2的二进制赋值,形成一个二进制编码,这个编码就是对特征点的描述,即特征描述子.(一般N=256)
非常重要的一点是:BRIEF 是一种特征描述符,它不提供查找特征的方法。所以我们不得不使用其他特征检测器,比如 SIFT 和 SURF 等。原始文献推荐使用 CenSurE 特征检测器,这种算法很快。而且 BRIEF 算法对 CenSurE关键点的描述效果要比 SURF 关键点的描述更好。
简单来说 BRIEF 是一种对特征点描述符计算和匹配的快速方法。这种算法可以实现很高的识别率,除非出现平面内的大旋转。
接下来我们来进行代码演示,使用示例图片:
首先创建BRIEF描述符:
brief = cv2.xfeatures2d.BriefDescriptorExtractor_create(, bytes, use_orientation)
bytes:描述符中的值,用字节表示可取16, 32 (default) or 64,代表的值为 128,256,512
use_orientation:使用特征点方向的示例模式,默认情况下禁用。
创建 CenSurE 特征检测器(在OpenCV中称为STAR检测器):
star = cv2.xfeatures2d.StarDetector_create(, maxSize, responseThreshold, lineThresholdProjected, lineThresholdBinarized, suppressNonmaxSize)
maxSize:最大尺寸,默认45
responseThreshold:响应阈值,默认30
lineThresholdProjected:线性投影阈值,默认10
lineThresholdBinarized:线性二值化阈值,默认8
suppressNonmaxSize:非极大抑制参数,默认5
计算在图像中检测到的一组特征点的描述符:
kp, des = brief.compute(img, kp)
image:输入图像
kp:输入特征点集合。无法计算描述符的特征点将被删除。有时可以添加新的特征点,例如:SIFT具有多个主导方向的重复特征点(对于每个方向)。
des:输出计算后的描述符,是一个矩阵。
def BRIEF(img): # Initiate FAST detector star = cv2.xfeatures2d.StarDetector_create() # Initiate BRIEF extractor brief = cv2.xfeatures2d.BriefDescriptorExtractor_create() # find the keypoints with STAR kp = star.detect(img, None) # compute the descriptors with BRIEF kp, des = brief.compute(img, kp) print(brief.descriptorSize()) print(des.shape) # draw only keypoints location,not size and orientation img2 = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0) plt.imshow(img2), plt.show()
结果:
进而看输出结果:
事实上,BRIEF虽然免费,不过由于其本身并不具有特征检测的功能,并且BRIEF的描述符在旋转的图像下表现很差劲,所以在之后我们将会介绍更加强大的同时速度更快的算法。