• 数字图像处理(十)腐蚀和膨胀



    前言

      二值图像中一类主要处理是对提取的目标图形进行形态分析。形态学处理中最基本的是腐蚀和膨胀。
      腐蚀和膨胀是两个互为对偶的运算。腐蚀的作用是将目标图像收缩,而膨胀是将图像扩大。
      结构元素是指具有某种确定形状的基本结构元素,例如,一定大小的矩形、圆形等。结构元素具有原点。如下图所示:
    在这里插入图片描述
    这就是一个矩形的结构元素(四个 1 构成矩形),标有颜色的位置就是结构元素的原点。

    这是一个三角形的结构元素(三个 1 构成三角形),标有颜色的位置就是结构元素的原点。


    一、腐蚀

    1.概念

      腐蚀是一种消除边界点,使边界向内部收缩的过程。可以用来消除小且无意义的目标物。如果两目标物间有细小的连通,可以选取足够大的结构元素,将细小连通腐蚀掉。

    2.算法的具体步骤

    1. 构建结构元素
    2. 扫描原图,找到第一个像素值为1(因为是二值图,非0即1)的点。
    3. 将预先设定好形状以及原点位置的结构元素的原点移动到该点
    4. 判断该结构元素覆盖范围内的图像的像素值是否全部为1,如果是,则腐蚀后图像相同位置上的像素值为1,如果至少有一个像素的值为0,则腐蚀后图像的相同位置上的像素值为0
    5. 对原图中所有像素值为1的点重复进行步骤3和步骤4

    3.举例

    设原图像 f f f如下图所示:
    在这里插入图片描述
    结构元素选择三角形的结构元素,结构元素原点在左上角,如下图所示:
    在这里插入图片描述
    按照算法步骤,将结构元素的原点移动到第一个像素值为1的点,如下图所示:
    在这里插入图片描述
    可以清楚的看到,结构元素覆盖范围内的像素值全为1。所以腐蚀后的图像在第一行第二列的像素值 g ( 1 , 2 ) = 1 g(1,2)=1 g(1,2)=1
    接下来我们寻找下一个像素值为1的点,发现在该点是边缘点。此时的结构元素的原点移动到该点,会出现边界溢出的现象,所有我们对此像素不做处理(也就是说要确保结构元素的覆盖范围在原图内)。
    下一个像素值为1的像素点位于第二行,第二列,将结构元素的原点移动到该点。如下图所示:
    在这里插入图片描述
    可以看到,结构元素覆盖范围内的像素值有两个1,一个0。所以腐蚀后的图像在第二行、第二列的像素值 g ( 2 , 2 ) = 0 g(2,2)=0 g(2,2)=0
    以此类推,对所有像素值为1的像素点重复上述操作。便可得到腐蚀后的图像 g g g,如下图所示:
    在这里插入图片描述

    4.python代码


    二、膨胀

    1.概念

      膨胀是将目标区域接触的背景点合并到该目标物中,使目标边界向外扩张的处理。膨胀可以用来填补目标区域存在的某些空洞,也可以用来消除包含在目标区域中的小颗粒噪声。膨胀处理是腐蚀处理的对偶。

    2.算法步骤

    1. 将预先设定好形状以及原点位置的结构元素移动到图像中可包容(可包容的意思是说:结构元素的覆盖范围必须完全落在图像内)的所有像素点
    2. 判断该结构元素覆盖范围内的像素值是否存在至少一个为1的点,如果存在,则膨胀后图像中与结构元素原点相同位置的像素值为1,如果该覆盖范围内所有的像素值为0,则膨胀后图像相同位置上的像素值为0
    3. 对原图中的所有像素重复进行步骤2

    3.举例

    设原图像 f f f如下图所示:
    在这里插入图片描述
    三角形的结构元素如下图所示,带有颜色的位置为结构元素的原点:
    在这里插入图片描述
    第一步:将结构元素的原点移动到图像中的第一个像素点,如下图所示:
    在这里插入图片描述
    结构元素覆盖的范围内有两个0,一个1,所以膨胀后的图像在第一行,第一列位置处的像素值 g ( 1 , 1 ) = 1 g(1,1)=1 g(1,1)=1
    依次遍历原图中的每个像素点(结构元素无法全部落在原图内的像素点除外)。
    当遍历到 f ( 3 , 1 ) f(3,1) f(3,1)点时,如下图所示:
    在这里插入图片描述
    此时结构元素覆盖范围内有三个0,0个1,所以膨胀后的图像在第三行、第三列位置处的像素值 g ( 3 , 1 ) = 0 g(3,1)=0 g(3,1)=0

    膨胀后的图像 g g g如下图所示:
    在这里插入图片描述

    4.C++代码

    # 膨胀算法
    import cv2
    import numpy as np
    
    # 读取二值图像
    input_image = cv2.imread('test1.png', cv2.IMREAD_GRAYSCALE)
    
    height = input_image.shape[0]
    width = input_image.shape[1]
    
    # 定义结构元素,左上角为结构元素原点
    s = np.array([[1, 0], [1, 1]], dtype=np.bool8)
    m, n = s.shape[0], s.shape[1]
    
    output_image = input_image.copy()
    
    # 进行膨胀操作
    for row in range(height-m+1):  # 对边界不做处理
        for col in range(width-n+1):
            result = input_image[row:row+m, col:col+n] & s
            if result.sum() >= 1:
                output_image[row, col] = 255
            else:
                output_image[row, col] = 0 
    
    cv2.imshow('input-image', input_image)
    cv2.imshow('output-image', output_image)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    5. 结果展示

    在这里插入图片描述
    可以看到,右图(膨胀后的图像)相较于左边的原图,轮廓变粗。

    参考资料

    1. 数字图像处理基础.朱虹
  • 相关阅读:
    Scala---数据基础
    【git】新电脑(Windows)中Git配置SSH公钥
    Mac 使用paralles 从零搭建hadoop集群
    组件分享之后端组件——基于Golang实现的database/sql附加功能组件dbr
    java基于SpringBoot+Vue的大学生体质健康测试管理系统 element
    C#语法知识之变量
    Android的刷机模式
    图像分类竞赛涨分小技巧——以智能硬件语音控制的时频图分类挑战赛为例
    阿里云轻量应用服务器月流量限制说明(部分套餐不限流量)
    Simulink和GUI联合使用
  • 原文地址:https://blog.csdn.net/qq_41596730/article/details/127950992