10、标记连通分量

标记连通分量的意思就是找到二值图中的每一个连通区域,用某种记号标记出来,从而可以确定连通区域的个数,本讲将会介绍关于连通分量的几个函数,从而可以利用matlab找到图中的每一个连通区域。

1. 标记连通分量的函数

[L, n] = bwlabel(bw);
L = bwlabel(bw);
  1. 其中 bw 代表一张二值图
  2. 返回值 L 是一个和图片的像素大小相同的double型矩阵,bwlabel 会从上到下、从左到右的扫描每一个像素点,将遇到的第一个连通区域的所有像素点对应在矩阵 L 上的位置值置为 1 。
    依次类推,将第二个连通区域在矩阵上对应的位置的值置为 2 ,最后得到的矩阵就是在连通区域的位置上分布的1,2,3 ······,和其余位置为 0 的矩阵。
  3. 返回值 n 保存图中连通区域的个数,例如下图的箭头图片,返回的 n 的值为 6 。

对下图图片使用该函数得到的矩阵如图:

在这里插入图片描述
在这里插入图片描述

2. 对图片指定位置做标记

plot(c, r, 'r*');

该函数用来在第 c 列、第 r 行的地方,添加一个红色的 *r 代表红色,* 表示用 * 做标记,注意 plot 函数第一个坐标为列值,第二个坐标为行值。

plot 函数使用之前需要加上 hold on; 语句,以保持上一次显示的 figure ,实现在上次显示的 figure 上做标记(详细使用见下例)。



3. 标记箭头

目的:在上面的箭头图的每一个连通区域的重心点处标记红的的 *

思路:首先转换为二值图,然后用 bwlabel 函数作用于二值图,返回关于该图的连通区域坐标矩阵,之后可以用 find 函数分别找到每一个连通区域,使用 plot 函数标记红色的 *

步骤:

  1. 将图片转换为二值图
    在这里插入图片描述
    该步代码为:

    clear,clc,close all;
    f=imread('arrow.jpg');
    g=rgb2gray(f);
    bw=imbinarize(g);
    imshow(bw);
    
  2. bwlabel 函数计算图片的连通矩阵,然后这一步用了几个函数用不同的方式显示矩阵。

    figure,imshow(I, []);
    

    imshow 显示矩阵时候,在变量后面加一个参数 [ ],可以实现将矩阵中的值按比例均匀的转变为 0-255 中的值,从而将图片转换为灰度图显示(该句为我的猜测,有了解的老铁可以跟我说说对不对),效果见下图:

    在这里插入图片描述
    新增代码为:

    [I,n]=bwlabel(bw);
    figure,imshow(I,[]);
    

    可以在上面的代码后面加入一句 colormap hot;colormap cool; 实现给上面邻接的 *figure 中的灰度图加入暖色冷色 伪彩色。下图展示了两种不同的伪彩色。

    注意,colormap 是作用于上一个个 figure 里的所有图像的,如果用 subplot 显示图像, subplot 内的所有图像属于同一个 figure ,所有图片均会显示同一种伪彩色。

    在这里插入图片描述

  3. for 循环依次查找矩阵中值为 1 到 6 的区域,然后计算出重心的位置,用 plot 函数标记。

    在这里插入图片描述
    新增代码为:

    for i=1:n                     %for循环的格式
        [r,c]=find(I==i);
        mr=mean(r);		          %解释见下
        mc=mean(c);
        hold on;			      %保持上一figure,以使下个函数可以做标记
        plot(mc,mr,'r*');
    end					          %for循环的结束
    

    for 循环的格式如上所示,i 是递增变量,初始值为 1 ,每次循环 i 加 1 ,循环到值和 n 相同,便结束循环,继续向下执行,每次循环都要执行循环体内的语句。

    注意,for 循环内的语句需要缩进。

    [r,c] = find( I == i );   % 该语句查找矩阵 `I` 中满足值为 `i` 的所有坐标点,然后将横纵坐标相对应保存到 `r` 和 `c` 中
    
    mr = mean(r);     %该函数实现从一维矩阵中找到中值,返回给 mr
    
    mc=mean ( c );    %意义同上
    
    hold on;          %保持上一figure,以使下个函数 **plot** 可以做标记,可以参考上文的 **plot**函数的解释
    

    本例代码为:

    clear,clc,close all;
    f=imread('arrow.jpg');
    g=rgb2gray(f);
    bw=imbinarize(g);
    imshow(bw);
    [I,n]=bwlabel(bw);
    
    %显示伪彩色的代码
    % figure,imshow(I,[]),title('colormap hot');
    % colormap hot;
    % figure,imshow(I,[]),title('colormap cool');
    % colormap cool;
    
    for i=1:n
        [r,c]=find(I==i);
        mr=mean(r);
        mc=mean(c);
        hold on;
        plot(mc,mr,'r*');
    end
    

4. 数硬币

用红色的 * 在图片的硬币中心标记,然后输出共有多少硬币。
在这里插入图片描述
思路:先转化为二值图,然后用 bwlabel 计算出有多少连通区域,用 plot 函数标记,然后在本例中会介绍如何在命令行中输出字符串。

步骤:

  1. 先把图片转换为二值图
    在这里插入图片描述
    该步代码为:

    clear,clc,close all;
    f=imread('coin.jpg');
    g=rgb2gray(f);
    bw=imbinarize(g);
    imshow(bw);
    
  2. 观察上一步的二值图,发现在硬币的中心有许多黑色的小坑洞,这些小坑洞会影响连通区域的标记,因此需要先去除小坑洞。本步介绍一个函数,来去除小坑洞。

    bw = imfill(bw, 'holes');
    

    该函数可以去除 bw 图像上白色区域内的小黑洞,让整个连通区域完全连通。

    该步效果如下:

    在这里插入图片描述
    新增代码为:

    bw_fill=imfill(bw,'holes');
    figure,imshow(bw_fill);
    
  3. bwlabel 函数,计算连通区域的矩阵,并获取连通区域的个数,然后用 plot 函数标记每个硬币的重心。

    在这里插入图片描述
    本步新增代码为:

    [I,n]=bwlabel(bw_fill);
    for i=1:n
        [r,c]=find(I==i);
        mr=mean(r);
        mc=mean(c);
        hold on;
        plot(mc,mr,'r*');
    end
    
  4. 在命令行输出字符串,说明有几个硬币。

    s = strcat('str1' , 'str2' , 'str3' ... );   %将参数中的字符串连接为一个,并赋值给 s
    
    display (s);      %在命令行中输出字符串 s
    
    s =num2str(n);    %该函数的作用为,将数字转换为字符串并返回该字符串
    

    在本例中使用上述函数,输出所得到的图中硬币的个数。

    在这里插入图片描述
    新增代码为:

    s=strcat('一共有',num2str(n),'个硬币'); %在上面的运行中,n是一个整数,保存的是得到的硬币的个数,因此需要先转换为字符串
    display(s);
    

    本例代码为:

    clear,clc,close all;
    f=imread('coin.jpg');
    g=rgb2gray(f);
    bw=imbinarize(g);
    imshow(bw);
    bw_fill=imfill(bw,'holes');
    figure,imshow(bw_fill);
    [I,n]=bwlabel(bw_fill);
    
    for i=1:n
        [r,c]=find(I==i);
        mr=mean(r);
        mc=mean(c);
        hold on;
        plot(mc,mr,'r*');
    end
    
    s=strcat('一共有',num2str(n),'个硬币');
    display(s);
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值