1

ORB(Oriented FAST and Rotated BRIEF)可用来替代SIFT(或SURF),它对图像更具有抗噪特性,是一种特征检测高效算法,其速度满足实时要求,可用于增强图像匹配应用。
ORB的算法基于FAST角检测(Features from accelerated segment test)BRIEF(Binary Robust Independent Elementary Features)特征描述符,这也是它名字的由来。

FAST角检测

FAST角检测比之前我们介绍过的Harris角检测、SIFT特征点检测(使用高斯差)都要快,后两者关注的是高质量(精准、稳定性高)的特征检测,但计算复杂,而FAST关注的是实时应用,比如即时检测定位(检测视频中的移动物体),而且要在计算资源有限的智能手机上使用。

FAST检测角点的过程真的很简单:
图片描述

  1. 以灰度图像为例,从原图像中选一个点(设为p),如上图,放大显示p点周围的像素

  2. 给定一个阈值,比如设为p点灰度值的20%

  3. 以p为圆心,划出半径为3的圆,考虑落在圆周上的16个像素的值,若这16个像素连续N(N一般为12)个符合阈值,则认为p为兴趣点(角点)

  4. 为让上面的判断更快,可以先计算序号为1、5、9、13的4个像素(如图),这4个像素至少要有3个符合阈值,才有可能存在连续12个像素满足阈值,才有必要检测其它像素。

  5. 对原图像每一个像素,重复以上计算过程,最终得出所有兴趣点。

FAST算法存在的问题:

  1. N如果小于12,得出来的结果不是很理想,N建议值为12

  2. 只把圆周上的16个像素作为兴趣点的信息贡献(不一定适合大多数使用场景)

  3. 检测出的兴趣点,存在很多相邻的兴趣点(需要排除,选其一即可)

但现在这些问题可以通过机器学习的方法来解决。

skimage库包含了FAST算法实现:

skimage.feature.corner_fast(image, n=12, threshold=0.15)

BRIEF特征描述

如果用一个二进制串(binary strings)作为兴趣点描述符(interest point descriptor,下很简称IPD),不仅存储空间低,而且比较IPD,可以转化为比较汉明距离(hamming distance),汉明距离为两个二进制串不同位的个数,用异或就可以简单高效的完成计算。

BRIEF算法并不包含兴趣点检测(检测可以用FAST或Harris等方法),它只是提出了一种二进制串IPD,只需要256bit,甚至128bit就可以取得较好的匹配效果。在提取BRIEF二进制串之前,需要先对图像进行高斯滤波(有关高斯滤波,前面笔记已详细介绍,此不再述)以去除噪声,然后使用其它方法检测出兴趣点,以其中一个兴趣点为例:考虑以兴趣点为中心的S×S大小的矩形图像块,以两个像素值(设为p1和p2)为1对,随机选N对(N为128或256或512),对每对(p1,p2)进行测试,比较p1和p2,若p1<p2,结果为1,否则为0,此称为二值测试(binary test),将结果作为1bit存储,N对的结果连在一起就组成了一个N bit的二进制串。

如何选取N对像素?BRIEF给出了5种方法,并认为第2种效果最好:
图片描述

  1. 均匀采样(uniformly sampled)

  2. 以图像中心进行高斯分布采样,即越接近中心点的像素点将被优先选择

  3. 使用两个不同sigma的高斯分布,设为G1和G2,所有p1用G1采样,所有p2用G2采样

  4. 使用粗极坐标网格(coarse polar gird)的离散位置随机采样(原文:randomly sampled from discrete location of a coarse polar gird)

  5. 所有p1都固定为图像块的中心像素,所有p2用粗极坐标网格采样(每格采一像素)

对后两种方法提到的粗极坐标网格,看一下图就不难理解了:
图片描述

需要注意的是,BRIEF描述符没有考虑多尺度,虽然对亮度、模糊、视角失真有一定的不变性,但它没有考虑旋转,容易受旋转影响。

ORB

ORB其实综合了FAST、Harris角测量、图像矩、BRIEF等理论方法,并为实时计算提供解决方案。

ORB对FAST的补充

  1. 因FAST检测出的邻近兴趣点通常会有很多,这些邻近兴趣点其实都位于同一个角点处。ORB的解决方法是:使用阈值过滤,并借助Harris角测量得到角点。

  2. FAST没有考虑图像缩放,ORB构造了不同缩放尺寸的图像金字塔(详细参考SIFT),对每一层图像应用上述方法检测角点。

  3. FAST检测的角点没有考虑方向,ORB借助图像中心矩 计算方向。

图像矩(image moment)
*图像矩(或称几何矩)是由Hu(Visual pattern recognition by moment invariants)在1962年提出的。矩给出了对图像形状的一种度量。理解矩的概念有点困难,下面只是简要说明ORB用到的中心矩,有兴趣的读者,可自行深入了解。

