9.2.3 Python图像处理之图像数学形态学-二值形态学应用-区域填充
1 算法原理
区域和其边界可以互求。
区域填充就是已知区域按边界提取可求得其边界,反过来已知边界通过填充也可得到区域。
区域填充的一个例子,已知一个区域边界点的集合A,它的补集Ac.可通过用结构元素对它膨胀,求补,和求交来填充区域。首先给边界内一个点赋深色像素值。然后根据下列选代公式填充。实验中因为Ac 比较难求,用原始图的补集代替。
当Xk==Xk-1时停止选代。这种膨胀过程可称为条件膨胀过程。
2 代码
运行代码说明
1.要改变代码中的图片地址(地址不能有中文)
更改第8行代码的图片地址:
cv2.imread("image1.jpg", 0)
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 cv2
import numpy as np
import matplotlib.pyplot as plt
import copy
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
image = cv2.imread("image1.jpg", 0)
retval, image = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY_INV)
image_C = cv2.bitwise_not(image)
# 构造一个3×3的结构元素
element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dilate = cv2.dilate(image, element) #
erode = cv2.erode(image, element) # 腐蚀
# kernel形态运算的内核,一般由getStructuringElement函数生成,有三种形状
# MORPH_RECT 矩形
# MORPH_CROSS 交叉形
# MORPH_ELLIPSE 椭圆形
# 将两幅图像相减获得边,第一个参数是膨胀后的图像,第二个参数是腐蚀后的图像
margin = cv2.absdiff(dilate, erode)
### 区域填充
"""
条件,原图像image
原图像补集 image_C
边缘图像 margin
"""
r, c = margin.shape[:2]
Mark_1 = np.zeros((r,c), np.uint8) # 创建一个和图像一样的全零的图像矩阵
kernel = np.ones((7, 7), np.uint8)
epoch_img_1 = np.zeros((r,c), np.uint8)
epoch_img_2 = np.zeros((r,c), np.uint8)
Mark_1[200][250] = 255 # 种子点
stop = 0
while True:
stop = stop+1
print(stop)
if stop == 50:
epoch_img_1 = copy.deepcopy(Mark_1)
if stop == 100:
epoch_img_2 = copy.deepcopy(Mark_1)
if stop == 200:
# break
pass
Mark_tmep = copy.deepcopy(Mark_1)
Mark_1 = cv2.dilate(Mark_1, kernel) #图像膨胀处理
Mark_1 = cv2.bitwise_and(Mark_1, image) # 图像交集
flag = 0
for i in range(r):
for j in range(c):
if Mark_1[i][j] == Mark_tmep[i][j]:
flag = 0
else:
flag = 1
break
if flag == 1:
break
if flag == 0:
break
plt.subplot(231), plt.imshow(image, plt.cm.gray), plt.title('原始二值图像'), plt.axis('off')
plt.subplot(232), plt.imshow(image_C, plt.cm.gray), plt.title('原始补集')
plt.subplot(233), plt.imshow(margin, plt.cm.gray), plt.title('二值边缘图像'), plt.axis('off')
plt.subplot(234), plt.imshow(epoch_img_1, plt.cm.gray), plt.title('50轮填充'), plt.axis('off')
plt.subplot(235), plt.imshow(epoch_img_2, plt.cm.gray), plt.title('100轮填充'), plt.axis('off')
plt.subplot(236), plt.imshow(Mark_1, plt.cm.gray), plt.title('填充图像'), plt.axis('off')
# plt.savefig('2.3new-img.jpg")
plt.show()
对简单图片效果比较好。复杂图片不怎么样。