『youcans 的 OpenCV 例程300篇 - 总目录』
【youcans 的 OpenCV 例程 300篇】246. 特征检测之ORB算法
特征检测与匹配是计算机视觉的基本任务,包括检测、描述和匹配三个相互关联的步骤。广泛应用于目标检测、图像检索、视频跟踪和三维重建等诸多领域。
6.9.1 ORB 算法简介
ORB(Oriented FAST and rotated BRIEF) 是 OpenCV 实验室开发的一种特征检测与特征描述算法,将 FAST 特征检测与 BRIEF 特征描述结合并进行了改进,具有尺度不变性和旋转不变性,对噪声有较强的抗干扰能力。
ORB算法在图像金字塔中使用FAST算法检测关键点,通过一阶矩计算关键点的方向,使用方向校正的BRIEF生成特征描述符。
FAST(Features From Accelerated Segment Test)是一种关键点检测算法,用于特征提取但不涉及特征描述。FAST 算法通过与圆周像素的比较结果判别特征点,计算速度快、可重复性高,非常适合实时视频的处理。
BRIEF (Binary Robust Independent Elementary Features)是一种二进制特征描述符,直接生成二进制字符串作为关键点的特征描述符,加快了建立特征描述符的速度,降低了特征描述符的内存占用,极大地提高了特征匹配的效率,是一种快速高效的特征描述方法,对光照、模糊和透视变换具有较强的鲁棒性。
基本的FAST和BRIEF算法并不具有尺度不变性和旋转不变性,ORB算法的主要贡献是:
(1)对 FAST 算法提取的特征点,使用一阶矩计算特征点方向,实现旋转不变性;
(2)高效计算带方向的 BRIEF 特征点描述符;
(3)降低 BRIEF 特征描述符点对的相关性,在最近邻匹配中具有更好的性能。
参考文献:Ethan Rublee, Vincent Rabaud, Kurt Konolige, and Gary Bradski. Orb: an efficient alternative to sift or surf. In Computer Vision (ICCV), 2011 IEEE International Conference on, pages 2564–2571. IEEE, 2011.
ORB论文中没有解决尺度不变性,但在OpenCV算法中通过图像金字塔实现了尺度不变性。
ORB的主要步骤如下:
(1)尺度空间关键点检测
通过下采样构造图像金字塔,每层只有一张图像,第s层的尺度为:
σ
s
=
σ
0
s
\sigma_s=\sigma_0^s
σs=σ0s,第s层的图像尺寸为:
S
i
z
e
=
(
H
/
σ
s
,
W
/
σ
s
)
Size=(H/\sigma_s, W/\sigma_s)
Size=(H/σs,W/σs)。
在图像金字塔的每层图像中使用 FAST 检测关键点,然后使用Harris角点响应函数或FAST算法选择响应最强的N个点。通过检测每个尺度的关键点,使算法具有一定的尺度特征。
(2)确定关键点的方向
SIFT的定向算法计算量很大,而SURF的定向算法精度较差。ORB使用质心法对关键点确定唯一的主方向。
在以关键点为中心、尺度半径的邻域中,使用强度质心法(一阶矩)计算关键点的方向:
(
C
x
,
C
y
)
=
(
m
10
/
m
00
,
m
01
/
m
00
)
θ
=
a
r
c
t
a
n
(
m
01
,
m
10
)
(C_x, C_y) = (m_{10}/m_{00}, m_{01}/m_{00}) \\ \theta = arctan(m_{01}, m_{10})
(Cx,Cy)=(m10/m00,m01/m00)θ=arctan(m01,m10)
通过确定每个关键点的方向, 以实现旋转不变性。
(3)使用rBRIEF(Rotation-Aware BRIEF )生成特征描述符。
BRIEF描述符对于方向变化非常敏感, 存在10度以上旋转时匹配性能很差。
ORB 将角度离散化为2π/30(12度),并构建了BRIEF模式的查找表。rBRIEF根据关键点方向来引导 BRIEF,按关键点的方向将采样窗口旋转角度
θ
\theta
θ后再构造特征区域,生成 rBRIEF 特征描述符,因此具有旋转不变性。
(4)rBRIEF 特征描述符的方差
BRIEF描述符的每个关键点对都具有很大的方差(均值接近于0.5),相关性较小,便于增强匹配性能。
但 rBRIEF 会减小特征点对的方差,相关性增大,可识别性降低。
为了恢复 rBRIEF 损失的方差,ORB在所有可能的二进制测试中进行贪婪搜索,以找到具有高方差和相关性弱的二进制点对。
ORB的优点是速度非常快,性能比较好,具有旋转不变性和一定的尺度不变性。由于没有专利限制可以免费使用,ORB 算法应用广泛,经常被用来代替 SIFT、SURF 算法。
计算速度: ORB>>SURF>>SIFT(各差一个量级)
旋转鲁棒性:SURF>ORB~SIFT(~表示差不多)
模糊鲁棒性:SURF>ORB~SIFT
尺度鲁棒性:SURF>SIFT>ORB(ORB的尺度变换性很弱)
6.9.2 OpenCV 中的 ORB 类
OpenCV 提供了丰富的特征检测算法,而且继承了 cv::Feature2D 类,采用了统一的定义和封装。
OpenCV 中提供 cv::ORB 类实现 ORB 算法,ORB 类继承了cv::Feature2D类,通过create静态方法创建。
ORB 类的构造函数为:
static Ptr<ORB> create(int nfeatures=500,float scaleFactor = 1.2f,int nlevels = 8,int edgeThreshold = 31,int firstLevel = 0,int WTA_K = 2,ORB::ScoreType scoreType = ORB::HARRIS_SCORE,int patchSize = 31,int fastThreshold = 20)
ORB 类继承 cv::Feature2D父类,在Python语言中通过接口函数cv.ORB_create或cv.ORB.create实例化ORB类,创建ORB对象。通过成员函数orb.detect检测关键点,函数orb.compute计算关键点描述符,函数orb.detectAndCompute检测关键点并生成描述符。
cv.ORB.create([, nfeatures=500, scaleFactor=1.2f, nlevels=8, edgeThreshold=31, firstLevel=0, WTA_K=2, scoreType=ORB::HARRIS_SCORE, patchSize=31, fastThreshold=20]) → retval
cv.ORB_create([, nfeatures=500, scaleFactor=1.2f, nlevels=8, edgeThreshold=31, firstLevel=0, WTA_K=2, scoreType=ORB::HARRIS_SCORE, patchSize=31, fastThreshold=20]) → retval
orb.detect(image[, mask]) → keypoints
orb.compute(image, keypoints[, descriptors=None]) → keypoints, descriptors
orb.detectAndCompute(image, mask[, descriptors[, useProvidedKeypoints]]) → keypoints, descriptors
参数说明:
- nfeatures:关键点的最大数量,默认值为500。
- scaleFactor:图像金字塔的缩放比,大于1的浮点数,默认值为1.2。
- nlevels :图像金字塔的层数,默认值为8。
- edgeThreshold:边界保留尺寸,不检测靠近边界的像素,默认值为31。
- firstLevel:原始图像作为金字塔的第几层,默认值为0。
- WTA_K:构造BRIEF描述符点对的像素点数,可选值2/3/4,默认值为2。
- scoreType:响应排序方法,默认HARRIS_SCORE,表示按Harris响应函数排序。
- patchSize:生成定向描述符的特征区域的尺寸,默认值为31。
- fastThreshold:FAST阈值,默认值为20。
- image:输入图像,单通道。
- mask:掩模图像,指定查找关键点的区域,可选项。
- keypoints:检测到的关键点,元组。
- descriptors:关键点的描述符,形为(nfeatures,32)的Numpy数组。
注意事项:
- 通过接口函数cv.ORB.create或cv.ORB_create实例化ORB类,在OpenCV的不同版本中可能只允许其中一种方式。
- 函数detect、compute、detectAndCompute等是继承Feature2D类的成员函数,在程序中的格式为orb.detect,orb表示ORB类的实例对象。
- 关键点描述符descriptor的形状为(nfeatures,32),nfeatures是关键点的数量,描述符的字节长度为32,对应于二进制编码长度为256。
例程 14.28:特征检测之 ORB 算法
# 【例程 14.28】特征检测之 ORB 算法
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
if __name__ == '__main__':
img = cv.imread("../images/Fig1701.png", flags=1)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
print("shape of image: ", gray.shape)
# Initiate ORB detector
orb = cv.ORB_create() # 实例化 ORB 类
# kp, descriptors = orb.detectAndCompute(gray) # 检测关键点和生成描述符
kp = orb.detect(img, None) # 关键点检测,kp 为元组
kp, des = orb.compute(img, kp) # 生成描述符
print("Num of keypoints: ", len(kp)) # 500
print("Shape of kp descriptors: ", des.shape) # (500,32)
imgS = cv.convertScaleAbs(img, alpha=0.5, beta=128)
imgKp1 = cv.drawKeypoints(imgS, kp, None) # 只绘制关键点位置
imgKp2 = cv.drawKeypoints(imgS, kp, None, flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # 绘制关键点大小和方向
plt.figure(figsize=(9, 3.5))
plt.subplot(131), plt.title("1. Original")
plt.axis('off'), plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.subplot(132), plt.title("2. ORB keypoints")
plt.axis('off'), plt.imshow(cv.cvtColor(imgKp1, cv.COLOR_BGR2RGB))
plt.subplot(133), plt.title("3. ORB keypoints scaled")
plt.axis('off'), plt.imshow(cv.cvtColor(imgKp2, cv.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
程序说明
程序运行结果如图所示。
⑴ 子图1是原始图像,子图2、子图3将ORB检测的关键点绘制在原始图像上。子图2只绘制了关键点的中心,子图3对每个关键点绘制表示关键点大小和方向的圆圈。
⑵ 例程检测到500个关键点,但子图2中显示的关键点数量似乎并不多。对比子图3可知,在一个关键点及其邻近点,可能在不同尺度被检测为很多个关键点,ORB算法并未对此进行抑制。
参考文献:Ethan Rublee, Vincent Rabaud, Kurt Konolige, and Gary Bradski. Orb: an efficient alternative to sift or surf. In Computer Vision (ICCV), 2011 IEEE International Conference on, pages 2564–2571. IEEE, 2011
【本节完】
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/128033070)
Copyright 2022 youcans, XUPT
Crated:2022-11-25