如何在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




