本文主要介绍二值形态学在目标检测上的用法, 就不讲形态学原理了。
不熟悉的选手可以参考以下文章,
二值形态学原理:https://blog.csdn.net/zxli3011/article/details/50522939
二值形态学效果MATLAB演示:https://blog.csdn.net/abigbiggirl/article/details/49888733
%% 矩形
% bg:背景图 x,y:矩形中心坐标 rh,rw:矩形高宽半径
function bg = CreateRectangle(bg, x, y, rh, rw)
bg(x-rh:x+rh, y-rw:y+rw) = 1;
end
%% 圆形
% bg:背景图 x,y:圆心坐标 r:半径
function bg = CreateCircle(bg, x, y, r)
for i = x-r:x+r
for j = y-r:y+r
if(i-x)^2+(j-y)^2 < (r+1)^2
bg(i,j) = 1;
end
end
end
end
%% 测试图生成
bg1 = zeros(500);
bg2 = zeros(500);
N = 8; % 图形数量
for n = 1:N
% 随机生成整数坐标(以下写法是为确保图形在图像内部)
x = round(rows*(rand()*0.8+0.1);
y = round(cols*(rand()*0.8+0.1);
bg1 = CreateRectangle(bg1, x, y, 30, 30);
bg2 = CreateCircle(bg2, x, y, 40);
end
利用二值连通区域标记算法统计目标的数量。
二值连通区域标记算法
算法原理不做介绍,感兴趣可以查看:
二值图连通区域标记-https://blog.csdn.net/ch190029975/article/details/82734619
MATLAB实现与结果
这里以圆形目标为例,可自行测试其他图形。
%% 测试图生成与显示
% 略...
%% 连通区域标记
[label,num] = bwlabel(bg);
%% 结果显示
status = regionprops(label,'BoundingBox'); % 获取标记框
centroid = regionprops(label,'Centroid'); % 获取标记中心
subplot(122), imshow(bg), title('连通分量标记');
hold on
for n = 1:num
rectangle('position',status(n).BoundingBox,'edgecolor','r'); % 画框
text(centroid(n,1).Centroid(1,1)-1,centroid(n,1).Centroid(1,2)-1, num2str(n),'Color', 'r') % 标号
end
从结果可以看出,当目标图形无重叠时,连通分量标记可以很好的统计目标数量;但图像有相连或重叠时,则无法正确统计。
充分利用腐蚀算法的原理,实现目标检测。
%% 矩形
% rh,rw:矩形高宽半径
function se = RectangleStrel(rh, rw)
mask = ones(rh*2+1,rw*2+1);
se = strel(mask);
end
%% 圆形
% r:半径
function se = CircleStrel(r)
[x,y] = meshgrid(-r:r);
mask = x.^2+y.^2<(r+1)^2;
se = strel(mask);
end
%% 测试图生成
bg = zeros(500);
N = 8; % 图形数量
R = 40; % 圆形半径
for n = 1:N
% 随机生成整数坐标(以下写法是为确保图形在图像内部)
x = round(rows*(rand()*0.8+0.1);
y = round(cols*(rand()*0.8+0.1);
bg = CreateCircle(bg2, x, y, R);
end
%% 形态学腐蚀
se = CircleStrel(R*0.9); % 使用等于或略小于目标的结构元
ob = imerode(bg,se);
%% 连通区域标记
[label,num] = bwlabel(ob); % 对腐蚀结果进行连通区域标记
%% 结果显示
subplot(131), imshow(bg), title('原图')
subplot(132), imshow(ob), title('腐蚀结果')
subplot(133),imshow(bg), title('标记结果')
hold on;
for n = 1:num
rectangle('position',status(n).BoundingBox+[-R,-R,2*R,2*R],'edgecolor','r');
text(centroid(n,1).Centroid(1,1)-1,centroid(i,1).Centroid(1,2)-1, num2str(n),'Color', 'r')
end
结果图如下, 可以看到效果比较好。如果代码里使用与目标等半径的结构元,腐蚀结果则可以定位到图形中心。
对于形状和尺寸都统一的图形,利用该方法可以精确获取目标图形的位置与数量。
但对于图形尺寸不一、形状多样的背景里,还能适用吗?
这个问题将在下一篇为大家分享。
有任何问题欢迎讨论,最后还是把测试代码上传
https://download.csdn.net/download/xsz591541060/11246225
由于核心代码在文中已讲,不推荐下载,除非你买了年VIP。