目标
- 学习 ORB 算法的基础
原理
对于一个 OpenCV 的狂热爱好者来说 ORB 最重要的一点就是: 它来自“OpenCV_Labs''。这个算法是在 2011 年提出的。 在计算开支,匹配效率以及更主要的是专利问题方面 ORB 算法是是 SIFT 和 SURF 算法的一个很好的替代品。 SIFT 和 SURF 算法是有专利保护的, 如果要使用它们,就可能要花钱。 但是 ORB 不需要!!!
ORB 基本是 FAST 关键点检测和 BRIEF 关键点描述器的结合体, 并通过很多修改增强了性能。 首先它使用 FAST 找到关键点, 然后再使用 Harris角点检测对这些关键点进行排序找到其中的前 N 个点。 它也使用金字塔从而产生尺度不变性特征。 但是有一个问题,FAST 算法步计算方向。 那旋转不变性怎样解决呢?作者进行了如下修改。
它使用灰度矩的算法计算出角点的方向。 以角点到角点所在(小块)区域质心的方向为向量的方向。 为了进一步提高旋转不变性, 要计算以角点为中心半径为 r 的圆形区域的矩,再根据矩计算除方向。
对于描述符,ORB 使用的是 BRIEF 描述符。 但是已经知道 BRIEF对与旋转是不稳定的。 所以在生成特征前, 要把关键点领域的这个 patch的坐标轴旋转到关键点的方向。
对于位置(x i,y i)上n个二进制测试的任何特征集, 定义一个2×n矩阵S,其中包含这些像素的坐标。 然后使用面片θ的方向,找到其旋转矩阵并旋转S以获得转向(旋转)版本Sθ。 ORB将角度离散化为2π/ 30(12度)的增量, 并构造了预先计算的Brief模式的查找表。 只要关键点方向\ theta在所有视图中都是一致的, 就将使用正确的点集Sθ计算其描述符。 摘要具有一个重要的特性,即每个位特征具有较大的方差, 且均值接近0.5。 但是,一旦将其沿关键点方向定向, 它就会失去此属性并变得更加分散。 高方差使功能更具区分性,因为它对输入的响应不同。 另一个理想的特性是使测试不相关, 因为从那时起每个测试都会对结果有所贡献。 为了解决所有这些问题,ORB在所有可能的二进制测试中进行贪婪搜索, 以找到方差高且均值接近0.5且不相关的测试。结果称为rBRIEF。 对于描述符匹配,使用了对传统LSH进行改进的多探针LSH。 该论文说,ORB比SURF快得多,SIFT和ORB描述符比SURF更好。 在全景拼接等低功耗设备中,ORB是一个不错的选择。
实验证明,BRIEF 算法的每一位的均值接近 0.5,并且方差很大。
steered_BRIEF
算法的每一位的均值比较分散(均值为 0.5,0.45,0.35... 等值的关键点数相当),
这导致方差减小。
数据的方差大的一个好处是:使得特征更容易分辨。
为了对 steered_BRIEF 算法使得特征的方差减小的弥补和减小数据间的相关性,
用一个学习算法(learning method)选择二进制测试的一个子集。
在描述符匹配中使用了对传统 LSH 改善后的多探针 LSH。
文章中说 ORB算法比 SURF 和 SIFT 算法快的多,
ORB 描述符也比 SURF 好很多。ORB是低功耗设备的最佳选择。
OpenCV 中的 ORB 算法
和前面一样,首先要使用函数 cv3.ORB()
或者 feature2d
通用接口创建一个 ORB 对象。
它有几个可选参数。
最有用的应该是 nfeature
,默认值为 500,它表示了要保留特征的最大数目。
scoreType 设置使用 Harris打分还是使用 FAST 打分对特征进行排序(默认是使用 Harris 打分)等。
参数 WTA_K
决定了产生每个 oriented_BRIEF
描述符要使用的像素点的数目。
默认值是 2,也就是一次选择两个点。
在这种情况下进行匹配,要使用 NORM_HAMMING
距离。
如果 WTA_K
被设置成 3 或 4,那匹配距离就要设置为 NORM_HAMMING2
。
下面是一个使用 ORB 的简单代码。
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('simple.jpg',0)
# Initiate STAR detector
orb = cv2.ORB()
# find the keypoints with ORB
kp = orb.detect(img,None)
# compute the descriptors with ORB
kp, des = orb.compute(img, kp)
# draw only keypoints location,not size and orientation
img2 = cv2.drawKeypoints(img,kp,color=(0,255,0), flags=0)
plt.imshow(img2),plt.show()