你所拥有的几乎是正确的。如果你看一下你的阈值图像,它不起作用的原因是你的鞋子对象在图像中有间隙。具体来说,您所追求的是您希望鞋子的周边是全部连接的。如果发生这种情况,那么如果您提取最外部的轮廓(这是您的代码正在执行的操作),您应该只有一个代表对象外周长的轮廓。填充轮廓后,您的鞋子应该是完全坚固的。
由于鞋子的周边不完整且破损,这会导致白色区域断开连接。如果您使用findContours
查找所有轮廓,它只会找到每个白色形状的轮廓,而不是最外周。因此,如果您尝试使用findContours
,它会为您提供与原始图像相同的结果,因为您只需找到图像内每个白色区域的周长,然后用 填充这些区域findContours
。
您需要做的是确保图像完全关闭。我建议您做的是使用形态学将所有断开连接的区域一起关闭,然后findContours
对这个新图像运行调用。具体来说,执行二进制形态关闭。这样做的目的是,它需要靠近在一起的断开的白色区域并确保它们是连接的。使用形态闭合,或者使用类似 7 x 7 方形结构元素的东西来闭合鞋子。您可以将此结构化元素视为白色区域之间的最小间隔,以将它们视为连接。
因此,请执行以下操作:
import numpy as np
import cv2
image = cv2.imread('...') # Load your image in here
# Your code to threshold
image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 45, 0)
# Perform morphology
se = np.ones((7,7), dtype='uint8')
image_close = cv2.morphologyEx(image, cv2.MORPH_CLOSE, se)
# Your code now applied to the closed image
cnt = cv2.findContours(image_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
mask = np.zeros(image.shape[:2], np.uint8)
cv2.drawContours(mask, cnt, -1, 255, -1)
此代码实质上采用您的阈值图像,并将形态关闭应用于该图像。之后,我们找到这个图像的外部轮廓,并用白色填充它们。FWIW,我下载了你的阈值图像,并自己尝试了这个。这就是我从你的图像中得到的:
