本章将介绍 ORB 的基础知识。
理论基础
对于OpenCV爱好者而言,ORB最值得关注的一点是它源自“OpenCV实验室”。 该算法由Ethan Rublee、Vincent Rabaud、Kurt Konolige和Gary R. Bradski在2011年的论文《ORB: SIFT与SURF的高效替代方案》中提出。 如标题所示,ORB在计算成本、匹配性能以及专利限制(关键因素)上均为SIFT和SURF的优秀替代方案。 需注意的是,SIFT和SURF受专利保护,使用时需付费,而ORB则完全免费!
ORB本质上是FAST关键点检测器与BRIEF描述符的融合,并通过多项改进以提升性能。其工作流程如下: 使用FAST算法定位关键点;通过Harris角点度量筛选出其中最优的N个点;采用图像金字塔生成多尺度特征。 但FAST本身不计算方向,如何实现旋转不变性?作者通过以下改进解决了这一问题。
算法首先计算以角点为中心的图像块的强度加权质心,角点到该质心的向量方向即为关键点的方向。 为了增强旋转不变性,计算图像矩时,仅考虑以角点为中心、半径为 $r$ (图像块大小)的圆形区域内的 x 和 y 坐标。
ORB采用BRIEF描述符,但BRIEF本身对旋转敏感。为此,ORB根据关键点的方向对BRIEF进行定向调整(Steered BRIEF)。具体步骤如下:
对于包含 $n$ 个二进制测试的特征集,其像素坐标 $(x_i, y_i)$ 构成一个 $2 \times n$ 的矩阵 $S$ 。 根据关键点方向 $\theta$ 计算旋转矩阵,并对 $S$ 进行旋转,得到调整后的矩阵 $S_\theta$ 。 ORB将角度离散化为 $2 \pi /30$(即12度)的增量,并预先计算不同方向的BRIEF模式,构建查找表。 只要关键点的方向 $\theta$ 在不同视角下保持一致,即可通过查找表快速获取对应的 $S_\theta$ 点集,进而生成具有旋转鲁棒性的描述符。
BRIEF有一个重要特性:每个比特特征都具有较大的方差且均值接近0.5。 但当其沿关键点方向定向后,会失去这一特性并变得更加分散。高方差使特征更具区分度,因为它对输入能产生差异化响应。 另一个理想特性是测试间互不相关,这样每个测试都能对结果产生独立贡献。 为解决这些问题,ORB通过贪婪算法从所有可能的二进制测试中筛选出同时满足高方差、均值接近0.5且互不相关的测试,最终结果称为rBRIEF。
在描述符匹配方面,ORB采用了改进传统LSH的多探针局部敏感哈希算法。论文指出ORB比SURF和SIFT更快,且ORB描述符性能优于SURF。 ORB是低功耗设备(如全景拼接等场景)的理想选择。
OpenCV 中的 ORB 实现
通常我们通过cv2.ORB()
函数或feature2d通用接口创建ORB对象。
其包含多个可选参数,最常用的有:nFeatures
(保留特征的最大数量,默认500)、scoreType(特征排序采用Harris分数或FAST分数,默认Harris分数)等。
另一个参数WTA_K决定生成定向BRIEF描述符的采样点数,默认值为2(即每次选取两个点)。
此时匹配使用NORM_HAMMING
距离。若WTA_K
设为3或4,则采用NORM_HAMMING2
距离进行匹配。
以下为演示 ORB 用法的简易代码。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('/data/cvdata/simple.jpg',0)
# Initiate ORB detector
orb = cv.ORB_create()
# 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 = cv.drawKeypoints(img, kp, None, color=(0,255,0), flags=0)
plt.imshow(img2), plt.show()
(<matplotlib.image.AxesImage at 0x7f0673926810>, None)