You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python中实现类似MATLAB imfill的图像内部白色填充功能?

在Python中实现MATLAB imfill 功能(填充形状内部黑色区域)

嘿,我正好处理过类似的需求,你要的就是MATLAB imfill对应的Python实现,用OpenCV就能轻松搞定。先给你拆解下思路,再给你两种实用的解决方案:

方法一:用OpenCV的floodFill(漫水填充)

floodFill的逻辑其实很好理解:从你指定的种子点开始,把相邻的、符合颜色条件的像素都替换成目标颜色。对你的场景来说,图像的四个角落基本都是背景区域,我们就从这些点出发,把背景之外的内部黑色空洞填充成白色。

完整代码(基于你现有代码修改)

import cv2
import numpy as np

# 读取并预处理图像(保留你原来的逻辑)
image = cv2.imread('rec2.jpg')
kernel = np.ones((5,5),np.uint8)
w = int(image.shape[1] * 0.3)
h = int(image.shape[0] * 0.5)
resized = cv2.resize(image, (w, h), interpolation=cv2.INTER_CUBIC)
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(blurred, 200, 255, cv2.THRESH_BINARY_INV)[1]

# ------------------- 核心填充步骤 -------------------
# 创建mask:floodFill要求mask比原图大2个像素,用来标记填充区域
mask = np.zeros((h + 2, w + 2), np.uint8)

# 从四个角落作为种子点,把黑色背景填充成白色
cv2.floodFill(thresh, mask, (0, 0), 255)
cv2.floodFill(thresh, mask, (w-1, 0), 255)
cv2.floodFill(thresh, mask, (0, h-1), 255)
cv2.floodFill(thresh, mask, (w-1, h-1), 255)

# 取反得到实心形状:此时原来的内部黑色区域变成了背景的反色,取反后就全白了
filled_thresh = cv2.bitwise_not(thresh)

# 对比显示结果
cv2.imshow("Original Threshold", thresh)
cv2.imshow("Filled Solid Shape", filled_thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

方法二:通过轮廓填充(更直观)

既然你已经在提取轮廓了,那直接用轮廓填充更直观:找到所有外部轮廓,然后把每个轮廓的内部直接涂成白色就行。

代码实现

import cv2
import numpy as np

image = cv2.imread('rec2.jpg')
w = int(image.shape[1] * 0.3)
h = int(image.shape[0] * 0.5)
resized = cv2.resize(image, (w, h), interpolation=cv2.INTER_CUBIC)
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(blurred, 200, 255, cv2.THRESH_BINARY_INV)[1]

# 提取外部轮廓(和你原来的代码一致)
cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 创建空白画布,用来填充轮廓
filled_image = np.zeros_like(thresh)

# 遍历每个轮廓,填充内部(thickness=cv2.FILLED表示填充整个轮廓区域)
for cnt in cnts:
    cv2.drawContours(filled_image, [cnt], -1, 255, thickness=cv2.FILLED)

# 显示结果
cv2.imshow("Contour-Filled Result", filled_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

两种方法怎么选?

  • floodFill方法:适合背景单一、内部空洞清晰的图像,不需要提前提取轮廓,速度更快。
  • 轮廓填充方法:适合需要精准控制填充区域的场景(比如只填充面积大于某个阈值的轮廓),灵活性更高。

两种方法都能实现你要的“实心形状”效果,完全对应MATLAB imfill的功能,你可以根据自己的图像情况挑一个用~

内容的提问来源于stack exchange,提问作者Shivam Sahil

火山引擎 最新活动