我使用自适应阈值技术来创建如下图片:
我使用的代码是:
image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 45, 0)
然后,我使用此代码来获取轮廓:
cnt = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
我的目标是使用外部轮廓内的所有像素生成蒙版,因此我想将对象内的所有像素填充为白色。我怎么能这样做?
我已经尝试过以下代码来创建一个遮罩,但是在应用自适应阈值后,生成的遮罩与图像没有什么不同
mask = np.zeros(image.shape[:2], np.uint8)
cv2.drawContours(mask, cnt, -1, 255, -1)
答案 0 :(得分:14)
你所拥有的几乎是正确的。如果你看看你的阈值图像,它之所以不起作用,是因为你的鞋子对象在图像中有间隙。具体来说,您所追求的是您希望鞋子的周长全部连接。如果发生这种情况,那么如果你提取最外部轮廓(这是你的代码正在做的),你应该只有一个代表对象外围的轮廓。填写轮廓后,鞋子应该完全固定。
由于您的鞋子周边没有完整和破损,这会导致白色区域断开。如果您使用findContours
查找所有轮廓,它只能找到每个白色形状的轮廓,而不是最外层的轮廓。因此,如果您尝试使用findContours
,它会给您与原始图像相同的结果,因为您只是在图像中找到每个白色区域的周长,然后填写这些地区findContours
。
您需要做的是确保图片完全关闭。我建议您使用morphology将所有断开连接的区域关闭在一起,然后对此新图像进行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,我下载了你的thresholded图像,并自己尝试了。这就是我对你的形象所得到的:
答案 1 :(得分:0)
一种简单的方法是使用cv2.morphologyEx()
和cv2.MORPH_CLOSE
封闭前景中的孔以形成单个轮廓
现在填充了外部轮廓,我们可以使用cv2.findContours()
找到外部轮廓,并使用cv2.fillPoly()
用白色填充所有像素
import cv2
# Load in image, convert to grayscale, and threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Close contour
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)
# Find outer contour and fill with white
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cv2.fillPoly(close, cnts, [255,255,255])
cv2.imshow('close', close)
cv2.waitKey()