数字图像处理笔记(九)基本的形态学算法

0.前言

  这篇文章就慢慢一边做实验一边写基本的形态学处理的内容,看着阮老师翻译的书直接用MATLAB靠自己的记忆写程序。慢慢更这篇,一边理解一边更,包括边界提取、孔洞填充(重点,因为我要考的课有道题就考这个)、骨架、连通分量、细化、裁剪等等。

1.边界提取

  表示为 β ( A ) \beta(A) β(A) 的集合 A A A 的边界可以先用 B B B A A A 服饰,而后做 A A A 和 腐蚀结果的之间的集合之差得到,即 β ( A ) = A − ( A ⊖ B ) \beta(A) = A - (A \ominus B) β(A)=A(AB)
我在思考边界提取边缘提取到底有什么区别,就写了写对比了下,思考了下。
  边界:专门指外部的轮廓
  边缘:在数字图像处理中专门指灰度突变的地方
然后写了个程序对比了下,发现其实确实形态学处理起来还真有点带感。

  程序的思路是读入彩色图像,然后将彩色图转灰度图之后利用 edge 提取边缘,以及提取3个通道的分量去提取边缘,然后进行对比。
  而边界提取可以直接在彩色空间中操作,所以我用上面的公式,直接得到彩色的边界,然后在彩色边界中提取R、G、B分量,之后进行显示对比。其中结构元是 5*5 的 strucure

                        先看下面的结果吧
在这里插入图片描述
以前手撸过canny边缘的算法,这次用了系统自带的 edge 函数,二阶边缘,速度快、识别效率高,但是MATLAB中 edge 函数需要转换到灰度空间去做,并且最后一步连通的时候出来结果是 二值图 ,采用 rgb2gray 函数不免会有灰度损失,而直接直接提取各个分量容易造成在浮点型转化的时候的精度损失。左边的图是边缘提取的结果,是黑白二值图 ,而右边的是利用上面公式提取出来的 彩色边界 ,看到轮廓分明,神清气爽。

                      再看下面的另一个结果吧

在这里插入图片描述
诚如我在之前说的,利用 edge 函数需要在灰度图像进行,所以我提取R、G、B空间进行边缘提取,但是由于提取出来的灰度图每个灰度值不一样,所以容易导致了可能灰度突变的地方不一样,所以显示出的 边缘 有些不一样,而利用传统的边界提取方法的边界提取的绝对一样,仅仅只是在灰度显示有差别罢了,况且人眼还识别不出来。

1.1总结

  边缘边界的提取有差别,并且有不同的方法,在边界提取的时候结构元的大小选择也有考究,需要再进一步思考吧!

1.2代码

%Coding = UTF8
%By neverland!
%Nov 19th
%version1.0

%读入图像
	im = imread('test.jpg');
%操作
	gray_im = rgb2gray(im);         %灰度图
	r = im(:,:,1);                  %红
	g = im(:,:,2);                  %绿
	b = im(:,:,3);                  %蓝
	r_edge = edge(r,'canny');       %红边缘
	g_edge = edge(g,'canny');       %绿边缘
	b_edge = edge(b,'canny');       %蓝边缘

%显示图像
	subplot(2,3,1);imshow(r_edge);  title('红通道canny边缘','fontsize',20);
	subplot(2,3,2);imshow(g_edge);  title('绿通道canny边缘','fontsize',20);
	subplot(2,3,3);imshow(b_edge);  title('蓝通道canny边缘','fontsize',20);

%利用边界提取的方法提取
	str_ =  ones(5,5);             %结构元
 	combined_edge = im - imerode(im,str_);         %边界提取

 %显示图像
	 subplot(2,3,4);
	 r_edge2 = combined_edge(:,:,1);
	 imshow(r_edge2);title('第二种方法提红边界','fontsize',20);   
	 subplot(2,3,5);
 g_edge2 = combined_edge(:,:,2);
 	imshow(g_edge2);title('第二种方法提绿边界','fontsize',20);
 b_edge2 = combined_edge(:,:,3);
	subplot(2,3,6);
	imshow(b_edge2);title('第二种方法提蓝边界','fontsize',20);

 %开启另一个窗口对比
 	figure
 	gray_edge = edge(gray_im,'canny');
 	subplot(1,2,1);
 	imshow(gray_edge);             
	title('灰度图像提取边缘','fontsize',20);
	subplot(1,2,2);
	imshow(combined_edge);
	title('利用形态学处理提取的边界','fontsize',20);

