算法分析
-
图像预处理。对二值图进行形态学开操作,开操作能去掉细小的块,平滑目标区域边界且保持面积不变
-
遍历二值图矩阵,寻找目标区域且未被标记的点,若当前像素未标记且当前位置像素点为1(二值图的目标区域)
-
将该目标点入队,并标上区域编号label
-
BFS,对步骤1中的求得8邻域的像素点,如果该点未越界,是目标点(灰度值为1)并且未被标记过则入队,并且标上当前编号label,队列中每个点的8领域判断完则出队,当队列为空时一个连通区域标记完成,label+1
-
回到步骤1,直到二值图遍历完成
-
输出,将标记矩阵以彩色标记的形式输出,循环结束时label的值多加了1,退出循环时,label的值减1才是该图中的连通区域的个数
伪代码
function [conn,num] = mybwlabel( I )
% 使用BFS对二值图区域标记
% 输入:I是二值图矩阵
% 输出:tmp是标记矩阵,num是连通区域个数
[m n] = 计算二值图的大小
conn = 开辟一个和二值图同样大小的标记矩阵
label = 给区域编号设初值1
queue = 定义二维数组用于存放一个连通区域的点的坐标(模拟队列)
neighbour = 8邻域(坐标无序)
遍历二值图
如果当前点属于目标区域且未标记
queue = 当前点坐标入队
conn(i,j) = 给该点赋值区域编号
队列不空
index = 取出队首坐标
8邻域搜索
cur_index = 当前点邻域坐标
如果当前坐标未越界
如果当前像素邻域像素为1并且标记图像的这个邻域像素没有被标记
标记当前点
当前坐标入队(矩阵合并)
队首坐标出
label = 区域编号加1
num = 连通区域的个数为label-1
end
代码
function [conn,num] = mybwlabel( I )
% 对二值图区域标记
% 输入:I是二值图矩阵
% 输出:tmp是标记矩阵,num是连通区域个数
[m n] = size(I);
conn = zeros(m,n); %标记矩阵
label = 1;
queue = []; %用二维数组模拟队列
%和当前像素坐标相加得到八个邻域坐标(坐标无序)
neighbour = [-1 -1;-1 0;-1 1;0 -1;0 1;1 -1;1 0;1 1];
for i = 2 : m-1
for j = 2 : n-1
if I(i,j) == 1 && conn(i,j) == 0 %属于目标区域且未标记才处理
conn(i,j) = label;
queue = [i;j]; %记录当前点坐标
while ~isempty(queue) %队列不空,这里没有出队操作,队列中的每一个元素的8领域都判断一遍
index = [queue(1,1),queue(2,1)];
for k = 1 : 8 %8邻域搜索
cur_index = index + neighbour(k,:); %加上每一行的坐标得到周围8邻域的坐标点
if cur_index(1) >= 2 && cur_index(1) <= m - 1 && cur_index(2) >= 2 && cur_index(2) <= n - 1 %防止坐标越界
if I(cur_index(1),cur_index(2)) == 1 && conn(cur_index(1),cur_index(2)) ==0 %如果当前像素邻域像素为1并且标记图像的这个邻域像素没有被标记,那么标记
conn(cur_index(1),cur_index(2)) = label;
queue = [queue [cur_index(1);cur_index(2)]];
end
end
end
queue(:,1) = []; %队列中第一列的坐标出队
end
label = label+1;
end
end
end
num = label - 1; %连通区域的个数(减去背景这个连通区域)
end
实验结果
% 调用示例:
I = imread('rice.png');
Ib = im2bw(I);
[B,num] = mybwlabel(Ib);
subplot(1,3,1),imshow(I),title('原图');
subplot(1,3,2),imshow(Ib),title('二值图');
subplot(1,3,3),imshow(label2rgb(B)),title('区域标记');
连通区域个数:
图像预处理去噪,由上图中二值化之后,二值图中有很多噪声点,可以通过形态学开操作去除这些点
SE = strel('disk',3); %定义一个圆形结构元
Ib = imopen(Ib,SE); %开操作去除噪声
开操作之后的效果
连通区域个数:
开操作之后去除噪声,连通区域个数明显减少
实验分析
-
在标记连通区域之前可以通过形态学操作,去除噪声点
-
对二值图中每一个像素点的8邻域,都遍历一遍,将8邻域中属于目标区域的点的坐标都入队,对于当前满足条件的像素点判断结束时,就会标记完一个连通区域
-
在遍历8领域时为避免重复标记,需要多次判断当前是否已经标记