如何用Python自动填充二值图像中两个轮廓间的像素?
自动化填充二值图像两条轮廓间区域的解决方案
核心思路
利用OpenCV的轮廓检测功能自动识别图像中的内外轮廓,通过创建掩码填充轮廓间的环形区域,无需手动指定种子点,可直接批量处理大量图像。
步骤与代码实现
1. 导入依赖库
import cv2 import numpy as np
2. 读取并预处理图像
读取图像并转为灰度模式,确保图像为标准二值格式(0代表黑色,255代表白色):
# 读取灰度图像 img = cv2.imread('input_image.png', 0) # 二值化处理(确保图像只有黑/白两色) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 若图像是黑轮廓白背景,需反转(根据实际情况调整) # thresh = cv2.bitwise_not(thresh)
3. 检测并筛选轮廓
使用层级轮廓检测区分内外轮廓,同时过滤噪声小轮廓:
# 检测轮廓,RETR_CCOMP模式可获取轮廓层级关系 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) # 过滤面积过小的噪声轮廓(阈值根据实际图像调整) min_area = 100 filtered_contours = [c for c in contours if cv2.contourArea(c) > min_area] # 按轮廓面积从大到小排序,最大的为外轮廓,次大的为内轮廓 sorted_contours = sorted(filtered_contours, key=cv2.contourArea, reverse=True) outer_contour = sorted_contours[0] inner_contour = sorted_contours[1]
4. 创建掩码填充中间区域
生成掩码,先填充外轮廓内部为白色,再将内轮廓内部重置为黑色,得到仅轮廓间区域为白色的掩码:
mask = np.zeros_like(img) # 填充外轮廓内部 cv2.drawContours(mask, [outer_contour], 0, 255, cv2.FILLED) # 清除内轮廓内部的白色,保留环形区域 cv2.drawContours(mask, [inner_contour], 0, 0, cv2.FILLED)
5. 合并掩码与原图,得到最终结果
将掩码与原图进行按位或操作,保留原有轮廓并填充中间区域:
result = cv2.bitwise_or(img, mask) # 保存结果 cv2.imwrite('output_image.png', result)
批量处理方案
将上述代码封装为函数,遍历文件夹中的所有图像即可实现批量处理:
import os def fill_contour_gap(input_path, output_path, min_area=100): img = cv2.imread(input_path, 0) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) filtered_contours = [c for c in contours if cv2.contourArea(c) > min_area] sorted_contours = sorted(filtered_contours, key=cv2.contourArea, reverse=True) if len(sorted_contours) >= 2: outer_contour = sorted_contours[0] inner_contour = sorted_contours[1] mask = np.zeros_like(img) cv2.drawContours(mask, [outer_contour], 0, 255, cv2.FILLED) cv2.drawContours(mask, [inner_contour], 0, 0, cv2.FILLED) result = cv2.bitwise_or(img, mask) cv2.imwrite(output_path, result) else: print(f"图像 {input_path} 未检测到足够的轮廓,跳过处理") # 批量处理示例 input_dir = 'your_input_folder' output_dir = 'your_output_folder' os.makedirs(output_dir, exist_ok=True) for filename in os.listdir(input_dir): if filename.lower().endswith(('.png', '.jpg', '.jpeg')): input_path = os.path.join(input_dir, filename) output_path = os.path.join(output_dir, filename) fill_contour_gap(input_path, output_path)
内容的提问来源于stack exchange,提问作者Mohit Lamba
相关产品推荐
相关产品推荐

