基本思路:

  1. 二值化后前景图像以1进行标记,背景图像标记为0。
  2. 遍历原图I,当遇到前景图像时,判断该前景图像是否被标记,若该像素点pix(i,j)未被标记,则保存其坐标值至队列中,并在标记矩阵的对应坐标位置对该像素点进行标记。
  3. 对pix(i,j)的八个邻域进行搜索,当遇到新的未被标记的前景像素点时,将该点p(i+1,j)(或是其他点)坐标值入列,并在标记矩阵中进行标记。
  4. 八个邻域搜索标记完成后,将pix(i,j)出列,此时列头为pix(i+1,j),再次进行步骤3的八邻域搜索及标记操作。
  5. 当一个连通区域标记完成后,标签计数加一,清空队列,再次进行步骤2~4的遍历等操作,标记新的连通区域。

源码:

function IMG = label_blob(I)
%图像连通区域标记
%输入:灰度图矩阵 (可用Matlab自带图像 rice.png 进行测试
%输出:图像内连通区域数量

%%
%二值化
L = I > 130;
[row,col] = size(L);

%标记连通图像
connected = zeros(row,col);
queue = [];
label = 2;   

%8邻域坐标
offsets = [-1 -1; -1 0; -1 1; 0 -1; 0 1; 1 -1; 1 0; 1 1];  

%%
for i = 1:row
    for j = 1:col        
        if L(i,j) == 1 && connected(i,j) == 0           
            connected(i,j) = label;
            if isempty(queue)
                queue = [i;j];
            else
                queue = [queue [i;j]];
            end
            while ~isempty(queue)
                pix = [queue(1,1),queue(2,1)];
                %8邻域搜索
                for k = 1:8      
                    %邻域坐标 (外加获得
                    n_pix = bsxfun(@plus,pix,offsets(k,:));
                    %判断邻域坐标是否在范围内
                    if n_pix(1) >= 1 && n_pix(1) <= row && n_pix(2) >= 1 && n_pix(2) <= col
                        %像素值为1且未被标记
                        if L(n_pix(1),n_pix(2)) == 1 && connected(n_pix(1),n_pix(2)) == 0  
                            connected(n_pix(1),n_pix(2)) = label;
                            %邻域坐标入列
                            queue = [queue [n_pix(1);n_pix(2)]];
                        end  
                    end              
                end
                queue(:,1) = [];
            end            
            %标记加1以进行下一区域搜索
            label = label + 1;                       
        end   
    end
end

%连通区域数
num = label - 2;

%%
%输出显示
%imshow(I);
IMG = mat2gray(connected);
%figure,imshow(IMG);