如何使用python opencv提取内部轮廓(孔)?

如何使用python opencv提取内部轮廓(孔)?,python,opencv,Python,Opencv,是否有一种简单直接的方法可以使用opencv 3.1 python从图像中提取内部轮廓(孔) 我知道我可以使用“面积”作为条件。但是,如果更改图像分辨率,则“区域”不同 例如,对于此图像: 如何提取内部孔 _, contours, hier_ = cv2.findContours(img,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE) areas = [cv2.contourArea(c) for c in millCnts] max_area = np.max(

是否有一种简单直接的方法可以使用opencv 3.1 python从图像中提取内部轮廓(孔)

我知道我可以使用“面积”作为条件。但是,如果更改图像分辨率,则“区域”不同

例如,对于此图像: 如何提取内部孔

_, contours, hier_ = cv2.findContours(img,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in millCnts]
max_area = np.max(areas)
Mask = np.ones(img.shape[:2], dtype="uint8") * 255

   # I can do something like this (currently not working, just to show an example)
for c in contours:
    if(( cv2.contourArea(c) > 8) and (cv2.contourArea(c)< 100000)):
        cv2.drawContours(Mask ,[c],-1,0,1)
\u轮廓,层次=cv2.找到的轮廓(img,cv2.翻新,cv2.链约\u简单)
面积=[cv2.c的轮廓面积(c)]
最大面积=np.max(面积)
Mask=np.one(img.shape[:2],dtype=“uint8”)*255
#我可以这样做(目前不起作用,仅举一个例子)
对于等高线中的c:
如果((cv2.轮廓面积(c)>8)和(cv2.轮廓面积(c)<100000)):
cv2.绘制轮廓(掩模,[c],-1,0,1)

正如我在评论中解释的,您必须检查层次结构返回变量。找到等高线后,您将获得等高线(点列表)和层次结构(列表列表)

这方面的问题非常清楚:

层次结构–可选输出向量,包含有关 图像拓扑。它的元素数量与等高线的数量相同。对于 每个第i等高线[i],元素
层次[i][0]
hierarchy[i][1]
hierarchy[i][2]
hierarchy[i][3]
设置为 下一个和上一个等高线的等高线中基于0的索引 同一层级,第一个子轮廓和父轮廓 轮廓,分别。如果轮廓i没有下一个, 上一个、父轮廓或嵌套轮廓的对应元素 层次结构[i]将为负

因此,这意味着对于每个
countour[i]
您应该得到一个
hierarchy[i]
,其中包含一个包含4个变量的列表:

  • 层次[i][0]
    :同一级别下一个轮廓的索引
  • hierarchy[i][1]
    :同一级别上一个轮廓的索引
  • 层次结构[i][2]
    :第一个子级的索引
  • 层次结构[i][3]
    :父级的索引
因此,在你的例子中,应该有一个没有父对象的,如果是负数,你可以通过检查
层次结构[i][3]
来检查哪一个

它应该类似于(未测试的代码):

*更新:

为了总结我们在聊天中讨论的内容

  • 图像太大,轮廓有小洞:用75号的内核进行扩张和腐蚀
  • 图像需要反转,因为OpenCV希望放大黑色背景
  • 该算法给出了两个大轮廓,一个外部(如预期)和一个内部(几乎与外部相同),这可能是由于图像具有一些外部(和闭合)凹凸。这是通过在没有父对象及其第一个子对象的情况下删除轮廓来解决的

您始终可以使用层次结构值来了解它们是否嵌套(孔)或不嵌套(外部孔)。。。不确定find contours是否正确获取了所有轮廓(您应该显示该输出),但如果正确,您可以通过检查相应的层次结构h来检查countour'c'是否嵌套,如果它是非负的,则检查第四个值(
h[3]
)。我想我的主要问题是理解层次结构是如何工作的。输出阵列很大:\n在这种特殊情况下,它无法工作。限值应该在8000到9000之间!哪里定义了
millCnts
?你能展示一张所有发现的轮廓的图像吗?我想我理解它是如何工作的,但是不清楚如何通过比较来完成。我知道您没有测试代码,但输出是:ValueError:包含多个元素的数组的真值不明确。使用a.any()或a.all()@marco为什么会有歧义,据我所知应该是一个列表列表。。。。你可以打印
len(等高线)
len(hier_)
它应该是一样的,或者那里有什么问题,你也可以尝试做
len(_hier[0])
它应该是4等高线的len是1335,hier是1,hier[0]是1335@marco哇,1335的轮廓太多了。。。。您能否打印
len(\u hier[0][0])
,希望这是4,然后您必须更改为
层次结构[0][i][3]
。然而,如果你想到文档中解释的输出,我会觉得有点奇怪……我觉得它很奇怪。但我认为它是有效的。代码是:holes=[millCnts[i]表示范围内的i(len(millCnts)),如果hier[0][i][3]>=0]但是,我不知道如何绘制“holes”,因为有一个列表,并且drawCountours只接受countours或numpy
holes = [contours[i] for i in range(len(contours)) if hierarchy[i][3] >= 0]