『youcans 的 OpenCV 例程300篇 - 总目录』
【youcans 的 OpenCV 例程 300篇】249. 特征检测之视网膜算法(FREAK)
1. FREAK 算法简介
快速视网膜算法(FREAK)算法是 Alexandre Alahi 在 ICCV 2012 的论文 FREAK: Fast Retina Keypoint 中提出的,其灵感来自人类视觉系统,通过比较视网膜采样模式的图像强度来计算二进制串的级联。。
快速视网膜关键点描述(FREAK,Fast Retina Keypoint)模拟人类视网膜的拓扑结构设计关键点的采样模式,构造二进制编码串珠外关键点的特征描述符,具有速度快、内存占用小和鲁棒性强的优点。
视觉系统基于不同尺度的高斯差分从图像中提取细节,视网膜的拓扑结构非常重要。如图16-11所示,神经细胞分为中央凹Foveal、中央凹Fovea、中心凹旁Parafoveal和中央凹周围Perifoveal的四个区域,空间分布具有中间密集、四周稀疏的特点。
BRISK算法的采样模式是均匀采样模式(在同一圆上等间隔的进行采样),FREAK算法采取了更为接近于人眼视网膜接收图像信息的采样模型。
人眼视网膜细胞的分布,中间密集,四周稀疏。FREAK算法的采样区域由大小不同并有重叠的同心圆构成,中心点是特征点,其它圆心是采样点。采样区域由以关键点为圆心的7 个同心圆组成。每个同心圆上各有 6个均匀分布的采样点,相邻同心圆的采样点的旋转角度交错分布,相隔30度。采样区域中共有 1+7x6=43个采样点。采样点离特征点的距离越远,采样点圆的半径越大,也表示该圆内的高斯函数半径越大。
采样像素的滤波内核半径都是各自所在同心圆半径的一半,而圆心处的特征点的滤波内核半径为1/24,一般来说,采用高斯滤波的方法效果更好。此时,滤波内核的半径就是高斯函数的标准差,均值滤波应该有着更快的特点,可以应用积分图像的方法,此时的滤波内核大小就是均值滤波的面积。
FREAK算法使用二进制串对特征点进行描述。
F
=
∑
0
≤
a
<
N
2
a
T
(
P
a
)
T
(
P
a
)
=
{
1
,
I
(
P
a
r
1
)
−
I
(
P
a
r
2
)
>
0
0
,
o
t
h
e
r
w
i
s
e
F=\sum_{0 \le a\lt N}{2^a T(P_a)} \\ T(P_a) = \begin{cases} 1 &,I(P_a^{r1})-I(P_a^{r2})>0\\ 0 &,otherwise\\ \end{cases}
F=0≤a<N∑2aT(Pa)T(Pa)={10,I(Par1)−I(Par2)>0,otherwise
F 表示二进制描述子,Pa 表示一个采样点对,N 是二进制编码长度。
I
(
P
a
r
1
)
I(P_a^{r1})
I(Par1) 表示采样点对Pa中前一个采样点的像素值,
I
(
P
a
r
2
)
I(P_a^{r2})
I(Par2) 表示后一个采样点的像素值。
FREAK 还将得到的 N bit的二进制描述子进行筛选降维,以获得更好和更具有辨识度的描述子。
1、建立矩阵D,D的每一行是一个FREAK二进制描述符,即每一行有N个元素。对每个特征点提取了43个采样点,可以产生 N=43*(43-1)/2=903 个采样点对,因此矩阵 D 有 903 行列。
2、对矩阵D的每一列计算其均值,由于D中元素都是0/1分布的,均值在0.5附近说明该列具有高的方差;
3、每一列都有一个均值,以均值最接近0.5的排在第一位,均值离0.5越远的排在越靠后,对列进行排序;
4、选取矩阵的前 k 列作为二进制描述符,例如 k=512。也可以是256、128、64、32等。
把得到的512个采样点对分成4组,每128个为一组,如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/50732fedf25d4fed976d9cfce9935d69.png#pic_center)
这四组的连线中第一组主要在外侧,之后的每组连线逐渐向内收缩,最后一组的连线主要在内侧。这与人眼视觉系统很
相似。人眼视觉系统首先通过perifoveal区域对感兴趣的物体的位置进行估计,然后通过感光细胞更加密集的fovea区域进行验证,最终确定物体的位置。
人眼的fovea区域由于有比较密集的感光细胞,可以捕捉高分辨率的图像,在识别和匹配过程中起关键作用。perifoveal区域的感光细胞则较为稀疏,只能捕捉到模糊的图像,因此首先用他们来进行物体位置的估计。这是人眼识别和匹配的原理,模仿这种流程对特征点进行匹配。
FREAK描述符的前段方差大表征粗略信息,后段方差小表征精细的高频数据。视觉系统的运行机制是先通过Perifoveal区域进行初步估计,再通过Fovea区域获取高分辨的图像。参考这种机制,FREAK实行描述符的级联匹配,先对前段的第一级进行匹配,如果匹配通过再继续下一级的匹配,这种方法显著提高了特征描述符的匹配速度。
FREAK 描述符的圆形对称采样结构使其具有旋转不变性,采样的位置半径随着尺度的变化使其具有尺度不变性,对每个采样点进行高斯模糊,也具有一定的抗噪性能,像素点的强度对比生成二进制描述子使其具有光照不变性。因此由上述产生的二进制描述子可以用来进行特征匹配。在匹配之前,再补充一下特征点的方向信息。
FREAK 比 SIFT、SURF、BRISK 算法的计算速度更快,内存负载更低,鲁棒性强,是现有算法的替代品,尤其适用于嵌入式应用。
2. OpenCV 的 FREAK 类
OpenCV提供了cv::xfeatures2d::FREAK类实现FREAK特征描述符。FREAK类继承cv::Feature2D父类,通过create静态方法创建。在Python语言中,通过接口函数FREAK.create实例化FREAK类,创建FREAK对象。
FREAK描述符是针对关键点的描述符,不涉及特征检测方法,需要配合SURF、FAST、STAR等特征检测算法,使用检测到的关键点keypoints作为输入,构造关键点描述符。
函数原型
cv.xfeatures2d.FREAK.create([, orientationNormalized, scaleNormalized=true, patternScale, nOctaves, selectedPairs])→ retval
cv.xfeatures2d.FREAK_create([, orientationNormalized, scaleNormalized=true, patternScale, nOctaves, selectedPairs]) → retval
freak.compute(image, keypoints[, descriptors]) → keypoints, descriptors
参数说明
orientationNormalized:方向标准化设置选项,默认值为true。
scaleNormalized:尺度标准化设置选项,默认值为true。
patternScale:描述符模式的缩放系数,默认值为22.0。
nOctaves:倍频程的组数,即尺度空间金字塔的层数,默认值为4。
selectedPairs:用户指定点对的索引。
image:输入图像,数据类型CV_8U。
keypoints:检测到的关键点,元组。
descriptors:关键点的描述符,形为(n,64)的Numpy 数组。
注意问题
⑴ 函数cv.FREAK_create()实例化FREAK类,定义一个FREAK类对象。默认设置尺度和方向标准化,具有尺度不变性和旋转不变性。
⑵ 描述符descriptors是FREAK特征描述符的数组,形状为(n,64),n是关键点的数量,描述符长度为64,对应于512位二进制编码。
3. 例程:特征描述之FREAK关键点描述
本例程使用STAR方法进行特征点检测,构造BRIEF关键点描述符。
# 【1611】特征描述之FREAK 描述符
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) # 基准图像
height, width = img.shape[:2] # (500, 500)
print("shape of image: ({},{})".format(height, width))
# BRISK 检测关键点
brisk = cv.BRISK_create() # 创建 BRISK 检测器
kp = brisk.detect(img) # 关键点检测,kp 为元组
print("Num of keypoints: ", len(kp)) # 271
# BRIEF 特征描述
brief = cv.xfeatures2d.BriefDescriptorExtractor_create() # 实例化 BRIEF 类
kpBrief, desBrief = brief.compute(img, kp) # 计算 BRIEF 描述符
print("BRIEF descriptors: ", desBrief.shape) # (270, 32)
# FREAK 特征描述
freak = cv.xfeatures2d.FREAK_create() # 实例化 FREAK 类
kpFreak, desFreak = freak.compute(img, kp) # 生成描述符
print("FREAK descriptors: ", desFreak.shape) # (196, 64)
imgS = cv.convertScaleAbs(img, alpha=0.5, beta=128)
imgKp1 = cv.drawKeypoints(imgS, kpBrief, None, flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
imgKp2 = cv.drawKeypoints(imgS, kpFreak, 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. BRIEF keypoints scaled")
plt.axis('off'), plt.imshow(cv.cvtColor(imgKp1, cv.COLOR_BGR2RGB))
plt.subplot(133), plt.title("3. FREAK keypoints scaled")
plt.axis('off'), plt.imshow(cv.cvtColor(imgKp2, cv.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
程序说明:
- ⑴ 运行结果如图16-12所示。子图1是原始图像,使用BRISK算法检测到271个关键点。
- ⑵ BRIEF描述符的形状为(270,32),子图2中的圆圈表示每个关键点的尺度与方向。
- ⑶ FREAK描述符的形状为(196,64),64表示描述符由512位二进制编码组成。子图3中的圆圈表示每个关键点的尺度与方向。
参考文献:
A Alahi,R Ortiz,P Vandergheynst, FREAK: Fast Retina Keypoint, 2012, Published in: 2012 IEEE Conference on Computer Vision and Pattern Recognition (CVPR 2012)
【本节完】
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/128169703)
Copyright 2022 youcans, XUPT
Crated:2022-12-3