一个图像块I的p+q阶矩的公式为:
图片描述

其中,I(x,y)表示xy坐标所在像素的亮度。
0阶矩(记m00,用p=0, q=0代入上述公式)其实就是所有I(x,y)的和,即所有像素的亮度之和,也称为图像的总质量(mass)。

用p=1,q=0代入公式,得到相对x的一阶矩,记为m10,如果用m10除以m00,便可以得到x的平均值,也称为中心值。同理,用p=0,q=1代入公式,得到相对y的一阶矩,记为m01,用m01除以m00便得到y的中心值,x的中心值和y的中心值构成了图像亮度的 中心矩(centroid),记为C:
图片描述

中心矩有时也称为质心,在二值图像中,可用来代表形状的中心。如果我们构建一个从角点到中心矩的向量,那么此向量与X轴的角度为:
图片描述

θ即为图像块的亮度方向,先旋转到此方向再计算得出的兴趣点描述符,便具有旋转不变性。
测试表明,在图像噪声较大的情况下,此方法对旋转相对SIFT更稳定。

steered BRIEF
ORB使用BRIEF建议的第二种采样方法(即以图像中心进行高斯分布采样,IPD长度使用256bit),然后在BRIEF基础上增加了旋转的描述以及快速的计算方法,这种方法被称为steered BRIEF

BRIEF在选取点对(采样)之前,需要对图像应用高斯滤波,而ORB则不用,取而代之的是使用以选取点为中心的5×5区域像素平均值,并用积分图(integral image)来计算。积分图,又称总和面积表(summed area table,简称SAT),是一个快速且有效的对一个网格的矩形子区域中计算和的数据结构和算法。

因引入了旋转,采样的点对坐标也需要旋转变换。将采样点对坐标组成矩阵S:
图片描述

旋转矩阵(Rotation matrix)设为Rθ:
Rθ = 58ee3d6d55fbb2fb006f83ce4a4a20a44723dca2.jpg

则通过:
Sθ = S*Rθ
将S的每个列向量(x,y)关于原点逆时针旋转θ,为加速计算,将360度以12度为单位离散为30份,事先计算好30个Sθ作为查找表,之后就可以节省坐标变换这一步计算了。

看起来此方法不错,可惜的是,它的匹配效果比BRIEF差一截,通过大量样本分析发现,BRIEF描述符有一个很好的特性,就是每一位bit对应的点对之间表现出方差大、相关性小,而且同一位置bit的平均值接近0.5。但是steered BRIEF因进行了坐标旋转,损失了这个特性,导致不同特征点描述符差别不大,相关性高,不利于匹配。所以ORB开发了另一种选取点对和计算IPD的方法——rBRIEF,此方法比steered BRIEF优很多。

rBRIEF
这才是ORB最为关键的部分,一是因为有点难懂(细节之处论文没有讲清楚),二是因为用了这个方法,使得ORB相较BRIEF和SURF表现突出。
rBRIEF是一种需要学习的算法,学习分两步:

第一步,建立训练集,提取二值测试

  • 论文例子使用的样本数为30万,即30万个特征点及其对应的(31×31)图像块,图像数据来自PASCAL 2006 dataset

  • 对每一个特征点, 其对应的31×31图像块中,任选出两个5×5的小块组成一个二值测试,这种组合数目达到205590个,相当于穷举出了所有点对的可能组合

  • 执行所有二值测试,每个二值测试其实就是比较两个5×5小块的像素平均值(前文有述),结果为1或0,用1bit存储,所以一个特征点得出一个向量[b1,b2,...,b205590]

  • 循环上述计算步骤,直至完成30万个特征点,将所有向量组成矩阵A,共30万行:

[b1,b2,...,b205590]
[b1,b2,...,b205590]
...
[b1,b2,...,b205590]
[b1,b2,...,b205590]

第二步,排序,挑选

  • 计算矩阵A的每一列的平均值,设为avg,那么该列与0.5的距离为:d = avg - 0.5

  • 将矩阵A的列按d从小到大顺序排列,结果设为T

  • 将T中第一列放到结果矩阵R中

  • 从T中拿出第一列,与R中所有列进行比较,若它与R中任何一列的绝对相关度(absolute correlation)大于给定阈值,则丢弃,否则将它放入R中,循环执行这一步,直到R中有256列

  • 如果所有T的列都历遍了,R中的列数还不足256,则增大阈值,重复上述步骤,直至R中有256列

经过第二步的计算,我们得到一个列向量之间相关性最小、每个列向量均值最接近0.5的结果集R(30万行,256列),每一行即可以做为对应特征点的IPD(256bit),此IPD对应的点对组合是最优的。

