说明
某人说,算法看不懂,公式不明白,举个栗子咯,能看到具体数值的那种。
好吧,举个最简单的角点检测算法吧。以下代码为matlab。
步骤
一、生成图像
构造一个棋盘图像作为测试图像,并且为了使数据在可见范围内,只生成单格5个像素共2x2大小的棋盘格
image = checkerboard(5,1,1);
imshow(image);
看看image是什么:
对应10x10的数据,不要问为什么不是0~255。。。。
二、梯度
xg=imfilter(image,[-1 0 1], 'replicate','same','conv');
xg=xg(2:end-1,2:end-1);
yg=imfilter(image,[-1 0 1]','replicate','same','conv');
yg=yg(2:end-1, 2:end-1);
要丢掉图像边界的值。在两个方向上与(-1 0 1)卷积(反转平移乘积求和)。
对应两个数值表如下,灰度是要截断的数据:
x方向梯度
y方向
是不是出现了两个方向的边缘线出来了。这就是为什么各大边缘算法都是基于梯度。
三、计算A、B、C
c=xg.*yg;
a=xg.*xg;
b=yg.*yg;
分别是什么呢,看下图。
c
a
b
四、滤波
filter_coef = [0.120078384243213;0.233880756585350;0.292081718342872;0.233880756585350;0.120078384243213;];
filter_coef = filter_coef(:);
w = filter_coef * filter_coef';
% filter A, B, and C
a = imfilter(a,w,'replicate','full','conv');
b = imfilter(b,w,'replicate','full','conv');
c = imfilter(c,w,'replicate','full','conv');
% clip to image size
removed = (numel(filter_coef)-1) / 2 - 1;
a = a(removed+1:end-removed,removed+1:end-removed);
b = b(removed+1:end-removed,removed+1:end-removed);
c = c(removed+1:end-removed,removed+1:end-removed);
滤波的主观感受就是眼睛对感兴趣区特别清晰,而背景虚化。类似於单反效果给人的感觉。
a滤波后
b滤波后
c滤波后
数据一下变得又长又黑。。。。。
五、特征值计算
sensitivity_factor = 0.04;
% 'Harris'
cMetric = (a .* b) - (c .^ 2) - sensitivity_factor * ( a + b ) .^ 2;
对应数值如下:
好,特征值出来了,那就完成了。自己数横座标6,纵座标5。打完收工。
六、最小值抑制
还是用代码数吧,人眼已瞎。
quality_level = 0.01;
BW = imregionalmax(cMetric,8);
max_cmetric = max(cMetric(:));
min_metric = quality_level * max_cmetric;
BW(cMetric < min_metric) = false;
BW = bwmorph(BW,'shrink',Inf); %n = Inf时,将目标缩成一个点。没有孔洞的目标缩成一个点,有孔洞的目标缩成一个连通环。
ind = find(BW);
[~,sorted_ind] = sort(cMetric(ind),'descend');
[r,c] = ind2sub(size(BW),ind(sorted_ind));
xpeak = c;
ypeak = r;
corners = [xpeak, ypeak];
plot(corners(:,1), corners(:,2), '.', 'Color', 'g')
这里数值不贴了,没意思。主要是去掉了值小的点, imregionalmax这个是用来判断是否为8临点最大值。
最后打点显示结果,图像是放大了效果,看起来偏离了中心,下面一张是实际大小。