You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python和OpenCV实现通用形状填充及面积计算

通用形状内部空白填充方案

你的问题核心是固定尺寸的形态学闭运算无法适配不同大小的形状/空洞,导致填充失效。以下是两种不依赖固定kernel、自适应不同形状的通用方案:

方案一:基于轮廓检测与填充

通过检测形状的外层轮廓,直接填充轮廓内部区域,完全适配任意形状的大小和空洞:

import cv2
import numpy as np

# 读取二值图像(假设输入为「白色轮廓+黑色内部/背景」,可根据实际调整)
image = cv2.imread('binary_image.png', cv2.IMREAD_GRAYSCALE)

# 可选:先做开运算去除小噪声,避免误检测小轮廓
noise_kernel = np.ones((3, 3), np.uint8)
clean_image = cv2.morphologyEx(image, cv2.MORPH_OPEN, noise_kernel)

# 反转图像(让轮廓为白色,背景为黑色,符合OpenCV轮廓检测的默认逻辑)
inv_image = cv2.bitwise_not(clean_image)

# 只检测最外层轮廓,忽略内部小轮廓(RETR_EXTERNAL参数)
contours, _ = cv2.findContours(inv_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 创建空白画布,填充轮廓内部为白色
filled_image = np.zeros_like(image)
cv2.drawContours(filled_image, contours, -1, (255), thickness=cv2.FILLED)

# 统计白色像素数(即形状面积)
total_area = cv2.countNonZero(filled_image)
print(f"形状总面积:{total_area}")

关键说明:

  • RETR_EXTERNAL参数确保只提取每个形状的最外层轮廓,不会把内部空洞当成独立轮廓;
  • 开运算去噪是可选步骤,如果你的二值图像已经很干净可以跳过;
  • 如果你的原始二值图像是「黑色轮廓+白色背景」,可以去掉反转图像的步骤,直接检测轮廓。

方案二:漫水填充法

通过填充图像的背景区域,再反转得到填充后的形状,适合背景区域明确的场景:

import cv2
import numpy as np

image = cv2.imread('binary_image.png', cv2.IMREAD_GRAYSCALE)
h, w = image.shape

# 复制图像作为填充画布
flood_canvas = image.copy()

# 创建比原图大2的掩膜,避免漫水填充时边界溢出
mask = np.zeros((h + 2, w + 2), np.uint8)

# 从左上角(假设是背景区域)开始漫水填充,将背景改为白色
cv2.floodFill(flood_canvas, mask, (0, 0), 255)

# 反转图像,此时原来的形状内部空洞会被填充为白色
filled_image = cv2.bitwise_not(flood_canvas)

# 统计面积
total_area = cv2.countNonZero(filled_image)
print(f"形状总面积:{total_area}")

关键说明:

  • 确保漫水填充的起始点(示例中是(0,0))属于背景区域,如果你的图像背景不在角落,可以换其他背景点;
  • 如果背景颜色不是0(黑色),需要调整cv2.floodFill的参数匹配背景色。

为什么原方案失效?

形态学闭运算依赖固定大小的kernel:

  • 当形状内部空洞比kernel大时,无法完全填充;
  • 当形状之间的间距比kernel小时,会把相邻形状合并成一个;
  • 无法自适应不同大小、不同复杂度的形状。

内容的提问来源于stack exchange,提问作者Daniel Agam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:10:28