目录
1. 基本原理
为 了 提 取 图 像 的 角 点 ( 特 征 点 ),最 小 核 值 相 似 区 ( Smallest Univalue Segment Assimilating Nucleus,SUSAN)算法引入了圆形模板如图 1 所示,其中蓝色部分和红色部分表示圆形模板实际覆盖的像素点范围,红色部分表示模板核。
图1 SUSAN模板
类似于卷积操作,SUSAN角点检测算法将圆形模板在图像上进行窗口滑动,每次滑动都会对圆形模板覆盖的像素点进行统计。统计时,算法会计算模板内蓝色部分像素值与模板核像素值的距离(即两者之差的绝对值),若距离小于给定距离阈值,则认为该像素属于SUSAN区域,计算公式如下:
其中,用于判断像素是否属于 SUSAN 区域,为模板内蓝色区域像素值, 为模板核像素值,为距离阈值。接着只需统计模板内属于 SUSAN 区域的像素值数量即可:
其中,表示以 为模板核的模板内的蓝色区域覆盖的像素点集合, 表示该模板内相近的像素点个数。
最后,模板滑动结束后,得到相似像素值数量矩阵,记矩阵中的最大值为,则阈值 可表示为,通过阈值 来筛选非角点:
一般地, 矩阵中非零值对应位置均为角点。但实际情况往往更为复杂,为了进一步剔除伪角点,可以采用 3X3 模板滑动方式扫描,若模板中心值大于所有领域值,将该点记为角点,否则不记为角点。
2. Matlab代码
参考代码
SUSAN角点检测 - 百度文库https://wenku.baidu.com/view/d368076c862458fb770bf78a6529647d2728348e.html
2.1 相似像素点统计函数
首先根据式(1)(2),编写 count 函数,用于统计模板 mask 内与模板核距离小于阈值 threshol 的像素个数。输入的 mask 模板的大小是 7X7,因此在 count 函数的前两行需要将圆形区域以外的部分设置为 NAN(非数字),接着统计符合要求的像素值个数 s。
function s = count(mask, threshold)
mask([1 7],[1 2 6 7]) = nan;
mask([2 6],[1 7]) = nan;
index = abs(mask(4,4)-mask) < threshold;
s = sum(index(:));
end
2.2 图像预处理
读入图像后,若图像为彩色图像,需要先转换为灰度图像。将原始图像进行padding 操作,以便于后续的模板窗口滑动。
clear, close all
im = imread('cameraman.tif');
[row, col, channel] = size(im);
if channel == 3
im_ = rgb2gray(im);
else
im_ = im;
end
im_padded = zeros(row+6, col+6);
im_padded(4:end-3, 4:end-3) = im_;
2.3 窗口滑动
执行模板窗口滑动操作,调用count函数,将统计结果记录在向量 S 中。
threshold = 45;
S = [];
for i = 4: row+3
for j = 4: col+3
mask = im_padded(i-3:i+3, j-3:j+3);
S = [S count(mask, threshold)];
end
end
2.4 筛选非角点
将向量 S 还原回矩阵,得到相似像素值数量矩阵,即角点矩阵。计算阈值G,并通过式(3)筛选非角点,筛选后非零值对应位置一般为角点。
S = reshape(S, row, col);
S = fliplr(imrotate(S, -90));
G = 3*max(S(:))/4;
index = S < G;
S(index) = G-S(index);
S(~index) = 0;
2.5 剔除伪角点
为进一步剔除伪角点,需判断每个角点是否为 3X3 邻域内的最大值。
loc = [];
for i = 2: row-1
for j = 2: col-1
temp = S(i-1:i+1,j-1:j+1);
temp(2,2) = 0;
if S(i,j) > temp
loc = [loc; [j i]];
end
end
end
2.6 绘制图像
绘制原始图像和角点检测图像。
subplot(1,2,1), imshow(im);
subplot(1,2,2), imshow(im);
hold on
plot(loc(:,1), loc(:,2), '*')
2.7 完整代码
clear, close all
%% 读取图像并padding
im = imread('cameraman.tif');
[row, col, channel] = size(im);
if channel == 3
im_ = rgb2gray(im);
else
im_ = im;
end
im_padded = zeros(row+6, col+6);
im_padded(4:end-3, 4:end-3) = im_;
%% 窗口滑动,得到角点向量
threshold = 45;
S = [];
for i = 4: row+3
for j = 4: col+3
mask = im_padded(i-3:i+3, j-3:j+3);
S = [S count(mask, threshold)];
end
end
%% 角点向量转矩阵
S = reshape(S, col, row);
S = fliplr(imrotate(S, -90));
%% 筛选非角点
G = 3*max(S(:))/4;
index = S < G;
S(index) = G-S(index);
S(~index) = 0;
%% 进一步剔除伪角点
loc = [];
for i = 2: row-1
for j = 2: col-1
temp = S(i-1:i+1,j-1:j+1);
temp(2,2) = 0;
if S(i,j) > temp
loc = [loc; [j i]];
end
end
end
%% 绘制原始图像和角点检测图像
subplot(1,2,1), imshow(im);
subplot(1,2,2), imshow(im);
hold on
plot(loc(:,1), loc(:,2), '*')
%% 相似像素点统计函数
function s = count(mask, threshold)
mask([1 7],[1 2 6 7]) = nan;
mask([2 6],[1 7]) = nan;
index = abs(mask(4,4)-mask) < threshold;
s = sum(index(:));
end
3. 运行结果
从图 2 可以观察 SUSAN 角点检测算法的准确度。一个明显的结果是左上方孤立的一个点,可以看到在原图中它是一个白色的像素点,不同于周边的灰色像素,它是一个较为明显的角点。
图2 角点检测人物
从图 2,3,4 中可以看出,SUSAN 角点检测算法拥有较好的鲁棒性,能够较为准确地检测出图像的角点。从图 3 的两个字母 S 的结果可以看出,同一角点在不同位置也能检测出来,不受位置的影响。从图4和5可以看出,SUSAN 角点检测算法具有旋转不变性。
图3 角点检测单词
图4 角点检测抽象画
图5 图4旋转后的角点检测结果
4. 总结
算法优点 算法简单易于实现,角点位置识别准确,具有较好的鲁棒性,无需计算梯度,窗口滑动可以加速获得较快的检测速度。
局限性 该算法仅适用灰度图像,对于彩色图像需要将其转换为灰度图像,忽略了彩色空间分量之间的关联性,从而导致检测结果可能并不准确。单纯通过统计模板中和模板核相近的像素点个数较为理想化,实际场景可能并不能仅凭该统计结果判断角点。
5. 代码获取
关注公众号,回复“数字图像处理”,即可获取完整代码和测试图片