新的特征点的计算过程:

  1. 参考上述第一步,穷举计算特征点所有可能的二值测试

  2. 将结果作为一行加入矩阵A中,按照上述第二步进行计算,就可以得到此特征点对应的IPD
    因之前的样本都计算过,所以对新的特征点来说,计算消耗就是上述第二步。

最后,还遗留有一个小问题没有讲清楚,就是二进制向量间的绝对相关度(absolute correlation)如何计算?用汉明距离?

示例

skimage库包含了一个ORB类:

from skimage.feature import ORB

若import出错,查看scikit-image包版本:

pip show scikit-image
---
Name: scikit-image
Version: 0.11.3

如果低于此版本需要进行升级:

sudo pip install -U scikit-image

构造函数

class skimage.feature.ORB(downscale=1.2, n_scales=8, 
                        n_keypoints=500, fast_n=9, fast_threshold=0.08, harris_k=0.04)

downscale : 缩减因子,用于构建图像金字塔,默认值1.2可以增强特征对图像缩放尺度不变性
n_scales : 图像金字塔的最大层数
n_keypoints : 指定最多检测多少个关键点
fast_n : FAST算法的N值,即圆周上连续N个点符合阈值时,则中心点为关键点
fast_threshold : FAST算法阈值,设Ic为圆周上的像素值,Ip为中心像素值,若 Ic < Ip - fast_threshold 或 Ic > Ip + fast_threshold,表示符合阈值
harris_k : 为harris角检测k方法中的k系数(详见之前笔记),用于将角点从边缘分离出来,典型取值区间[0, 0.2],值越小表示检测越锐利的边缘

类方法
detect(image): 检测图像关键点
extract(image, keypoints, scales, orientations): 为给定关键点提取rBRIEF描述符
detect_and_extract(image): 检测图像关键点并提取rBRIEF描述符,此方法比用上面两步要快

对象属性
keypoints: 关键点坐标数组
scales: 尺度数组
orientations: 方向(弧度)数组
responses: harris角检测结果
descriptors:描述符数组

ORB论文中没有描述如何比较两个IPD的相关性和如何匹配,但BRIEF是有指出用汉明距离比较IPD。下面的例子,我使用是skimage库中的一个匹配函数:

skimage.feature.match_descriptors(descriptors1, descriptors2, metric=None, 
                                            p=2, max_distance=inf, cross_check=True)

metric: 指定匹配算法: {‘euclidean’, ‘cityblock’, ‘minkowski’, ‘hamming’, ...},默认使用hamming(汉明距离)
max_distance: 两个IPD之间的最大距离,小于此距离才认为是匹配的,经测试,它的取值范围为[0.0,1.0]
cross_check: 为True时,表示使用两向匹配,即两个IPD相互认为对方是最佳匹配时,才确定对应关系

综合以上函数,找出两张图像的若干对应关键点的代码示例:

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from skimage.feature import (match_descriptors, ORB, plot_matches)
                             
im1 = Image.open('y1.jpg')
im2 = Image.open('y2.jpg')
img1 = np.array(im1.convert('L'))
img2 = np.array(im2.convert('L'))

o = ORB(n_keypoints=200)     #创建一个ORB对象,只提取200个关键点
o.detect_and_extract(img1)   #提取第一幅图像                    
k1 = o.keypoints
d1 = o.descriptors

o.detect_and_extract(img2)   #提取第二幅图像                       
k2 = o.keypoints
d2 = o.descriptors

matches12 = match_descriptors(d1, d2, cross_check=True, max_distance=0.5)

plot_matches(plt, im1, im2, k1, k2, matches12)
plt.axis('off')
plt.show()

效果图:
图片描述

小结

从整个ORB的设计思想可以看出,它重在快速计算,目的就是为了满足在实时计算情景下使用,而且通过大量的样本分析得出,ORB并不逊于SIFT和SURF,反而在图像受噪声影响的情况下,ORB表示出更稳定的特性。
另外,ORB的rBRIEF描述符需要事先训练学习,但我觉得这不是问题,第一,今时今日非常容易收集和获取到更具有代表性的数据样本;第二,训练这一步计算可以由后台服务器来实现,所以ORB非常适合在移动设备上使用。
目前,关于ORB可参考的中文资料缺乏,加上论文原文有一些关键细节没有表达出来,所以在学习ORB上花了较多的时间。但本文包含的所介绍的方法,其思想让人视野开阔。
本文所述内容,可能存在理解偏差,欢迎指正。

参考资料

FAST
BRIEF
Image moment
ORB


jk_v1
1.8k 声望198 粉丝

Linux爱好者,技术积累主要在Linux、Qt、Android,后以Android开发为主,从上层(kotlin,java)到底层(jni,linux)有一定的工作经验和理解,擅长快速学习和知识关联梳理,整合不同技术资源为客户提供合适的解决方案。