图像形态学_图像形态学处理 - CSDN
精华内容
参与话题
  • 形态学图像处理

    万次阅读 多人点赞 2016-12-31 16:17:01
    形态学,即数学形态学(mathematical Morphology),是图像处理中应用最为广泛的技术之一,主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质〈最具区分能力-...

    形态学,即数学形态学(mathematical Morphology),是图像处理中应用最为广泛的技术之一,主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质〈最具区分能力-most discriminative)的形状特征,如边界和连通区域等。同时像细化、像素化和修剪毛刺等技术也常应用于图像的预处理和后处理中,成为图像增强技术的有力补充。

    本文主要包括以下内容

    • 二值图像的基本形态学运算, 包括腐蚀、膨胀、开和闭。
    • 二值形态学的经典应用, 包括击中击不中变换、边界提取和跟踪、区域填充、提取连通分量、细化和像素化, 以及凸壳
    • 灰度图像的形态学运算, 包括灰度腐蚀、灰度膨胀、灰度开和灰度闭
    • 本章的典型案例分析
      • 在人脸局部图像中定位嘴的中心
      • 显微镜下图像的细菌计数
      • 利用顶帽变换(top-hat)技术解决光照不均问题

    预备知识
    在数字图像处理中, 形态学是借助集合论的语言来描述的, 本章后面的各节内容均以本集合论为基础。

    结构元素(structure element)
    设有两幅图像A, S。若A是被处理的对象, 而S是用来处理A的, 则称S为结构元素。结构元素通常都是一些比较小的图像, A与S的关系类似于滤波中图像和模板的关系.

    二值图像中的基本形态学运算

    本节介绍几种二值图像的基本形态学运算, 包括腐蚀、膨胀, 以及开、闭运算。由于所有形态学运算都是针对图像中的前景物体进行的, 因而首先对图像前景和背景的认定给出必要的说明.

    注意: 大多数图像,一般相对于背景而言物体的颜色(灰度)更深, 二值化之后物体会成为黑色, 而背景则成为白色, 因此我们通常是习惯于将物体用黑色(灰度值0)表示, 而背景用白色(灰度值255)表示,本章所有的算法示意图以及所有的Visual C++的程序实例都遵从这种约定;但Matlab 在二位图像形态学处理中,默认情况下白色的(二位图像中灰度值为1的像素,或灰度图像中灰度值为255的像素)
    是前景(物体),黑色的为背景, 因而本章涉及Matlab 的所有程序实例又都遵从Matlab本身的这种前景认定习惯.

    实际上, 无论以什么灰度值为前景和背景都只是一种处理上的习惯, 与形态学算法本身无关。例如对于上面两幅图片, 只需要在形态学处理之前先对图像反色就可以在两种认定习惯之间自由切换。

    腐蚀及其实现

    腐蚀和膨胀是两种最基本也是最重要的形态学运算, 它们是后续要介绍的很多高级形态学处理的基础, 很多其他的形态学算法都是由这两种基本运算复合而成

    matlab实现
    Matlab中与腐蚀相关的两个常用函数为imerode和strel。
    imerode函数用于完成图像腐蚀.其常用调用形式如下:I2 = imrode(I,SE)
    I为原始图像,可以是二位或灰度图像(对应于灰度腐蚀).
    SE是由strel函数返回的自定义或预设的结构元素对象.

    strel函数可以为各种常见形态学运算生成结构元素SE, 当生成供二值形态学使用的结构元素肘, 其调用形式为:SE=strl(shape,parameter)
    shape指定了结构元素的形状, 其常用合法取值如在8.1所示.

    腐蚀的作用“ 顾名思义,腐蚀能够消融物体的边界,而具体的腐蚀结果与图像本身和结构元素的形状有关。如果物体整体上大于结构元素,腐蚀的结构是使物体变“ 瘦”一圈,而
    这一圈到底有多大是由结构元素决定的:如果物体本身小于结构元素, 则在腐蚀后的图像中物体将完全消失:如物体仅有部分区域小于结构元素〈如细小的连通3,则腐蚀后物体会在细
    连通处断裂,分离为两部分。

    I = imread('erode_dilate.bmp');    
    se = strel('square',3);
    Ib = imerode(I,se);
    se = strel([0 1 0;1 1 1;0 1 0]);    
    Ic = imerode(I,se);
    se = strel('square',5);
    Id = imerode(I,se);
    
    figure;
    subplot(2,2,1);
    imshow(I);
    subplot(2,2,2);
    imshow(Ib);
    subplot(2,2,3);
    imshow(Ic);
    subplot(2,2,4);
    imshow(Id);

    随着腐蚀结构元素的逐步增大,小于结构元素的物体相继消失。由于腐蚀运算具有上述的特点,可以用于滤波。选择适当大小和形状的结构元素,可以滤除掉所有不能 完全包含结构元素的噪声点。然而,利用腐蚀滤除噪声有一个缺点,即在去除噪声点的同时,对图像中前景物体的形状也会有影响,但当我们只关心物体的位置或者个数时,则影响不大

    膨胀及其实现

    实际上, 膨胀和腐蚀对子集合求补和反射运算是彼此对偶的.
    这里值得注意的是定义中要求和A有公共交集的不是结构元素S本身, 而是S的反射集, 觉得熟悉吗?这在形式上似乎容易让我们回忆起卷积运算, 而腐蚀在形式上则更像相关运算。由于图8.8 中使用的是对称的结构元素, 故使用S 和S^' 的膨胀结果相同:但对于图8.9中非对称结构元素的膨胀示例, 则会产生完全不同的结果, 因此在实现膨胀运算时一定要先计算S^'

    matlab实现
    imdilate函数用于完成图像膨胀, 其常用调用形式如下:
    I2 = imdilate(I,SE);
    I为原始图像, 可以是二位或灰度图像(对应于灰度膨胀).
    SE是由strel函数返回的自定义或预设的结构元素对象

    膨胀的作用和腐蚀相反, 膨胀能使物体边界扩大, 具体的膨胀结果与图像本身和结构元素的形状有关。膨胀常用于将图像中原本断裂开来的同一物体桥接起来, 对图像进行二值化之后, 很容易使一个连通的物体断裂为两个部分, 而这会给后续的图像分析(如要基于连通区域的分析统计物体的个数〉造成困扰,此时就可借助膨胀桥接断裂的缝隙

    I = imread('starcraft.bmp');
    Ie1 = imerode(I,[1 1 1;1 1 1;1 1 1]);     
    Ie2 = imerode(Ie1,[0 1 0;1 1 1;0 1 0]); 
    Id1 = imdilate(Ie2,[1 1 1;1 1 1;1 1 1]);
    Id2 = imdilate(Id1,[0 1 0;1 1 1;0 1 0]);
    
    figure;
    subplot(2,2,1);
    imshow(Ie1);
    subplot(2,2,2);
    imshow(Ie2);
    subplot(2,2,3);
    imshow(Id1);
    subplot(2,2,4);
    imshow(Id2);

    开运算及其实现

    开运算和闭运算都由腐蚀和膨胀复合而成, 开运算是先腐蚀后膨胀, 而闭运算是先膨胀后腐蚀。

    一般来说, 开运算可以使图像的轮廓变得光滑, 还能使狭窄的连接断开和消除细毛刺。
    如图8.11所示, 开运算断开了团中两个小区域间两个像素宽的连接〈断开了狭窄连接〉,并且去除了右侧物体上部突出的一个小于结构元素的2×2的区域〈去除细小毛刺〉: 但与腐蚀不同的是, 图像大的轮廓并没有发生整体的收缩, 物体位置也没有发生任何变化。
    根据图8.12 的开运算示意图, 可以帮助大家更好地理解开运算的特点。为了比较, 图中也标示出了相应的腐蚀运算的结果:

    matlab实现
    根据定义,以相同的结构元素先后调用imerode和imdilate即可实现开操作。此外,Matlab 中也直接提供了开运算函数imopen, 其调用形式如下:
    I2 = imopen(I,SE);

    I = imread('erode_dilate.bmp');
    Io = imopen(I,ones(6,6));
    figure;
    subplot(1,2,1);
    imshow(I);
    subplot(1,2,2);
    imshow(Io);


    从图8.13中可以看到同腐蚀相比,开运算在过滤噪声的同时并没有对物体的形状、轮廓造成明显的影响,这是一大优势。但当我们只关心物体的位置或者个数时,物体形状的改变不会给我们带来困扰,此时用腐蚀滤波具有处理速度上的优势〈同开运算相比节省了一次膨胀运算〉。

    闭运算及其实现

    闭运算同样可以使轮廓变得光滑, 但与开运算相反, 它通常能够弥合狭窄的间断, 填充小的孔洞。

    Matlab实现
    根据定义,以相同的结构元素先后调用imdilate 和imerode 即可实现闭操作。此外,Matlab中也直接提供了闭运算函数imclose, 其用法同imopen 类似

    二值图像中的形态学应用

    击中与击不中交换及其实现

    I = zeros(120,180);
    I(11:80,16:75)=1;
    I(56:105,86:135)=1;
    I(26:55,141:170)=1;
    
    se = zeros(58,58);
    se(5:54,5:54)=1;
    
    Ie1 = imerode(I,se);
    Ic = 1 - I;
    S2 = 1 - se;
    Ie2 = imerode(Ic,S2);
    Ihm = Ie1&Ie2;
    
    figure;
    subplot(2,2,1);
    imshow(I);
    subplot(2,2,2);
    imshow(Ie1);
    subplot(2,2,3);
    imshow(Ie2);
    subplot(2,2,4);
    imshow(Ihm);


    图中给出了变换的最终结果。为便于观察在显示时每幅图像周围都环绕着一圈黑色边框, 注意该边框并不是图像本身的一部分。

    注意: 注意对于结构元素s,我们感兴趣的物体S1之外的背景S2不能选择得太宽,因为使得S包含背景S2的目的仅仅是定义出物体S1的外轮廓,以便在图像中能够
    找到准确的完全匹配位置. 从这个意义上说, 物体S1周围有一个像素宽的背景环绕就足够了, 例8.3中选择了4个像素宽的背景,是为了使结构元素背景部分应
    看起来比较明显, 但如果背景部分过大, 则会影响击中/击不中变换的计算结果.在上例中, 中间的正方形Y与右上的正方形Z之间的水平距离为6,如果在定义S时, S2的宽度超过6个像素, 则最终的计算结果将是空集.

    边界提取与跟踪及其实现

    轮廓是对物体形状的有力描述, 对图像分析和识别十分有用。通过边界提取算法可以得到物体的边界轮廓:而边界跟踪算法在提取边界的同时还能依次记录下边界像素的位置信息,下面分别介绍.

    边界提取
    要在二值图像中提取物体的边界,容易想到的一个方法是将所有物体内部的点删除(置为背景色〉。具体地说,可以逐行扫描原图像,如果发现一个黑点〈图8.17 中黑点为前景点)的8个邻域都是黑点, 则该点为内部点, 在目标图像中将它删除。实际上这相当于采用一个3*3的结构元素对原图像进行腐蚀, 使得只有那些8个邻域都有黑点的内部点被保留,再用原图像减去腐蚀后的图像, 恰好删除了这些内部点, 留下了边界像素。这一过程可参
    见图8.17 。

    I = imread('head_portrait.bmp');
    se = strel('square',3);
    Ie = imerode(I,se);
    Iout = I - Ie;
    figure;
    subplot(1,2,1);
    imshow(I);
    subplot(1,2,2);
    imshow(Iout);

    边界跟踪

    区域填充

    区域填充可视为边界提取的反过程, 它是在边界已知的情况下得到边界包围的整个区域的形态学技术。

    理论基础
    问题的描述如下: 己知某-8连通边界和边界内部的某个点, 要求从该点开始填充整个边界包围的区域, 这一过程称为种子填充, 填充的开始点被称为种子.
    如图8.20 所示, 对于4 连通的边界, 其围成的内部区域是8 连通的, 而8连通的边界围成的内部区域却是4连通的.

    为了填充4 连通的边界应选择图8.20 (b )中的3 × 3 结构元素, 但如果想在8 连通边界内从种子点得到区域则需选用图8.20 (d)的十字结构元素S 对初始时仅为种子点的图像B进行膨胀,十字结构元素S能够保证只要B在边界A的内部〈不包括边界本身〉,每次膨胀都不会产生边界之外的点(新膨胀出来的点或者在边界内部, 或者落在边界上〉, 这样只需把每次膨胀的结果图像和边界的补图像Ac相交, 就能把膨胀限制在边界内部。随着对B的
    不断膨胀, B的区域不断生长, 但每次膨胀后与Ac的交又将B限制在边界d的内部, 这样一直到最终B充满整个A的内部区域,停止生长。此时的B与d的并集即为最终的区域填充结果。

    连通分量提取及其实现

    连通分量的概念在0.3.1小节中曾介绍过。在二值图像中提取连通分量是许多自动图像分析应用中的核心任务。提取连通分量的过程实际上也是标注连通分量的过程, 通常的做法是给原图像中的每个连通区分配一个唯一代表该区域的编号, 在输出图像中该连通区内的所有像素的像素值就赋值为该区域的编号, 我们将这样的输出图像称为标注图像。

    matlab实现
    在Matlab中, 连通分量的相关操作主要借助IPT函数bwlabel实现. 其调用语法为
    [L num]= bwlabel(Ibw,conn);
    Ibw为一幅输入二位图像.
    conn为可选参数, 指明要提取的连通分量是4连边还是8连通, 默认值为8.
    L为类似于图8.23 ( b)的标注图像.
    num为二维图像Ibw中连通分量的个数.

    提取连通分量的应用十分广泛, 利用标注图像可以方便地进行很多基于连通区的操作。例如要计算某一连通分量的大小, 只需扫描一遍标注图像, 对像素值为该区编号的像素进行计数: 又如要计算某一连通分量的质心, 只需扫描一遍标注图像, 找出所有像素值为该区编号的像素的x、y坐标, 然后计算其平均值.

    在人脸局部图像中定位嘴的中心
    我们希望在如图8.24 (a )所示的图像中定位嘴的中心,假定已经掌握了输入图像中的某些先验知识,嘴部占据了图像的大部分区域且从灰度上易于与周围皮肤分离开来. 于是针
    对性地拟定了在二位化图像中寻找最大连通区域中心的解决方案, 具体步骤为:
    (1)对输入图像进行二位化处理.
    (2)标注二值图像中的连通分量.
    (3)找出最大的连通分量.
    (4)计算最大连通分量的中心.

    % locateMouth.m
    
    I = imread('mouth.bmp'); %读入图像
    Id = im2double(I);
    figure, imshow(Id) % 得到8.24(a)
    Ibw = im2bw(Id, 0.38); % 以0.38为阈值二值化
    Ibw = 1 - Ibw; %为在Matlab中进行处理,将图像反色
    figure, imshow(Ibw) % 得到8.24(b)
    hold on
    [L, num] = bwlabel(Ibw, 8); % 标注连通分量
    disp(['图中共有' num2str(num) '个连通分量'])
    
    % 找出最大的连通分量(嘴)
    max = 0; % 当前最大连通分量的大小
    indMax = 0; % 当前最大连通分量的索引
    for k = 1:num
        [y x] = find(L == k); % 找出编号为k的连通区的行索引集合y和列索引集合x
    
        nSize = length(y); %计算该连通区中的像素数目
        if(nSize > max)
            max = nSize;
            indMax = k;
        end
    end
    
    if indMax == 0
        disp('没有找到连通分量')
        return
    end
    
    % 计算并显示最大连通分量(嘴)的中心
    [y x] = find(L == indMax);
    yMean = mean(y);
    xMean = mean(x);
    plot(xMean, yMean, 'Marker', 'o', 'MarkerSize', 14, 'MarkerEdgeColor', 'w', 'MarkerFaceColor', 'w');
    plot(xMean, yMean, 'Marker', '*', 'MarkerSize', 12, 'MarkerEdgeColor', 'k'); % 得到8.24(c)

    细菌计数

    I = imread('bw_bacteria.bmp');
    [L,num]=bwlabel(I,8);
    Idil = imdilate(I,ones(3,3));
    [L,num] = bwlabel(Idil,8);
    
    figure;
    subplot(1,2,1);
    imshow(I);
    subplot(1,2,2);
    imshow(Idil);

    展开全文
  • opencv 形态学处理

    千次阅读 2018-04-06 10:11:35
    一、话说形态学图像形态学中的几个基本操作:腐蚀、膨胀、开操作、闭操作。1.1 腐蚀结构A被结构B腐蚀的定义为, A⨀B={z|(B)z⊆A}A⨀B={z|(B)z⊆A}可以理解为,移动结构B,如果结构B与结构A的交集完全属于结构A的...

    一、话说形态学

    图像形态学中的几个基本操作:腐蚀、膨胀、开操作、闭操作。

    1.1 腐蚀

    结构A被结构B腐蚀的定义为, 

    AB={z|(B)zA}A⨀B={z|(B)z⊆A}

    可以理解为,移动结构B,如果结构B与结构A的交集完全属于结构A的区域内,则保存该位置点,所有满足条件的点构成结构A被结构B腐蚀的结果。 


    1.2 膨胀

    结构A被结构B膨胀的定义为, 

    AB={z|(B^)zA}A⨁B={z|(B^)z⋂A≠∅}

    可以理解为,将结构B在结构A上进行卷积操作,如果移动结构B的过程中,与结构A存在重叠区域,则记录该位置,所有移动结构B与结构A存在交集的位置的集合为结构A在结构B作用下的膨胀结果。 

    图示中红色框内的区域表示结构A在结构B的作用下膨胀的结果。 


    这里有另外一个例子。


    1.3 开运算

    先腐蚀后膨胀的操作称之为开操作。它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。 采用上图的结构B对原件进行开操作。

    1.4 闭运算

    先膨胀后腐蚀的操作称之为闭操作。它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。 

    采用上图的结构对原件进行闭操作。


    以上部分内容出自 点击打开链接

    二、相关API 

    2.1 膨胀

    dst=cv2.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
    
    • src:源图,通道数任意,深度需为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F
    • dst:输出图,与src有着同样的尺寸
    • kernel:膨胀操作的核,通常这个参数由函数getStructuringElement得到(稍后会讲)
    • anchor:锚点位置,默认值为中心点
    • iterations:自身迭代的次数,默认为1
    • borderType和borderValue都有各自的默认值,通常不用理会

    2.2 腐蚀

    dst=cv2.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
    
    • kernel:腐蚀操作的核,通常这个参数由函数getStructuringElement得到(稍后会讲)
    • iterations:自身迭代的次数,默认值为1

    再讲讲这个用于计算kernel的函数getStructuringElement,原型:

    retval=cv2.getStructuringElement(shape, ksize[, anchor])
    
    • retval:得到的核,矩阵形式
    • shape:核的形状,有cv2.MORPH_RECT、cv2.MORPH_CROSS和cv2.MORPH_ELLIPSE
    • ksize:核的大小, (x,y) 形式
    • anchor:锚点,默认为中心

    2.3 开运算和闭运算

    开运算:

    先腐蚀后膨胀,用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。

    闭运算:

    先膨胀后腐蚀,闭运算能够排除小的黑色区域。

    形态学梯度:

    膨胀图与腐蚀图之差,通常用来保留边缘轮廓(不是轮廓和边缘识别)。

    上述三种常规操作是通过调用函数morphologyEx并修改对应的参数来实现的。

    函数原型:

    dst=cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
    
    • src:源图,深度需为CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F
    • op:操作标识符,即进行哪种操作,有下表(节选,注意将cv改为cv2):

    • kernel:核,依然由getStructuringElement求得。

    三、实验

    3.1 腐蚀与膨胀

    	Mat src = imread("D:\\cv_study\\随机练\\gonglu.jpg");
    	Mat dilate_dst, gray, erode_dst;
    	Mat element = getStructuringElement(MORPH_RECT, Size(8, 8));
    	dilate(src, dilate_dst, element);
    	erode(src, erode_dst, element);


    3.2 开和闭

    	Mat src = imread("D:\\cv_study\\随机练\\gonglu.jpg");
    	Mat close, gray, open,dst;
    	Mat element = getStructuringElement(MORPH_RECT, Size(8, 8));
    	cvtColor(src, gray, CV_BGR2GRAY);
    	threshold(gray, gray, 100, 255, THRESH_BINARY);
    	morphologyEx(gray, open, MORPH_OPEN, element);
    	morphologyEx(gray, close, MORPH_CLOSE, element);
    	morphologyEx(src, dst, MORPH_GRADIENT, element);


    由上面的结果可以看出开运算能够消除小物体,闭运算能够排除小黑色区域。以上就是关于形态学处理的内容,欢迎批评指正。

    展开全文
  • matlab基于形态学的权重自适应图像去噪
  • 图像形态学处理

    千次阅读 2019-07-12 11:02:17
    本章的练习主要是形态学的一些基本概念和技术,这些构成了一组提取图像特征的有力工具,针对二值图像和灰度图像的腐蚀、膨胀和重构的基本操作可以组合使用,以执行非常宽泛的任务。其练习代码和结果如下:...

    转自

    https://www.cnblogs.com/tornadomeet/archive/2012/03/20/2408086.html

     

    Matlab DIP(瓦)ch9形态学图像处理

        本章的练习主要是形态学的一些基本概念和技术,这些构成了一组提取图像特征的有力工具,针对二值图像和灰度图像的腐蚀、膨胀和重构的基本操作可以组合使用,以执行非常宽泛的任务。其练习代码和结果如下:

     

    复制代码

      1 %% 第9章 形态学处理
      2 
      3 %% imdilate膨胀
      4 clc
      5 clear
      6 
      7 A1=imread('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif');
      8 info=imfinfo('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif')
      9 B=[0 1 0
     10    1 1 1
     11    0 1 0];
     12 A2=imdilate(A1,B);%图像A1被结构元素B膨胀
     13 A3=imdilate(A2,B);
     14 A4=imdilate(A3,B);
     15 
     16 subplot(221),imshow(A1);
     17 title('imdilate膨胀原始图像');
     18 
     19 subplot(222),imshow(A2);
     20 title('使用B后1次膨胀后的图像');
     21 
     22 subplot(223),imshow(A3);
     23 title('使用B后2次膨胀后的图像');
     24 
     25 subplot(224),imshow(A4);
     26 title('使用B后3次膨胀后的图像');
     27%imdilate图像膨胀处理过程运行结果如下:

     28 
     29 %% imerode腐蚀
     30 clc
     31 clear
     32 A1=imread('.\images\dipum_images_ch09\Fig0908(a)(wirebond-mask).tif');
     33 subplot(221),imshow(A1);
     34 title('腐蚀原始图像');
     35 
     36 %strel函数的功能是运用各种形状和大小构造结构元素
     37 se1=strel('disk',5);%这里是创建一个半径为5的平坦型圆盘结构元素
     38 A2=imerode(A1,se1);
     39 subplot(222),imshow(A2);
     40 title('使用结构原始disk(5)腐蚀后的图像');
     41 
     42 se2=strel('disk',10);
     43 A3=imerode(A1,se2);
     44 subplot(223),imshow(A3);
     45 title('使用结构原始disk(10)腐蚀后的图像');
     46 
     47 se3=strel('disk',20);
     48 A4=imerode(A1,se3);
     49 subplot(224),imshow(A4);
     50 title('使用结构原始disk(20)腐蚀后的图像');
     51 %图像腐蚀处理过程运行结果如下:
     52 

     53 %% 开运算和闭运算
     54 clc
     55 clear
     56 f=imread('.\images\dipum_images_ch09\Fig0910(a)(shapes).tif');
     57 %se=strel('square',5');%方型结构元素
     58 se=strel('disk',5');%圆盘型结构元素
     59 imshow(f);%原图像
     60 title('开闭运算原始图像')
     61%运行结果如下:

     62 
     63 %开运算数学上是先腐蚀后膨胀的结果
     64 %开运算的物理结果为完全删除了不能包含结构元素的对象区域,平滑
     65 %了对象的轮廓,断开了狭窄的连接,去掉了细小的突出部分
     66 fo=imopen(f,se);%直接开运算
     67 figure,subplot(221),imshow(fo);
     68 title('直接开运算');
     69 
     70 %闭运算在数学上是先膨胀再腐蚀的结果
     71 %闭运算的物理结果也是会平滑对象的轮廓,但是与开运算不同的是,闭运算
     72 %一般会将狭窄的缺口连接起来形成细长的弯口,并填充比结构元素小的洞
     73 fc=imclose(f,se);%直接闭运算
     74 subplot(222),imshow(fc);
     75 title('直接闭运算');
     76 
     77 foc=imclose(fo,se);%先开后闭运算
     78 subplot(223),imshow(foc);
     79 title('先开后闭运算');
     80 
     81 fco=imopen(fc,se);%先闭后开运算
     82 subplot(224),imshow(fco);
     83 title('先闭后开运算');
     84%开闭运算结果如下:

     85 
     86 %先膨胀再腐蚀
     87 fse=imdilate(f,se);%膨胀
     88 
     89 %gcf为得到当前图像的句柄,当前图像是指例如PLOT,TITLE,SURF等
     90 %get函数为得到物体的属性,get(0,'screensize')为返回所有物体screensize属性值
     91 %set函数为设置物体的属性
     92 figure,set(gcf,'outerposition',get(0,'screensize'));%具体目的是设置当前窗口的大小
     93 subplot(211),imshow(fse);
     94 title('使用disk(5)先膨胀后的图像');
     95 
     96 fes=imerode(fse,se);
     97 subplot(212),imshow(fes);
     98 title('使用disk(5)先膨胀再腐蚀后的图像');
     99%先膨胀后腐蚀图像如下:

    100 
    101 %先腐蚀再膨胀
    102 fse=imerode(f,se);
    103 figure,set(gcf,'outerposition',get(0,'screensize'))
    104 subplot(211),imshow(fse);
    105 title('使用disk(5)先腐蚀后的图像');
    106 
    107 fes=imdilate(fse,se);
    108 subplot(212),imshow(fes);
    109 title('使用disk(5)先腐蚀再膨胀后的图像');
    110%先腐蚀后膨胀的图像如下:

    111 
    112 %% imopen imclose在指纹上的应用
    113 clc
    114 clear
    115 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
    116 se=strel('square',3);%边长为3的方形结构元素
    117 subplot(121),imshow(f);
    118 title('指纹原始图像');
    119 
    120 A=imerode(f,se);%腐蚀
    121 subplot(122),imshow(A);
    122 title('腐蚀后的指纹原始图像');
    123%指纹原始图像和腐蚀后的图像结果如下:

    124 
    125 fo=imopen(f,se);
    126 figure,subplot(221),imshow(fo);
    127 title('使用square(3)开操作后的图像');
    128 
    129 fc=imclose(f,se);
    130 subplot(222),imshow(fc);
    131 title('使用square闭操作后的图像');
    132 
    133 foc=imclose(fo,se);
    134 subplot(223),imshow(foc);
    135 title('使用square(3)先开后闭操作后的图像')
    136 
    137 fco=imopen(fc,se);
    138 subplot(224),imshow(fco);
    139 title('使用square(3)先闭后开操作后的图像');
    140%指纹图像开闭操作过程结果如下:

    141 
    142 %% bwhitmiss击中或击不中变换
    143 clc
    144 clear
    145 f=imread('.\images\dipum_images_ch09\Fig0913(a)(small-squares).tif');
    146 imshow(f);
    147 title('击中或不击中原始图像');
    148%击中或不击中原始图像显示结果如下:

    149 
    150 B1=strel([0 0 0;0 1 1;0 1 0]);%击中:要求击中所有1的位置
    151 B2=strel([1 1 1;1 0 0;1 0 0]);%击不中,要求击不中所有1的位置
    152 B3=strel([0 1 0;1 1 1;0 1 0]);%击中
    153 B4=strel([1 0 1;0 0 0;0 0 0]);%击不中
    154 B5=strel([0 0 0;0 1 0;0 0 0]);%击中
    155 B6=strel([1 1 1;1 0 0;1 0 0]);%击不中
    156 
    157 g=imerode(f,B1)&imerode(~f,B2)%利用定义来实现击中或击不中
    158 figure,subplot(221),imshow(g);
    159 title('定义实现组1击中击不中图像');
    160 
    161 g1=bwhitmiss(f,B1,B2);
    162 subplot(222),imshow(g1);
    163 title('结构数组1击中击不中后的图像');
    164 
    165 g2=bwhitmiss(f,B3,B4);
    166 subplot(223),imshow(g2);
    167 title('结构数组2击中击不中的图像');
    168 
    169 g3=bwhitmiss(f,B5,B6);
    170 subplot(224),imshow(g3);
    171 title('结构数组3击中击不中的图像');
    172%击中击不中变换后图像如下:

    173 
    174 %%makelut
    175 clc
    176 clear
    177 
    178 f=inline('sum(x(:))>=3');%inline是用来定义局部函数的
    179 lut2=makelut(f,2)%为函数f构造一个接收2*2矩阵的查找表
    180 lut3=makelut(f,3)
    181 
    182 %% Conway生命游戏
    183 clc
    184 clear
    185 lut=makelut(@conwaylaws,3);
    186 bw1=  [0     0     0     0     0     0     0     0     0     0
    187        0     0     0     0     0     0     0     0     0     0
    188        0     0     0     1     0     0     1     0     0     0
    189        0     0     0     1     1     1     1     0     0     0
    190        0     0     1     0     0     0     0     1     0     0
    191        0     0     1     0     1     1     0     1     0     0
    192        0     0     1     0     0     0     0     1     0     0
    193        0     0     0     1     1     1     1     0     0     0
    194        0     0     0     0     0     0     0     0     0     0
    195        0     0     0     0     0     0     0     0     0     0  ];
    196 subplot(221),imshow(bw1,'InitialMagnification','fit');
    197 title('Generation 1');
    198 
    199 bw2=applylut(bw1,lut);
    200 subplot(222),imshow(bw2,'InitialMagnification','fit'),
    201 title('Generation 2');
    202 
    203 bw3=applylut(bw2,lut);
    204 subplot(223),imshow(bw3,'InitialMagnification','fit');
    205 title('Generation 3');
    206 
    207 temp=bw1;
    208 for i=2:100
    209     bw100=applylut(temp,lut);
    210     temp=bw100;
    211 end
    212 subplot(224),imshow(bw100,'InitialMagnification','fit')
    213 title('Generation 100');
    214%显示Generation结果如下:

    215 
    216 %% getsequence
    217 clc
    218 clear
    219 se=strel('diamond',5)
    220 decomp=getsequence(se)%getsequence函数为得到分解的strel序列
    221 decomp(1)
    222 decomp(2)
    223 
    224 %% endpoints
    225 clc
    226 clear
    227 
    228 f1=imread('.\images\dipum_images_ch09\Fig0914(a)(bone-skel).tif');
    229 subplot(121),imshow(f1);
    230 title('原始形态骨架图像');
    231 
    232 g1=endpoints(f1);
    233 %set(gcf,'outerposition',get(0,'screensize'));%运行完后自动生成最大的窗口
    234 subplot(122),imshow(g1);
    235 title('骨架图像的端点图像');
    236 %骨架头像端点检测头像如下:
    237 
    238 f2=imread('.\images\dipum_images_ch09\Fig0916(a)(bone).tif');
    239 figure,subplot(121),imshow(f2);
    240 title('原始骨头图像');
    241 
    242 g2=endpoints(f2);
    243 subplot(122),imshow(g2);
    244 title('骨头图像端点头像');%结果是没有端点
    245%骨头头像端点检测图像如下:

    246 
    247 %% bwmorph组合常见形态学之细化
    248 clc
    249 clear
    250 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
    251 subplot(221),imshow(f);
    252 title('指纹图像细化原图');
    253 
    254 g1=bwmorph(f,'thin',1);
    255 subplot(222),imshow(g1);
    256 title('指纹图像细化原图');
    257 
    258 g2=bwmorph(f,'thin',2);
    259 subplot(223),imshow(g2);
    260 title('指纹图像细化原图');
    261 
    262 g3=bwmorph(f,'thin',Inf);
    263 subplot(224),imshow(g3);
    264 title('指纹图像细化原图');
    265%指纹图像细化过程显示如下:

    266 
    267 %% bwmorph组合常见形态学之骨骼化
    268 clc
    269 clear
    270 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
    271 subplot(131),imshow(f);
    272 title('指纹图像骨骼化原图');
    273 
    274 fs=bwmorph(f,'skel',Inf);
    275 subplot(132),imshow(fs);
    276 title('指纹图像骨骼化');
    277 
    278 for k=1:5
    279     fs=fs&~endpoints(fs);
    280 end
    281 subplot(133),imshow(fs);
    282 title('指纹图像修剪后骨骼话');
    283%指纹图像骨骼化过程显示:

    284 
    285 %% 使用函数bwlabel标注连通分量
    286 clc
    287 clear
    288 f=imread('.\images\dipum_images_ch09\Fig0917(a)(ten-objects).tif');
    289 imshow(f),title('标注连通分量原始图像');
    290%其结果显示如下:

    291 
    292 [L,n]=bwlabel(f);%L为标记矩阵,n为找到连接分量的总数
    293 [r,c]=find(L==3);%返回第3个对象所有像素的行索引和列索引
    294 
    295 rbar=mean(r);
    296 cbar=mean(c);
    297 
    298 figure,imshow(f)
    299 hold on%保持当前图像使其不被刷新
    300 for k=1:n
    301     [r,c]=find(L==k);
    302     rbar=mean(r);
    303     cbar=mean(c);
    304     plot(cbar,rbar,'Marker','o','MarkerEdgeColor','k',...
    305          'MarkerFaceColor','k','MarkerSize',10);%这个plot函数用法不是很熟悉
    306     plot(cbar,rbar,'Marker','*','MarkerFaceColor','w');%其中的marker为标记
    307 end
    308 title('标记所有对象质心后的图像');

    309 
    310 %% 由重构做开运算
    311 clc
    312 clear
    313 f=imread('.\images\dipum_images_ch09\Fig0922(a)(book-text).tif');
    314 subplot(321),imshow(f);
    315 title('重构原始图像');
    316 
    317 fe=imerode(f,ones(51,1));%竖线腐蚀
    318 subplot(322),imshow(fe);
    319 title('使用竖线腐蚀后的结果');
    320 
    321 fo=imopen(f,ones(51,1));%竖线做开运算
    322 subplot(323),imshow(fo);
    323 title('使用竖线做开运算结果');
    324 
    325 fobr=imreconstruct(fe,f);%fe做标记
    326 subplot(324),imshow(fobr);
    327 title('使用竖线做重构开运算');
    328 
    329 ff=imfill(f,'holes');%对f进行孔洞填充
    330 subplot(325),imshow(ff);
    331 title('对f填充孔洞后的图像');
    332 
    333 fc=imclearborder(f,8);%清除边界,2维8邻接
    334 subplot(326),imshow(fc);
    335 title('对f清除边界后的图像');
    336%图像重构过程显示如下:

    337 
    338 %% 使用顶帽变换和底帽变换
    339 clc
    340 clear
    341 f=imread('.\images\dipum_images_ch09\Fig0926(a)(rice).tif');
    342 subplot(221),imshow(f);
    343 title('顶帽底帽变换原始图像');
    344 
    345 se=strel('disk',10);%产生结构元素
    346 %顶帽变换是指原始图像减去其开运算的图像
    347 %而开运算可用于补偿不均匀的背景亮度,所以用一个大的结构元素做开运算后
    348 %然后用原图像减去这个开运算,就得到了背景均衡的图像,这也叫做是图像的顶帽运算
    349 f1=imtophat(f,se);%使用顶帽变换
    350 subplot(222),imshow(f1);
    351 title('使用顶帽变换后的图像');
    352 
    353 %底帽变换是原始图像减去其闭运算后的图像
    354 f2=imbothat(imcomplement(f),se);%使用底帽变换,为什么原图像要求补呢?
    355 %f2=imbothat(f,se);%使用底帽变换
    356 subplot(223),imshow(f2);
    357 title('使用底帽变换后的图像');
    358 
    359 %顶帽变换和底帽变换联合起来用,用于增加对比度
    360 f3=imsubtract(imadd(f,imtophat(f,se)),imbothat(f,se));%里面参数好像不合理?
    361 subplot(224),imshow(f3);
    362 title('使用顶帽底帽联合变换后图像');
    363%顶帽底帽变换过程图像如下:

    364 
    365 %%使用开运算和闭运算做形态学平滑
    366 %由于开运算可以除去比结构元素更小的明亮细节,闭运算可以除去比结构元素更小的暗色细节
    367 %所以它们经常组合起来一起进行平滑图像并去除噪声
    368 clc
    369 clear
    370 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif');
    371 subplot(221),imshow(f);
    372 title('木钉图像原图');
    373 
    374 se=strel('disk',5);%disk其实就是一个八边形
    375 fo=imopen(f,se);%经过开运算
    376 subplot(222),imshow(f);
    377 title('使用半径5的disk开运算后的图像');
    378 
    379 foc=imclose(fo,se);
    380 subplot(223),imshow(foc);
    381 title('先开后闭的图像');
    382 
    383 fasf=f;
    384 for i=2:5
    385     se=strel('disk',i);
    386     fasf=imclose(imopen(fasf,se),se);
    387 end
    388 subplot(224),imshow(fasf);
    389 title('使用开闭交替滤波后图像');
    390%使用开运算和闭运算做形态学平滑结果如下:

    391 
    392 %% 颗粒分析
    393 clc
    394 clear
    395 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif');
    396 
    397 sumpixels=zeros(1,36);
    398 for k=0:35
    399     se=strel('disk',k);
    400     fo=imopen(f,se);
    401     sumpixels(k+1)=sum(fo(:));
    402 end
    403 
    404 %可以看到,连续开运算之间的表面积会减少
    405 plot(0:35,sumpixels),xlabel('k'),ylabel('surface area');
    406 title('表面积和结构元素半径之间的关系');
    407%其运算结果如下:   

    408 
    409 figure,plot(-diff(sumpixels));%diff()函数为差分或者近似倒数,即相邻2个之间的差值
    410 xlabel('k'),ylabel('surface area reduction');
    411 title('减少的表面积和结构元素半径之间的关系');
    412%其运算结果如下:

    413 
    414 %% 使用重构删除复杂图像的背景
    415 clc
    416 clear
    417 f=imread('.\images\dipum_images_ch09\Fig0930(a)(calculator).tif');
    418 subplot(221),imshow(f);
    419 title('灰度级重构原图像');
    420 
    421 f_obr=imreconstruct(imerode(f,ones(1,71)),f);
    422 subplot(222),imshow(f_obr);
    423 title('经开运算重构图');
    424 
    425 f_o=imopen(f,ones(1,71));
    426 subplot(223),imshow(f_o);
    427 title('经开运算后图');
    428 
    429 f_thr=imsubtract(f,f_obr);
    430 subplot(224),imshow(f_thr);
    431 title('顶帽运算重构图')
    432%使用重构删除复杂图像的背景1:

    433 
    434 f_th=imsubtract(f,f_o)
    435 figure,subplot(221),imshow(f_th);
    436 title('经顶帽运算图');
    437 
    438 g_obr=imreconstruct(imerode(f_thr,ones(1,11)),f_thr);
    439 subplot(222),imshow(g_obr);
    440 title('用水平线对f_thr经开运算后重构图');
    441 
    442 g_obrd=imdilate(g_obr,ones(1,2));
    443 subplot(223),imshow(g_obrd);
    444 title('使用水平线对上图进行膨胀');
    445 
    446 f2=imreconstruct(min(g_obrd,f_thr),f_thr);
    447 subplot(224),imshow(f2);
    448 title('最后的重构结果');
    449%使用重构删除复杂图像的背景2:

    复制代码

     

        形态学这一章很有用,因为它还可以应用在图像分割中。

     

    展开全文
  • 图像形态学

    2020-04-14 17:20:17
    图像形态学 1、是图像处理学科的一个单独分支学科 2、灰度与二值图像处理中重要手段 3、是由数学的集合论等相关理论发展起来的 膨胀 3*3的结构元素/模板 注意: –腐蚀与膨胀都支持 –任意形状的结构元素 膨胀的作用...

    图像形态学

    1、是图像处理学科的一个单独分支学科
    2、灰度与二值图像处理中重要手段
    3、是由数学的集合论等相关理论发展起来的
    膨胀
    3*3的结构元素/模板
    注意:
    –腐蚀与膨胀都支持
    –任意形状的结构元素

    膨胀的作用(Dilata)
    或操作也就是最大值替换中心像素
    1、对象大小增加一个像素(3*3)
    2、平滑对象边缘
    3、减少或者填充对象之间的距离

    腐蚀的作用 (Erode)
    与操作也就是最小值替换中心像素
    1、对象大小减少1个像素(3*3)
    2、平滑对象边缘
    3、弱化或者分割图像之间的半岛型连接

    也可以对彩色图像进行膨胀或腐蚀操作
    膨胀:opencv定义用最大值取代中心像素,用最大值彩色图像会变得超级亮,黑色的部分变得很少,白色的部分变多,整个图像变量
    腐蚀:opencv定义用最小值取代中心像素,黑色部分颜色加重,白色部分变少

    先确认核的中心点
    在这里插入图片描述

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

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

    import cv2 as cv
    import numpy as np
    
    print("----------------hi.python!---------------------------")
    src = cv.imread("C:/Users/LENOVO/Desktop/test image/shouxie.jpg")
    cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)  # 创建一个window
    cv.imshow("input image",src)
    
    def erode_demo(image):      # 腐蚀
        print(image.shape)
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)  # 返回两个量,ret返回阈值大小,binary返回得到二值图像
        kenel = cv.getStructuringElement(cv.MORPH_RECT, (20, 20))   # 通过改变模板的大小(5, 5)或(3, 3)会出现不同程度的腐蚀现象
        cv.imshow("binary", binary)
        cv.imshow("erode_demo", dst)
    
    def dilate_demo(image):      # 膨胀
        print(image.shape)
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)  # 返回两个量,ret返回阈值大小,binary返回得到二值图像
        kenel = cv.getStructuringElement(cv.MORPH_RECT, (6, 6))   # 通过改变模板的大小(5, 5)或(3, 3)会出现不同程度的腐蚀现象
        cv.imshow("binary", binary)
        dst = cv.dilate(binary, kenel)
        cv.imshow("erode_demo", dst)
    
    # 也可对彩色图像进行膨胀或腐蚀操作
        dst = cv.erode(binary, kenel)
    sr = cv.imread("C:/Users/LENOVO/Desktop/test image/lenaa.bmp")
    cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)  # 创建一个window
    cv.imshow("input image",sr)
    kenel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))   # 通过改变模板的大小(5, 5)或(3, 3)会出现不同程度的腐蚀现象
    #ds = cv.erode(sr, kenel)
    ds = cv.dilate(sr, kenel)   
    cv.imshow("erode_demo", ds)
    
    # erode_demo(src)
    #dilate_demo(src)
    cv.waitKey(0)
    cv.destroyAllWindows()
    
    展开全文
  • 原理:在特殊领域运算形式——结构元素(Sturcture Element),在每个像素位置上与二值图像对应的区域进行特定的逻辑运算。运算结构是输出图像的相应像素。运算效果取决于结构元素大小内容以及逻辑运算性质。 结构...
  • 数字图像处理(一) ——形态学处理

    万次阅读 2018-09-12 15:01:54
    1 形态学基本操作 1.1 膨胀 膨胀:就是求局部最大值的操作。 按数学方面来说,膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为A)与核(我们称之为B)进行卷积。 核可以是任何的形状和大小,它拥有...
  • 图像形态学操作

    千次阅读 2019-02-23 09:47:42
    图像形态学操作 微信公众号:幼儿园的学霸 个人的学习笔记,关于OpenCV,关于机器学习, … 问题或建议,请公众号留言; 看到一段话,深有感触 作为软件开发者,我们曾经写过的或者正在写的每一行代码都对我们的...
  • 在这里我们将接着上次的内容,接着描述其它的一些图像形态学操作方法,以及相应的Python实现。 图像的开运算 开运算的具体实现:通过先进性腐蚀操作,再进行膨胀操作得到。我们在移除小的对象时候很有用(假设...
  • MATLAB(三) 图像处理--形态学

    千次阅读 2018-05-11 13:11:29
    形态学处理 二值形态学 1. 结构元素的构造与分解 2.腐蚀与膨胀 3.开操作与闭操作 4.形态学滤波器 5.击中或击不中变换 6.二值图像形态学变换 7.形态学操作 灰度形态学 1.膨胀与腐蚀 2.开操作与闭操作 3.形态学...
  • 数学形态学运算——腐蚀、膨胀、开运算、闭运算

    万次阅读 多人点赞 2018-03-27 10:21:48
    数学形态学操作可以分为二值形态学和灰度形态学,灰度形态学由二值形态学扩展而来。数学形态学有2个基本的运算,即腐蚀和膨胀,而腐蚀和膨胀通过结合又形成了开运算和闭运算。 开运算就是先腐蚀再膨胀,闭运算就是...
  • 形态学重建

    千次阅读 2011-05-13 20:43:00
     在形态学梯度图像的基础上,利用形态学的开闭重建运算对梯度图像进行重建,在保留重要区域伦敦的同时去除细节和噪声。  分水岭变换存在过分割现象,原因在于检测的局部极值过多,造成极值过多的原因...
  • 膨胀、腐蚀、开、闭运算是数学形态学最基本的变换。 本文主要针对二值图像形态学 膨胀:把二值图像各1像素连接成分的边界扩大一层(填充边缘或0像素内部的孔); 腐蚀:把二值图像各1像素连接成分的边界点去掉...
  • 学习DIP第16天 转载请标明本文出处:... 新年第一篇博客,希望大家新年里能都收获更多的知识和技术,今天说的是灰度图像形态学处理,灰度图像与二值图像的区别在于其记录了灰度信息,所以,形态...
  • 图像处理之形态学梯度计算

    千次阅读 2016-10-23 18:06:51
    介绍图像处理形态学基本操作腐蚀与膨胀组合实现图像基本梯度计算、内部梯度、外部梯度与方向梯度等扩展知识点。
  • 图像形态学处理(2)

    千次阅读 2016-03-17 23:11:18
    接上篇图像形态学处理(1) 5)细化、粗化
  • 数学形态学
  • 图像处理--形态学

    万次阅读 2016-11-15 10:45:08
    最基本两个形态学运算----膨胀与腐蚀 膨胀与腐蚀能够实现以下作用:  1.消除噪声  2.分割出独立的图像元素,在图像中连接相邻的元素  3.寻找图像中的明显的极大值区域或者极小值区域  4.求出图像的梯度...
  • 形态学运算之基本概念

    万次阅读 2017-03-22 17:29:15
    形态学运算是针对二值图像依据数学形态学(Mathematical Morphology)的集合论方法发展起来的图像处理方法。 通常,形态学图像处理表现为一种邻域运算形式,一种特殊定义的领域称之为“结构元素”(Structure ...
  • 功能:图像平滑和去噪(形态学滤波)。 用法:对图像f先进行开操作,然后对结果进行闭操作,然后再对结果进行开操作,然后再对结果进行闭操作。。。。。 简单点理解: 1)把开操作和闭操作(或者闭操作和开操作,...
1 2 3 4 5 ... 20
收藏数 23,006
精华内容 9,202
关键字:

图像形态学