目录
0 原理 1 OpenCV中的BRIEF 2 OpenCV中的ORB算法
特征点检测完之后的匹配可以参考:https://blog.csdn.net/yukinoai/article/details/89055860
对于一个 OpenCV 的狂热爱好者来说 ORB 最重要的一点就是:它来自“OpenCV_Labs''。这个算法是在 2011 年提出的。在计算开支,匹配效率以 及更主要的是专利问题方面 ORB 算法是是 SIFT 和 SURF 算法的一个很好的 替代品。SIFT 和 SURF 算法是有专利保护的,如果你要使用它们,就可能要花钱。但是 ORB 不需要!!!
ORB 基本是 FAST 关键点检测和 BRIEF 关键点描述器的结合体,并通过很多修改增强了性能。首先它使用 FAST 找到关键点,然后再使用 Harris 角点检测对这些关键点进行排序找到其中的前 N 个点。它也使用金字塔从而产 生尺度不变性特征。但是有一个问题,FAST 算法步计算方向。那旋转不变性 怎样解决呢?作者进行了如下修改。
增加旋转不变性的:
ORB算法计算了以当前角点为中心所在区域的强度加权质心。那么,当前角点的方向向量就是由这个角点指向这个质心的方向。为了提高旋转不变性,还计算了以角点为圆心,半径大小为r的区域的矩(moments),坐标为x,y。
对于描述符,ORB算法使用了BRIEF算法的描述符。但是我们早就了解了BRIEF的描述符在旋转的图像下表现很差劲。所以,ORB根据特征点的方向使用了一种“可控BRIEF”描述符。对于任意特征集,例如在点的二进制检测,定义一个2×n的矩阵S,里面有n个之前找到的特征点,借用之前计算得到的角度,利用旋转矩阵来旋转矩阵S得到,这样就得到了可控的BRIEF描述符。
ORB算法将角度离散化为增量12度一个单位的角度,然后构造一个预先计算BRIEF模式的查找表。只要特征点的方向θθ始终一致,那么正确的特征点的集合就会用来计算描述符。
特征点匹配:BRIEF
BRIEF简介:
我们知道 SIFT 算法使用的是 128 维的描述符。由于它是使用的浮点数,所以要使用 512 个字节。同样 SURF 算法最少使用 256 个字节(64 维描述符)。创建一个包含上千个特征的向量需要消耗大量的内存,在嵌入式等资源 有限的设备上这样是合适的。匹配时还会消耗更多的内存和时间。
但是在实际的匹配过程中如此多的维度是没有必要的。我们可以使用PCA,LDA 等方法来进行降维。甚至可以使用 LSH(局部敏感哈希)将 SIFT 浮点 数的描述符转换成二进制字符串。对这些字符串再使用汉明距离进行匹配。汉 明距离的计算只需要进行 XOR 位运算以及位计数,这种计算很适合在现代的 CPU 上进行。但我们还是要先找到描述符才能使用哈希,这不能解决最初的内存消耗问题。
BRIEF 应运而生。它不去计算描述符而是直接找到一个二进制字符串。这种算法使用的是已经平滑后的图像,它会按照一种特定的方式选取一组像素点 对,然后在这些像素点对之间进行灰度值对比。例如,第一个点对的灰度值分别为 p 和 q。如果 p 小于 q,结果就是 1,否则就是 0。就这样对个点对进行对比得到一个 维的二进制字符串。
可以是 128,256,512。OpenCV 对这些都提供了支持,但在默认情况下是 256(OpenCV是使用字节表示它们的,所以这些值分别对应与 16, 32,64)。当我们获得这些二进制字符串之后就可以使用汉明距离对它们进行匹配了。
非常重要的一点是:BRIEF 是一种特征描述符,它不提供查找特征的方法。 所以我们不得不使用其他特征检测器,比如 SIFT 和 SURF 等。原始文献推荐使用 CenSurE 特征检测器(在OpenCV中称为STAR检测器),这种算法很快。而且 BRIEF 算法对 CenSurE 关键点的描述效果要比 SURF 关键点的描述更好。 简单来说 BRIEF 是一种对特征点描述符计算和匹配的快速方法。这种算 法可以实现很高的识别率,除非出现平面内的大旋转。
BRIEF算法有一个重要的性质就是每一位的特征都有很大的差异,并且差异大小的均值接近0.5。但是一旦它的方向沿着特征点的方向,它就会去掉了这个差异,并且变得更加分散。方差变大使得特征变得更加容易区分,因为它接受了不同的输入。另外一个让人满意的性质是让测试都不相关,因为这样每个测试都会贡献出影响。为了解决上面的问题,ORB使用了一个贪心搜索侧率,在所有可能的二进制测试当中去找到的一个拥有方差值高并且均值接近0.5的特征点,而且是不相关的。这个方法叫做rBRIEF算法。
对于描述符匹配,多探测局部敏感哈希(multi-probe LSH)在传统的LSH算法上有所用提高,并使用在描述符配的算法当中。论文中指出,ORB算法比SURF和SIFT算法更快速,并且ORB描述符的效果比SURF更高。ORB在低功耗设备上是一个不错的选择。
创建BRIEF描述符:
brief = cv2.xfeatures2d.BriefDescriptorExtractor_create(, bytes, use_orientation)
创建 CenSurE 特征检测器(在OpenCV中称为STAR检测器):
star = cv2.xfeatures2d.StarDetector_create(, maxSize, responseThreshold, lineThresholdProjected, lineThresholdBinarized, suppressNonmaxSize)
计算在图像中检测到的一组特征点的描述符:
keypoints, descriptors = brief.compute(image, keypoints)
举个小例子:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('test30.jpg', 0)
plt.subplot(131), plt.imshow(img, cmap='gray'),
plt.title('Origianl'), plt.axis('off')
# STAR检测器
star = cv2.xfeatures2d.StarDetector_create()
# BRIEF抽取器
brief = cv2.xfeatures2d.BriefDescriptorExtractor_create()
# find the keypoints with STAR
kp = star.detect(img, None)
img2 = cv2.drawKeypoints(img, kp, None, color=(255, 0, 0))
plt.subplot(132), plt.imshow(img2, cmap='gray'),
plt.title('STAR'), plt.axis('off')
# 使用BRIEF计算描述符
kp1, des = brief.compute(img, kp)
img3 = cv2.drawKeypoints(img, kp1, None, color=(255, 0, 0))
plt.subplot(133), plt.imshow(img3, cmap='gray'),
plt.title('BRIEF'), plt.axis('off')
plt.show()
# 打印BRIEF尺寸
print(brief.descriptorSize())
# 打印计算后输出符的尺寸
print(des.shape)
创建一个ORB对象:
orb = cv2.ORB_create(, nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize, fastThreshold)
可以使用类似于orb.getScoreType(),orb.setScoreType(ScoreType)查看和更改参数,具体可查看官网:
https://docs.opencv.org/master/db/d95/classcv_1_1ORB.html
最后举一个例子:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('test30.jpg', 0)
# 创建ORB,由于图比较简单,所以设置的关键点数较小,默认500
orb = cv2.ORB_create(nfeatures=200)
# 使用ORB检测特征点
kp = orb.detect(img, None)
# compute the descriptors with ORB
kp, des = orb.compute(img, kp)
# 绘制特征点
img2 = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0)
plt.imshow(img2, cmap='gray'), plt.title('ORB'), plt.axis('off')
plt.show()
结果如下,可以看出所有角点基本都被检测出来了。