如何填充二值图像中包括边界区域在内的所有孔洞?
解决二值图像全孔洞填充(含边界处孔洞)问题
你的现有代码仅能填充完全被前景包围的内部孔洞,无法处理与图像边界连通的孔洞——原因是cv2.RETR_CCOMP会区分轮廓层次,但边界处的孔洞属于背景连通区域,不会被标记为内层轮廓。以下是两种可靠的解决方法:
方法一:基于最外层轮廓填充(推荐)
通过提取前景的最外层轮廓,直接填充轮廓内部区域,可将所有前景区域(包括边界处的缺口/孔洞)转为实心:
import cv2 import numpy as np # 假设ddwi是输入的二值图像(前景为255白色,背景为0黑色) binary_img = ddwi.astype(np.uint8) # 提取前景的最外层轮廓 contours, _ = cv2.findContours(binary_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 创建与原图像尺寸一致的全黑掩码 filled_img = np.zeros_like(binary_img) # 填充每个最外层轮廓的内部为白色 for cnt in contours: cv2.drawContours(filled_img, [cnt], 0, 255, -1) # filled_img即为所有孔洞(含边界处)被填充后的结果
原理说明
cv2.RETR_EXTERNAL仅获取前景的最外层边界轮廓,忽略内部孔洞的层级。填充该轮廓内部时,会直接将轮廓包围的所有区域(包括原本与边界连通的孔洞)转为前景色,实现实心填充。
方法二:形态学闭运算(适用于规则孔洞)
如果孔洞形状规则、尺寸可控,可使用形态学闭运算(先膨胀后腐蚀)填充孔洞:
import cv2 import numpy as np binary_img = ddwi.astype(np.uint8) # 定义结构元素,尺寸需大于最大孔洞的直径 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) # 执行闭运算 filled_img = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel)
注意事项
- 结构元素的尺寸需根据孔洞实际大小调整,过大可能导致前景变形;
- 该方法对不规则形状的边界孔洞处理效果不如轮廓填充稳定。
内容的提问来源于stack exchange,提问作者fournifl
相关产品推荐
相关产品推荐

