本文着重介绍了用于图像特征点检测的算法,FAST算法,以及使用matlab的实现。
FAST算法是一种拐点检测算法,其主要应用于提取图像中的特征点,在动态成像的一系列图像中追踪定位对象。众所周知,我们生活的世界是动态化的,3D的,如何关联动态化过程中的平移,畸变,旋转对象,对每一帧的图像与上一帧之间的空间关系进行分析,很大程度上需求我们在每一帧中找到对应的关键点。FAST方法,拐点检测方法,简单来说就是用于提取图像中的关键点的算法,为进一步的图像处理,包括相机标定,SLAM打下了基础。
1. FAST算法解析
FAST拐点检测算法使用了一个包含了16个像素点的圆来判断目标点P是不是一个真正意义上的拐点。这16个像素点标序号为1至16。对于每一个候选像素点P,其强度为IpI_pIp (灰度图中即为该像素点的灰度值)。如果该圆中N个连续像素都比候选像素点P的强度亮很多,或都比候选像素点P的强度暗很多,那么P就被分类为一个拐点。 这个也比较好理解,即找出局部范围内最亮或最暗的点,作为局部图像的关键点。P为拐点所包含的情况如下:
- 条件1 : 一系列NNN个连续的像素点SSS,∀s∈S,Ix>Ip+t{\forall} s\in S, I_x > Ip + t∀s∈S,Ix>Ip+t
- 条件2 : 一系列NNN个连续的像素点SSS, ∀s∈S,Ix<Ip−t{\forall} s\in S, I_x < Ip - t∀s∈S,Ix<Ip−t
满足两个条件其中的任意一个,则可以认为像素点P为该局部区域的一个拐点。上述条件中,NNN 为连续的像素点个数,IxI_xIx为像素点xxx的强度,ttt为设置的阈值。显然,调整NNN以及阈值ttt,可以影响被分类为拐点的像素点P的个数。NNN值越大,被分类为拐点的像素点个数就会减少,同样ttt值越大,被分类为拐点的像素点个数也会减少。
tips : 所谓的NNN个连续的像素点,指的是例如N=5N = 5N=5 , [1,2,3,4,5],[2,3,4,5,6]...[1,2,3,4,5], [2,3,4,5,6]...[1,2,3,4,5],[2,3,4,5,6]...这样的像素点称为NNN个连续的像素点。
接下来我们就看看使用matlab如何实现这个拐点检测算法FAST。
2. MATLAB实现
下面就放出matlab代码,用于检测图像I中基于阈值t的拐点的函数。返回一个包含了这些拐点像素点坐标的矩阵。注释中详细解释了代码的原理。
function CS = FAST(I,t)
% I : 灰度图片
% t : 用户选择的阈值% 定义一个矩阵,描述了16个像素点关于待测像素点P的坐标关系。
% 需要注意的是,这些坐标的定义(i,j)为先行后列。
List_voisinage = [ -3 0;-3 1;-2 2;-1 3;0 3;1 3;2 2;3 1;3 0;3 -1;2 -2;1 -3;0 -3;-1 -3;-2 -2;-3,-1];
[height, width] = size(I);
% 初始化CS矩阵为空矩阵
CS = [];
const = 3;
% 定义N个连续的像素点,这里取值12,可以根据需求更改
N = 12;
% 由于我们要在整个图像上进行遍历,因此在没有Padding补充的情况下,需要考虑边缘的像素点
for i = const+1 : height - constfor j = const+1 : width - constIp = I(i,j);% 与算法描述相同,根据阈值规定上限下限upper = Ip + t;lower = Ip - t;% 将P周围的16个像素点的坐标及他们的灰度值,分别保存在coordonne_list 和% values_list 中 coordonne_list = zeros(16,2);values_list = zeros(16,1,"uint8");for k = 1:16coordonne_list(k,:) = List_voisinage(k,:) + [i, j];values_list(k,:) = I(coordonne_list(k,1),coordonne_list(k,2));end% X1向量,用于判断条件1是否满足X1 = zeros(16,1); for k = 1:16% 遍历,给X1向量赋值 0 或 1 的逻辑值X1(k) = values_list(k,1) > upper; end cond1voisins = X1;cond1verifiee = 0;compteur = 0;% 当条件1满足或数组已经循环平移过整个数组长度16时,结束循环while ~cond1verifiee && (compteur<16)nbVoisinCond1 = sum(cond1voisins(1:N));% 判断是否N个bool值都是1,即X1前N项和为Ncond1verifiee = (nbVoisinCond1 == N);% cirshift函数用于循环平移数组cond1voisins = circshift(X1,1)';compteur = compteur + 1;end% 满足条件1的时候,将目标点P的坐标添加进矩阵CSif cond1verifieeCS = [CS;[i,j]]; else% 如果条件1不满足,则继续判断条件2,与条件一大同小异X2 = zeros(16,1);for k = 1:16X2(k) = values_list(k,1) < lower;endcond2voisins = X2;cond2verifiee = 0;compteur = 0;while ~cond2verifiee && (compteur<16)nbVoisinCond2 = sum(cond2voisins(1:N));cond2verifiee = (nbVoisinCond2 == N);cond2voisins = circshift(X1,1)';compteur = compteur + 1;end% 同样如果满足了条件2,点P也分类为拐点,将其坐标添加入矩阵CSif cond2verifieeCS = [CS;[i,j]];end end end endend
3. 使用FAST function进行拐点检测的实验
I1 = imread("1.JPG");
I1_gray = rgb2gray(I1);
cs1 = FAST(I1_gray,30);
figure()
imagesc(I1)
hold on
plot(cs1(:,2),cs1(:,1),"*")
检测目标点结果如下 :
在这个实例中,设置了N值为12,阈值t为30。通过调整这两个变量可以改变提取出的关键点的个数。
\newline
\newline
\newline
参考文献 :
- Rosten, Edward; Reid Porter; Tom Drummond (2010). “FASTER and better: A machine learning approach to corner detection”. IEEE Transactions on Pattern Analysis and Machine Intelligence. 32 (1): 105–119. arXiv:0810.2434. doi:10.1109/TPAMI.2008.275. PMID 19926902.