其实就是定义一个连通规则(structure),用该连通区域在图像上stride, 用连通区域内的最小或者最大值代替原来的值。(边界上只覆盖部分值)。
腐蚀和膨胀的一个作用是提取二值图像的边界。腐蚀一般用来提取内边界,内边界由边界点构成,是区域的一部分。内边界的提取利用图像的腐蚀处理得到原图像的一个收缩,再将收缩结果与目标图像进行异或运算,实现差值部分的提取。
外边界指区域外部与边界点相邻的像素集合,属于背景的一部分。外边界提取先对图像进行膨胀处理,然后用膨胀结果与原目标图像进行异或运算,也就是求膨胀结果与原目标图像的差集。
1. 腐蚀(erosion)
构造如下的连通区域:
构造图像:
img = np.array([
[125, 190, 11, 190],
[141, 234, 21, 67],
[165, 234, 31, 189],
[112, 12, 41, 56]
], dtype='uint8')
kernel = np.array([
[0, 1, 0],
[1, 1, 1],
[0, 1, 0]
], dtype='uint8')
使用连通区域内的最小值代替:
cv2.erode(img, kernel)
# or
scipy.ndimage.binary_erosion(img, structure=struct)
输出结果
array([[125, 11, 11, 11],
[125, 21, 11, 21],
[112, 12, 21, 31],
[ 12, 12, 12, 41]], dtype=uint8)
求内边界:
inner_border=img ^ cv2.erode(img, kernel)
2. 膨胀
方法与腐蚀相同,使用最大值代替:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = np.array([
[125, 190, 11, 190],
[141, 234, 21, 67],
[165, 234, 31, 189],
[112, 12, 41, 56]
], dtype='uint8')
# kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
kernel = np.array([
[0, 1, 0],
[1, 1, 1],
[0, 1, 0]
], dtype='uint8')
dilate_res = cv2.dilate(img, kernel)
# or
scipy.ndimage.binary_dilation(img, structure=struct)
dialate_res
输出结果:
array([[190, 234, 190, 190],
[234, 234, 234, 190],
[234, 234, 234, 189],
[165, 234, 56, 189]], dtype=uint8)
求外边界:
outer_border = img ^ cv2.dilate(img, kernel)
总的来说腐蚀就是去掉毛刺(早点),而膨胀则是补全缺的部分。