9.1 Python图像处理之图像数学形态学-二值形态学(腐蚀、膨胀、开启、闭合)

9.1 Python图像处理之图像数学形态学-二值形态学(腐蚀、膨胀、开启、闭合)

1 算法原理

前提知识点:

结构元(SE,Structure Element)最直接的理解就是卷积操作中的卷积核,或者是空间域滤波中提到的滤波器。虽然形态学操作中结构元的形状可以是任意的,但是由于在图像操作中,为了方便计算,通常要求结构元是矩形的阵列,对于任意形状的结构元,如果不满足矩形的要求,则用0将其填充为矩形即可。

另外,结构元内部的有效元素不像滤波器那样有权值,通常结构元中只分为两种元素,就是0和1,不会出现其他数值的系数。(当然对有些算法来说也有例外)。结构元对图像进行的操作也和卷积非常类似,就是由结构元的中心依次滑过图像,然后进行设计好的操作即可。接下来就开始介绍图像处理中常见的形态学操作。

1.1 腐蚀(erode)

公式:

image-20210808163614867

其中,A c是图像A的补集,即1-A。上式表达的意思就是,在z的移动下,如果结构元B能够完全包含在图像A中(完全包含意味着结构元B中的有效元素对应于图像A中的位置全都是前景像素。z的移动就是针对于图像A的所有像素范围的移动。

image-20210808163627620

上图中,左边实线围住的9x9方格就是结构元B,红色代表其有效区域,白色代表其无效区域(0填充)。右侧实现代表图像A,浅蓝色部分代表A的前景像素,白色代表背景像素。

当结构元滑动到1区域时,所有有效区域对应的像素都是前景像素(紫色区域,红+蓝),因此称此时B ⊆ A,此时,1号位置在结果图像中应该置1。反之,如果只有部分区域重合,如结构元处于2号位置,那么说明此时的2号点不满足腐蚀条件,应该在结果图像中置0。

1.2 膨胀(dilate)

image-20210808163802939

其中,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TaQ0B0gG-1629076834164)(file:///C:\Users\mgboy\AppData\Local\Temp\ksohtml11668\wps4.jpg)]称为结构元B的反射,指的是,结构元B绕结构元的中心(通常设置在SE矩阵中心)旋转180°后的新结构元。对于对称的结构元,就有B = [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-58lrFRrv-1629076834166)(file:///C:\Users\mgboy\AppData\Local\Temp\ksohtml11668\wps5.jpg)] 。

膨胀的集合含义就是,SE和图像的前景像素至少有一个交点,那么当前移动到的像素就置1,否则置0。在膨胀的条件下,之前图示中的1,2号区域均会被置1。(腐蚀时,2号区域是被置0的)。

1.3 开启(opening)

image-20210808163910178

开操作就是先用SE腐蚀图像A,再对腐蚀后的结果进行膨胀

第一反应或许会觉得,这操作不是很多余吗?其实细想后发现,其中自有妙处。假设图像中存在很多细小琐碎的颗粒或噪声,那么经过第一步腐蚀后,这些细小的噪声就会被腐蚀而消失,尽管紧接着进行了膨胀操作,但是由于细小颗粒已经完全消失,因此即使膨胀也无法恢复。相反,那些图像中的主体,经过腐蚀后仍然存在,再经过膨胀就可以恢复原样。

1.4 闭合(closing)

image-20210808163942220

闭操作和开操作正好相反,是先膨胀腐蚀

如果图像中存在细小的孔洞或者缝隙,通过膨胀后就可以填充细小孔洞和缝隙,使其和主体连接起来,而再腐蚀的时候,只会腐蚀图像主体,而不会再恢复缝隙等瑕疵。因此,闭操作很适合拿来修补图像瑕疵的

2 代码

运行代码说明

1.要改变代码中的图片地址(地址不能有中文)

更改put(path)函数中的路径put(r'../image/image1.jpg')

2.注意最后的plt.savefig('1.new.jpg')是保存plt图像,如果不使用可以注释掉

代码依赖包:

matplotlib  3.4.2
numpy  1.20.3
opencv-python  4.1.2.30
# pip安装
pip install matplotlib numpy opencv-python
import numpy as np
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def put(path):
    # 读取图片
    img = cv2.imread(path)
    # 由于cv2.imread 读取图像格式为b,g,r但是 plt显示按照 rgb次序!因此要转换一下。
    b, g, r = cv2.split(img)
    img2 = cv2.merge([r, g, b])
    rows, cols = img.shape[:2]

    src = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 通过单阈值获得二值图像
    ret, src = cv2.threshold(src, 102, 255, cv2.THRESH_BINARY)
    # 反过来,大于阈值是0,小于阈值是255
    # ret, src = cv2.threshold(src, 102, 255, cv2.THRESH_BINARY_INV)
    
    # 设置卷积核
    kernel = np.ones((10, 10), np.uint8)  # 0是黑色,255是白色
    # 图像腐蚀处理
    res1 = cv2.erode(src, kernel)  # 注意膨胀和腐蚀都是对白色255来说的,
    # 图像膨胀处理
    res2 = cv2.dilate(src, kernel)
    # 图像开运算
    res3 = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel)
    # 图像闭运算
    res4 = cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel)
    # 图像显示
    plt.subplot(231), plt.imshow(img2, plt.cm.gray), plt.title('原始图像'), plt.axis('off')
    plt.subplot(232), plt.imshow(src, plt.cm.gray), plt.title('二值图像'), plt.axis('off')
    plt.subplot(233), plt.imshow(res1, plt.cm.gray), plt.title('腐蚀'), plt.axis('off')
    plt.subplot(234), plt.imshow(res2, plt.cm.gray), plt.title('膨胀'), plt.axis('off')
    plt.subplot(235), plt.imshow(res3, plt.cm.gray), plt.title('开运算'), plt.axis('off')
    plt.subplot(236), plt.imshow(res4, plt.cm.gray), plt.title('闭运算'), plt.axis('off')

    # plt.savefig('1.new-img.jpg')
    plt.show()

# 图像处理函数,要传入路径
put(r'../image/img5.jpg')

注意膨胀和腐蚀都是对白色255来说的,。如果获得的二值图像中的图案是黑色的,要用第二条转换函数。这样得到的图案比较美观。

3 效果

image-20210808164907791

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值