【问题标题】:How can I extract internal contours (holes) with python opencv?如何使用 python opencv 提取内部轮廓(孔)?
【发布时间】:2016-05-11 10:37:43
【问题描述】:

有没有一种简单直接的方法可以使用 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)

【问题讨论】:

  • 您始终可以使用层次结构值来了解它们是否嵌套(孔)或不嵌套(外部)...不确定是否已经找到轮廓正确获取所有轮廓(您应该表明输出),但如果是这样,您可以通过检查相应的层次结构“h”来检查计数“c”是否嵌套,如果它是非负数,则为第四个值(h[3])。
  • 我认为我的主要问题是理解层次结构是如何工作的。输出数组很大:\ 在这种特殊情况下,它不起作用。限制应该在 8000 到 9000 之间!
  • millCnts 在哪里定义?你能显示所有找到的轮廓的图像吗?

标签: python opencv


【解决方案1】:

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

documentation在这很清楚:

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

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

  • hierarchy[i][0]:同级下一个轮廓的索引
  • hierarchy[i][1]: 上一个同级轮廓的索引
  • hierarchy[i][2]:第一个孩子的索引
  • hierarchy[i][3]: 父级索引

所以说,在你的情况下,应该有一个没有父母,如果它是否定的,你可以通过检查hierarchy[i][3]来检查哪一个。

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

holes = [contours[i] for i in range(len(contours)) if hierarchy[i][3] >= 0]

* 更新:*

总结一下我们在聊天中讨论的内容,

  • 图像太大,轮廓有小洞:用大小为 75 的核的 dilate 和 erode 解决
  • 图像需要反转,因为 OpenCV 需要扩大黑色背景
  • 算法给出了 2 个大轮廓,一个外部(如预期)和一个内部(几乎与外部相同),这可能是由于图像具有一些外部(和闭合)凹凸。这个问题是通过移除没有父级及其第一个子级的轮廓来解决的。

【讨论】:

  • 我认为我理解它是如何工作的,但是目前尚不清楚如何进行比较。我知道您没有测试代码,但输出是: ValueError: 具有多个元素的数组的真值是不明确的。使用 a.any() 或 a.all()
  • @marco 为什么它会模棱两可,据我所知,它应该是一个 List of Lists ......你能打印len(contours)len(hier_) 它应该是一样的,还是什么那里错了,你也可以尝试做len(_hier[0])应该是4
  • 轮廓的 len 是 1335,hier 是 1,hier[0] 是 1335
  • @marco,哇,1335 对于该图像来说轮廓太多了......你能打印len(_hier[0][0]),希望这是4,然后你将不得不更改为hierarchy[0][i][3]。但是,如果您想到文档中解释的输出,我会有点奇怪......
  • 我觉得它很奇怪。但我认为它有效。代码是:holes = [millCnts[i] for i in range(len(millCnts)) if hier[0][i][3] >= 0] 但是,我不知道如何绘制“孔”,因为有一个列表,而 drawCountours 只接受 countours 或 numpy
猜你喜欢
  • 1970-01-01
  • 2019-03-23
  • 2022-01-23
  • 2019-01-25
  • 2016-09-25
  • 2021-09-07
  • 2019-06-28
  • 1970-01-01
  • 2015-02-02
相关资源
最近更新 更多