数字图像处理第九章形态学处理

第九章 形态学图像处理

1.基础概念

形态学图像处理的基本思想是:把图像视为多个基本形状组成的,分析这些基本形状以便于后期处理图像。基本操作有:膨胀、腐蚀等。

2.基本操作介绍

  • 腐蚀:是一种基本的形态学变换操作之一,它可以用来缩小或者消除二值图像中物体的边缘。
    腐蚀操作的原理是将一个结构元素(通常是一个小的矩形或圆形)沿着图像的边界向内滑动,如果结构元素与图像中的像素完全重合,则该像素保留,否则该像素被删除。这样,腐蚀操作可以消除图像中的细节和小的物体,使得图像变得更加简单和平滑。公式表达如式1
    A ⊖ B = { z ∣ ( B ) z ⊆ A } (1) A\ominus B=\{z|(B)_z\subseteq A\}\tag1 AB={z(B)zA}(1)
    Z为一片区域,A、B集合则包含于Z,式1表示A被B腐蚀。
    代码:

    import cv2
    import numpy as np
    # 读入图像
    img = cv2.imread('aTempImage/9/1.tif', cv2.IMREAD_GRAYSCALE)
    # 定义结构元素
    kernel = np.ones((5,5), np.uint8)
    # 执行腐蚀操作
    erosion = cv2.erode(img, kernel, iterations=1)
    # 显示结果
    result = cv2.hconcat([img,erosion])
    cv2.imshow('result',result)
    cv2.imwrite('aTempImage/9/2.tif',result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

效果:在这里插入图片描述

分析:设置了一个5x5矩形结构,用erode()函数来腐蚀图像,iteration参数是腐蚀的迭代次数。处理的图像是书本上的案例,如图所示,经过腐蚀之后,宽度较大的白色部分明显减少 且有向细线形状转变的趋势,部分白色细线则完全消失,如果这个核(5x5的矩形结构)再扩大,或者迭代次数iteration提高,那么被白色部分被腐蚀的程度会加深。
:图像被腐蚀后能有效去除噪声,但图像本身会被压缩

  • 膨胀:有腐蚀,就有与之相对应的膨胀操作,符号是 ⊕ \oplus ,它是腐蚀的逆操作,可以用来扩大图像中的物体。膨胀操作的基本思想是将结构元素沿着图像的边缘向外扩张,从而将物体的边界向外扩大。在膨胀操作中,结构元素的形状和大小会影响膨胀的效果。表达如式2所示:
    A ⊕ B = { z ∣ ( B ) z ⊆ A } (2) A\oplus B=\{z|(B)_z\subseteq A\}\tag2 AB={z(B)zA}(2)
    代码:

    import cv2
    import numpy as np
    # 读取图像
    img = cv2.imread('aTempImage/9/1.2.jpg', cv2.IMREAD_GRAYSCALE)
    img = cv2.resize(img,(500,500))
    # 定义结构元素
    kernel = np.ones((5,5), np.uint8)
    # 膨胀操作,此时对白色线条进行膨胀
    dilation = cv2.dilate(img, kernel, iterations=1)
    # 显示结果
    result = cv2.hconcat([img,dilation])
    cv2.imshow('result',result)
    cv2.imwrite('aTempImage/9/2.2.jpg',result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

​ 效果:在这里插入图片描述

​ 分析:与腐蚀类似,但效果相反,设置一个5x5的矩形结构,使用cv2.dilate()函 数实现膨胀,因为图片较大,所以设置原图大小为500x500。在膨胀之后,图像的白色部分变宽或扩散,如果这个矩形结构被放大或迭代次数提高,则白色扩散的内容会更多。

小结:腐蚀会缩小图像的组成部分(程度取决于核的形状与大小以及迭代次数),膨胀则是扩大

  • 开操作:能够”平滑“物体的轮廓,具体表现为:先腐蚀,再膨胀;可以用于去除图像中的小物体(尽可能地保存主体),平滑图像边缘、消除噪声。表达如式3:
    A ∘ B = ( A ⊖ B ) ⊕ B (3) A\circ B=(A\ominus B)\oplus B\tag3 AB=ABB(3)

    闭操作:与开操作相反,闭操作是 先膨胀,再腐蚀;能够填充图像中的小孔、消除噪声。表达如式4:
    A ∙ B = ( A ⊕ B ) ⊖ B (4) A\bullet B=(A\oplus B)\ominus B\tag4 AB=ABB(4)

​ 代码:

import cv2
import numpy as np

# 读取图像
img = cv2.imread('aTempImage/9/1.3.jpg', 0)
img = cv2.resize(img, (500, 500))
# 定义结构元素
kernel = np.ones((5, 5), np.uint8)
# 进行开操作
# opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)
opening1 = cv2.dilate(img, kernel, iterations=2)
opening2 = cv2.erode(opening1, kernel, iterations=2)
result = cv2.hconcat([img, opening1,opening2])
cv2.imshow('result', result)
cv2.imwrite('aTempImage/9/2.3.jpg',result)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果:2.3

分析:原图为图1,这是一个加粗的字符Z的图案,我手动给它添加了一些多余的条纹,现在希望能够使用闭操作来消除这些条纹,且尽可能不影响主体内容。具体操作是:先把图像转换为单通道的灰度图像,调整为合适的大小;先用dilate()函数对白色进行膨胀变成图2,此时对白色部分的膨胀度过高,导致原图像压缩得很严重,这时候再用erosion()函数对图2的白色进行腐蚀,形成图3,此时基本达到预期效果,以上的膨胀、腐蚀迭代次数均为2。

小结:腐蚀能够消除图像的噪声,比如“平滑”物体的边界;膨胀则是填充图像中缺少的细小部分(填充效果取决于卷积核以及图像本身),结合两者实现的开、闭操作可以组合出很多的图像处理方案。https://blog.csdn.net/Fishmemory/article/details/53113746关于这几个操作,这篇博客讲得很形象。

  • 对偶性:腐蚀与膨胀从集合的角度来看,存在对偶关系,关系形如式5,6:
    ( A ⊖ B ) c = A c ⊕ B ^ (5) {(A\ominus B)}^c=A^c\oplus \hat{B}\tag5 (AB)c=AcB^(5)
    式5指出,B对A的腐蚀是 B ^ \hat{B} B^ A c A^c Ac的膨胀的补集,同理,式6指出,B对A的膨胀是$ \hat{B} 对 对 A^c$的腐蚀的补集,上标c是补集的意思
    ( A ⊕ B ) c = A c ⊖ B ^ (6) {(A\oplus B)}^c=A^c\ominus \hat{B}\tag6 (AB)c=AcB^(6)

    类似的,开操作可以看作是一个闭操作的对偶操作,而闭操作可以看作是一个开操作的对偶操作,二者的关系形如式7,8:
    ( A ∙ B ) c = ( A c ∘ B ^ ) (7) (A\bullet B)^c = (A^c \circ \hat{B})\tag7 (AB)c=(AcB^)(7)

    ( A ∘ B ) c = ( A c ∙ B ^ ) (8) (A\circ B)^c = (A^c\bullet \hat{B})\tag8 (AB)c=(AcB^)(8)

  • 击中或击不中变换:是两种基本形态学操作,也是开闭操作的延伸。
    通俗理解就是:用一个小的结构元素(击中结构)去腐蚀原图,击中的元素保留;再用一个很大的结构元素(击不中结构)腐蚀原始图像,击不中原图的位置保留。满足击中元素能击中击不中元素不能击中的位置的元素 就是最终的形状结果,表达如式9
    A ⊛ B = ( A ⊖ E ) ⋂ ( A c ⊖ F ) (9) A \circledast B=(A\ominus E)⋂(A^c\ominus F)\tag9 AB=(AE)(AcF)(9)

3.基本的形态学算法

  • 边界提取:用来提取二值图像中物体的边界或者灰度图像中的轮廓,边界提取的基本思路是通过对原图像进行腐蚀操作,得到一幅新的图像,然后对原图和新图进行差分运算,得到物体的边界或者轮廓,表达如式10所示
    β ( A ) = A − ( A ⊖ B ) (10) β(A)=A-(A\ominus B)\tag{10} β(A)=A(AB)(10)
    其中,A与B是两个结构元,β(A)是A减去B对A做一次腐蚀操作的结果

    import cv2
    import numpy as np
    # 读取原始图像
    img = cv2.imread('aTempImage/9/1.4.png', cv2.IMREAD_GRAYSCALE)
    # 定义结构元素
    # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    kernel = np.ones((5,5),np.uint8)
    # 进行腐蚀操作
    eroded = cv2.erode(img, kernel)
    # 计算边界
    boundary = img - eroded
    # 显示结果
    result = cv2.hconcat([img,boundary])
    cv2.imshow('result', result)
    cv2.imwrite('aTempImage/9/2.4.png',result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    效果:2.4

    分析:读取原图的灰度图像A,设置一个3x3的卷积核去腐蚀这张图得到B,原图像被腐蚀后,高亮区域会缩小很多,此时,A再减去B即可获得A的轮廓。腐蚀程度与卷积核大小呈正比,腐蚀程度越高,则提取到的边界也越明显(粗)

  • 孔洞填充:基本思路是通过对原图像进行膨胀操作,将孔洞内部的像素逐渐向外扩张,直到与边缘相连为止。具体来说,可以使用一个大的结构元素对原图像进行膨胀操作,然后将膨胀后的结果与原图像进行按位或运算,得到填充后的图像。表达如式11所示:
    X k = ( X k − 1 ⊕ B ) ∩ A c , k = 1.2.3 , … (11) X_k = (X_{k-1}\oplus B)\cap A^c,k=1.2.3,…\tag{11} Xk=(Xk1B)Ac,k=1.2.3,(11)

  • 连通分量的提取:一张图中可能有多个目标,要提取这些目标首先要识别出他们,为他们设置编号。表达如式12所示
    X k = ( X k − 1 ⊕ B ) ∩ A , k = 1.2.3 , … (12) X_k = (X_{k-1}\oplus B)\cap A,k=1.2.3,…\tag{12} Xk=(Xk1B)A,k=1.2.3,(12)

  • 凸壳:若集合A内连接任意两个点的直线段都在A的内部,则称A是凸的。任意集合S的凸壳H是包含于S的最小凸集,差集H-S称为S的凸缺。计算出某集合凸壳的方法如式13
    X k i = ( X k − 1 ⊛ B i ) ∪ A , i 、 k = 1 , 2 , 3 … (13) X_k^i = (X_{k-1}\circledast B^i)\cup A,i、k=1,2,3…\tag{13} Xki=(Xk1Bi)A,ik=1,2,3(13)
    其中, X 0 i X_0^i X0i是集合A

  • 细化:将二值图像中的线条、边缘逐渐消减,直到它们变得足够细为止,目的是提取出二值图像中的骨架信息,细化算法通常基于迭代的思想,每一次迭代都会对二值图像进行一次操作,细化更进一步

    import cv2
    from PIL import Image, ImageFilter
    # 读取图像
    img = Image.open("aTempImage/9/1.4.png").convert('L')
    # 应用细化算法
    kernel = ImageFilter.Kernel((3,3), (-1,-1,-1, 2,2,2, -1,-1,-1))
    skeleton = img.filter(ImageFilter.CONTOUR)
    # 显示结果
    skeleton.save('aTempImage/9/2.5.png')
    

    效果:
    2.5

    分析:对于图像中的每一个像素,根据其周围像素的值来判断它是否可以被消减。如果可以被消减,则将其置为0。这个过程会一直重复,直到图像不能再进行细化为止。细化算法的实现需要考虑到算法的效率和细化结果的正确性,同时还需要注意避免细化过度导致图像信息的丢失。

  • 粗化:表达如式14所示
    A ⊙ B = A ∪ ( A ⊛ B ) (14) A\odot B = A\cup(A\circledast B)\tag{14} AB=A(AB)(14)
    粗化与细化相反,二者属于对偶关系。假设需要对集合A做粗化操作,可以先求出A的补集 A c A^c Ac,再对这个补集做细化,最后做一次求补

  • 骨架:可以看作是物体的中心线或轴线,是物体的重要特征。骨架提取的基本思想是将物体的边界向内收缩,直到物体被压缩成一条线或点。这条线或点就是物体的骨架。骨架提取算法通常需要进行多次迭代,每次迭代都将物体的边界向内收缩一个像素。在每次迭代中,需要对物体的边界进行细化和粗化操作,以便得到更准确的骨架

  • 裁剪:指从一张图像中截取出一个子区域的过程。裁剪通常用于去除图像中不需要的部分,或者将图像分割成多个子区域进行处理,可以用于消除毛刺

  • 形态学重建:基本思想是将一个结构元素在图像中进行膨胀或腐蚀操作,然后通过一系列的迭代来实现形状或区域的重建

    import cv2
    import numpy as np
    
    # 读取图像
    img = cv2.imread("aTempImage/9/1.6.png", cv2.IMREAD_GRAYSCALE)
    
    # 将图像转换为二值图像
    thresh, img_bin = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    
    # 定义竖线结构元素
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, img.shape[0]))
    
    # 进行腐蚀操作,将字符变成竖线
    img_eroded = cv2.erode(img_bin, kernel)
    result = cv2.hconcat([img,img_eroded])
    # 保存结果图像
    cv2.imwrite('aTempImage/9/2.7.png', result)
    

    效果:
    2.7

4.灰度级形态学

  • 基础知识:在灰度级形态学中,结构元素是一个灰度图像,而不是二值图像,所以腐蚀和膨胀操作都是基于灰度值的比较,而不是像素值的比较。开运算和闭运算操作可以用于去除噪声和连接断裂的边缘

  • 补充:灰度图像是一种每个像素点的灰度强度值都介于0到255之间的图像,其中0表示黑色,255表示白色。灰度图像中的每个像素点都可以用一个8位无符号整数来表示,即每个像素点都有256种不同的灰度强度值。而二值图像是一种每个像素点只有两种可能取值的图像,即黑色和白色

  • 注:以下操作的处理对象均为灰度级图像

  • 腐蚀和膨胀:若有平坦结构元b,其原点为(x,y),那么该结构在(x,y)对图像f的腐蚀便定义为:f与b的重合区域的最小值,如式15所示
    [ f ⊖ b ] ( x , y ) = m i n { f ( x + s , y + t ) } , ( s , t ) ∈ b (15) [f\ominus b](x,y) = min\{f(x+s,y+t)\},(s,t)\in b\tag{15} [fb](x,y)=min{f(x+s,y+t)},(s,t)b(15)
    同理,膨胀则定义为图f与 b b b反射重合区域的最大值,如式16所示
    [ f ⊕ b ] ( x , y ) = m a x { f ( x − s , y − t ) } , ( s , t ) ∈ b (16) [f\oplus b](x,y) = max\{f(x-s,y-t)\},(s,t)\in b\tag{16} [fb](x,y)=max{f(xs,yt)},(s,t)b(16)

  • 开操作和闭操作:前者先腐蚀后膨胀,抑制比结构元小的亮度细节,导致结果的亮度降低(对暗细节无影响);后者顺序相反,抑制暗度细节,处理的结果亮度会提高(对亮细节无影响)

  • 形态学平滑:结合开\闭操作,实现平滑图像和减噪

  • 形态学梯度:由结构b对图像f膨胀的结果 减去 结构b对图像腐蚀的结果 得到形态学梯度,如式17所示
    g = ( f ⊕ b ) − ( f ⊖ b ) 17 (1) g = (f\oplus b)-(f\ominus b)\tag1{17} g=(fb)(fb)17(1)
    腐蚀则细化图像,膨胀则粗化,二者之差能强调图像的边界。图像中的同质区域不受影响,因此相减操作趋于消除同质区域,最终结果就是物体的边缘变得更加明显。在数学中,梯度是一个向量,它表示函数在某一点处的变化率和变化方向;用在图像处理上,因为腐蚀、膨胀分别是对物体做收敛和扩散,所以形态学梯度可以看作是图像中像素值的变化率和变化方向。

  • 顶帽变换和底帽变换:图像减去图像开操作的结果 是顶帽变换,图像闭操作的结果减去图像 便是底帽变换

  • 粒度测定:充斥大量颗粒状物体的图像中,正确统计这些物体数量的难度较大。解决办法为:使用逐渐变大的结构元对图像做开操作;对于比背景亮的颗粒,基本方法是使用逐渐增大的结构元对图像执行开运算。对于每一个开运算,计算该开运算中像素值的和,因为开运算会降低亮特征的灰度,故像素值会随着结构元的增大而减小

5.总结

本章的主题是形态学处理,主要了学习腐蚀、膨胀操作,在二者的基础上延伸出开操作,闭操作等。为使效果更加明显,实验中的处理对象均是灰度图像

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值