2.孔洞填充

  孔洞是和背景相互连接的边界所包围的一个背景区域,如下面图所示,红色部分框起来的部分就是孔洞,在《数字图像处理第三版》中,处理孔洞一共有3种方法,但是在各种paper里也提出了其他的方法,其实不外乎就是基本的形态学处理、种子填充、扫描线 ,由于书上给的方法很难实现,实验的时候直接用了一个 imfill 的函数,感觉好菜,不过确实如果要知道孔洞的一个起始点,这样好费劲,还不自动。

在这里插入图片描述

2.1 形态学的方法

X k = ( X K − 1 ⊕ B ) h ∪ A C h h k = 1 , 2 , 3 , ⋯ X_k = (X_{K-1} \oplus B ) \phantom{h} \cup A^C \phantom{hh} k=1,2,3,\cdots Xk=(XK1B)hAChhk=1,2,3,  看了看图,实际是就是用了一个结构元从孔洞的一个任意内部开始膨胀,然后再和原图像的补集求交集,因为原图像孔洞部分(挖去的一部分)的值为0,而求完补集之后就变成有值的部分了,那么和做完膨胀的图像求交集就填充了一部分孔洞,然后多做几次,直到不再变化为止。
  这种方法费时费力,需要自己先定义一个起始点,然后进行膨胀,然后和补集合求交集,最后再和原来图像求并集,才能得到想要的图

在这里插入图片描述
有一个结构元是十字架,然后比如已经知道了 X 0 X_0 X0 即一个孔洞的起点,用十字架去膨胀,膨胀之后和补集求交就补了一部分,持续下去,直到你认为可以为止,matlab直接使用imfill函数即可,当然如果是手撕算法的话,

在这里插入图片描述
就是这样吧。。。把。。。。

 %MATLAB内置的函数填充
 im = imread('kongdong.tif');
 im_ = im2bw(im);
 true_im = imfill(im_,'holes');
 subplot(1,2,1);
 imshow(im);
 subplot(1,2,2);
 imshow(true_im);
    %手撕算法
    
    A = imread('kongdong.tif');
    A = im2bw(A); %二值化

    A_hat = ~A; %A的补集
    [m,n] = size(A);
    X = zeros(m,n);
    [x,y] = find(A==1);         %任意选取A中灰度值为1的点的位置 
    X(x(1),y(1)) = 1; %选取第一个灰度值为1的点为初始点
    se = [0,1,0;1,1,1;0,1,0]; %结构元
    flag = 0;  %  迭代标志
    i = 0;    %迭代次数
    
    while(~flag)
        i = i + 1;
        Xp = X;
        X = imdilate(X,se) & A_hat;     %膨胀后与补集求交集
        if X == Xp          
            flag = 1;         
        end
    end
    A_ = ~X | A; %求并集

    figure(1);
    subplot(1,2,1);
    imshow(A);
    title('二值化后的图','fontsize',30);
    subplot(1,2,2);
    imshow(A_);
title('填充结果','fontsize',30);

在这里插入图片描述
比imfill好像厉害点。。
https://blog.csdn.net/LYduring/article/details/80443709
这个手撕算法的话引用的是这篇blog里的。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现二维图像的形态学边缘提取,可以使用MATLAB中的形态学操作函数和边缘检测函数。下面是一个简单的MATLAB代码示例: ```matlab % 读取图像 img = imread('example.png'); % 将图像转换为灰度图像 gray_img = rgb2gray(img); % 对灰度图像进行二值化处理 bw_img = imbinarize(gray_img); % 定义结构元素 se = strel('disk', 5); % 对二值化图像进行膨胀操作 dilated_img = imdilate(bw_img, se); % 对膨胀后的图像进行腐蚀操作 eroded_img = imerode(dilated_img, se); % 计算边缘图像 edge_img = dilated_img - eroded_img; % 显示原图和边缘图像 figure; subplot(1, 2, 1), imshow(img), title('原图'); subplot(1, 2, 2), imshow(edge_img), title('边缘图像'); ``` 在上面的代码中,首先读取了一张图片并将其转换为灰度图像,然后对灰度图像进行了二值化处理。接着定义了一个结构元素,用于进行形态学操作。然后对二值化图像进行膨胀操作和腐蚀操作,最后计算出边缘图像。最后,使用subplot函数将原图和边缘图像显示在同一张图中。 上述代码中的strel函数用于创建一个结构元素,它的第一个参数指定了结构元素的形状,可以是'rectangle'(矩形)、'disk'(圆形)或'line'(直线)等。第二个参数指定了结构元素的大小。imdilate函数用于进行膨胀操作,而imerode函数用于进行腐蚀操作。 最后,使用图像的减法运算计算出边缘图像,即将膨胀后的图像减去腐蚀后的图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值