获取轮廓内的区域Opencv Python?

2024-05-17 10:11:49 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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)

Tags: 代码imagenp图片mask阈值像素gaussian
2条回答

你所拥有的几乎是正确的。如果您查看阈值图像,它不起作用的原因是您的鞋对象在图像中有间隙。具体地说,你所追求的是,你希望鞋子的周长全部连接起来。如果发生这种情况,那么如果提取最外部的轮廓(这是您的代码所做的),则应该只有一个轮廓表示对象的外部周长。一旦你填充轮廓,那么你的鞋应该是完全固体。

因为你的鞋的周长不完整和破损,这会导致断开白色区域。如果使用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,我下载了你的阈值图像,并尝试了我自己。这就是我从你的照片中得到的:

enter image description here

一个简单的方法是关闭前景中的孔,形成一个具有^{}cv2.MORPH_CLOSE的单轮廓

enter image description here

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

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

相关问题 更多 >