• Matlab实现bwlabel函数(区域标记)功能


    算法分析

    1. 图像预处理。对二值图进行形态学开操作,开操作能去掉细小的块,平滑目标区域边界且保持面积不变

    2. 遍历二值图矩阵,寻找目标区域且未被标记的点,若当前像素未标记且当前位置像素点为1(二值图的目标区域)

    3. 将该目标点入队,并标上区域编号label

    4. BFS,对步骤1中的求得8邻域的像素点,如果该点未越界,是目标点(灰度值为1)并且未被标记过则入队,并且标上当前编号label,队列中每个点的8领域判断完则出队,当队列为空时一个连通区域标记完成,label+1

    5. 回到步骤1,直到二值图遍历完成

    6. 输出,将标记矩阵以彩色标记的形式输出,循环结束时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领域时为避免重复标记,需要多次判断当前是否已经标记

  • 相关阅读:
    手机怎么知道5G基站的存在?(小区搜索和SSB简介)
    Python中*args,**kwargs两个参数的作用?
    python之jupyter的安装
    国内安装python库速度慢的解决办法
    MOSFET:金属-氧化物半导体场效应晶体管
    C# 小知识点汇总
    ajax和form和七个中间件
    BBS功能分析
    MVC和MTV
    自关联和auth模块
  • 原文地址:https://www.cnblogs.com/Vicky1361/p/13936349.html
Copyright © 2020-2023  润新知