前言

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

5. 结果展示

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

参考资料

  1. 数字图像处理基础.朱虹
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