OpenCV中反转背景色并保留前景目标的实现方法
两类白色像素的区分与目标提取方案
两类白色像素的本质差异非常清晰:和图像四周边界存在连通路径的白色属于背景区域,被黑色连通块完全包围、与图像边界无连通路径的白色属于黑色块内部的目标形状,无需深度学习模型,用基础的图像处理操作即可实现精准区分,具体流程如下:
- 预处理:读取输入二值图像,统一像素值规则:白色像素值为255,黑色像素值为0,若原图像素规则相反,先做一次全局反色对齐标准。
- 背景标记:以图像四条边上的所有白色像素作为种子点,执行漫水填充算法,遍历所有与种子点连通的白色像素,将这部分像素统一标记为背景。
- 结果生成:创建一张与输入图尺寸完全一致的全黑画布,将所有未被标记为背景的原白色像素(即黑色块内部的形状)保留为白色绘制到画布上,即可得到纯黑背景下仅保留内部目标的输出图。
样例效果
- 输入图像:

- 输出图像:

参考实现代码(Python + OpenCV)
import cv2 import numpy as np # 以灰度模式读取输入二值图 img = cv2.imread("input.png", cv2.IMREAD_GRAYSCALE) h, w = img.shape # 初始化漫水填充所需掩码,尺寸要求比原图宽高各多2个像素 fill_mask = np.zeros((h + 2, w + 2), dtype=np.uint8) # 遍历图像四条边界,从所有边界上的白色像素开始漫水填充标记背景 for col in range(w): if img[0, col] == 255: cv2.floodFill(img, fill_mask, (col, 0), 128) if img[h-1, col] == 255: cv2.floodFill(img, fill_mask, (col, h-1), 128) for row in range(h): if img[row, 0] == 255: cv2.floodFill(img, fill_mask, (0, row), 128) if img[row, w-1] == 255: cv2.floodFill(img, fill_mask, (w-1, row), 128) # 生成结果:仅保留未被标记为背景的原白色像素,其余区域全部置黑 output = np.where(img == 255, 255, 0).astype(np.uint8) cv2.imwrite("output.png", output)
特殊情况处理:如果黑色连通块存在和图像边缘相接的缺口,会导致漫水填充误把内部白色标记为背景,这种情况可以先给原图添加1-2个像素宽度的全黑外边框,再执行上述流程即可。
内容的提问来源于stack exchange,提问作者jeffreyL02
相关产品推荐
相关产品推荐

