在Opencv Python中获取轮廓区域?

时间:2014-12-04 16:46:24

标签: python opencv image-processing opencv-contour

我使用自适应阈值技术来创建如下图片:

enter image description here

我使用的代码是:

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)

2 个答案:

答案 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图像,并自己尝试了。这就是我对你的形象所得到的:

enter image description here

答案 1 :(得分:0)

一种简单的方法是使用cv2.morphologyEx()cv2.MORPH_CLOSE封闭前景中的孔以形成单个轮廓

enter image description here

现在填充了外部轮廓,我们可以使用cv2.findContours()找到外部轮廓,并使用cv2.fillPoly()用白色填充所有像素

enter image description here

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()