什么是图像形态学?这里的图像形态学指的是数学上的图像形态学。

本节的腐蚀和膨胀处理的都是二值化之后的图像,所以也可以称之为二值腐蚀和二值膨胀,与灰度腐蚀和灰度膨胀对应。
腐蚀和膨胀都是针对白色部分而言的(在二值图像中白色为255)。

腐蚀(erosion)

腐蚀是求局部最小值的过程,图像处理后的效果为白色减少、黑色增多。

适用的场景:

  1. 消除小的噪声点
  2. 断开相邻的物体
  3. 使物体整体缩小

膨胀(dilation)

膨胀是求局部最大值的过程,图像处理后的效果为白色增多、黑色减少。

适用的场景:

  1. 填补物体中的空洞
  2. 连接相邻的物体
  3. 使物体整体扩大

结构元素(核)的影响

结构元素的形状和大小会显著影响形态学操作的结果:
目前 opencv 有四种可选的核:矩形,椭圆形,十字形,菱形。
这些核实际上就是不同内容的二维矩阵。

腐蚀和膨胀的测试代码

下面是一段测试程序,用于演示腐蚀和膨胀的效果、不同核的处理效果。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('../photos/2.bmp')
assert img is not None, 'image is invalid'
print('img size:', img.size, img.shape)
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

img = img[0:500, 300:600]
cv.imwrite('../photos/2_1.bmp', img)

_, binary = cv.threshold(img, 127, 255, cv.THRESH_BINARY)

k_size = (5, 5)
kernel = np.ones(k_size, np.uint8)
print('k_ones', kernel)

# erode result
erosion = cv.erode(binary, kernel)

# dialate result
dilation = cv.dilate(binary, kernel)

# 不同形状的核
rect_kernel = cv.getStructuringElement(cv.MORPH_RECT, k_size)  # 矩形
ellipse_kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, k_size)  # 椭圆形
cross_kernel = cv.getStructuringElement(cv.MORPH_CROSS, k_size)  # 十字形
diamond_kernel = cv.getStructuringElement(cv.MORPH_DIAMOND, k_size)  # 菱形

print('rect kernel', rect_kernel)
print('ellipse kernel', ellipse_kernel)
print('cross kernel', cross_kernel)
print('diamond kernel', diamond_kernel)

# 应用不同核的腐蚀
erosion_rect = cv.erode(binary, rect_kernel)
erosion_ellipse = cv.erode(binary, ellipse_kernel)
erosion_cross = cv.erode(binary, cross_kernel)
erosion_diamond = cv.erode(binary, diamond_kernel)

images = [img, binary, erosion, dilation,
	  erosion_rect, erosion_ellipse, erosion_cross, erosion_diamond]
titles = ['original', 'binary', 'erosion', 'dilation',
	  'erosion rect', 'erosion ellipse', 'erosion cross', 'erosion diamond']

for i in range(len(images)):
    plt.subplot(2, 4, i + 1)
    # plt.imshow(binary, 'gray', vmin=0, vmax=255)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])

plt.tight_layout()
plt.savefig('plot.png', bbox_inches='tight')

plt.show()

开运算(opening)

线腐蚀后膨胀,用于消除小物体和毛刺

闭运算(closing)

先膨胀后腐蚀,用于填充小孔和连接断裂

(全文完)