Programming Computer Vision with Python (学习笔记十二)

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

FAST角检测

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

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

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

  2. 给定一个阈值,好比设为p点灰度值的20%数据结构

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

  4. 为让上面的判断更快,能够先计算序号为一、五、九、13的4个像素(如图),这4个像素至少要有3个符合阈值,才有可能存在连续12个像素知足阈值,才有必要检测其它像素。机器学习

  5. 对原图像每个像素,重复以上计算过程,最终得出全部兴趣点。数据结构和算法

FAST算法存在的问题:ide

  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

相关文章
相关标签/搜索