使用 findContours 从父级中删除子级轮廓

问题描述 投票:0回答:1

澄清:我需要原始多边形点,而不是蒙版图像。蒙版图像只是一个例子。外层答案无效后,画内层答案。

我正在尝试将分割掩码(二进制)转换为多边形。由于社区中大量使用,我尝试使用 OpenCV findContour,但它缺乏重要的用例。

考虑到物体内部有孔,不可能将 findContour 方法的输出转换为多边形。因为 findContour 不关心对象内部的孔。

假设我们下面有一个二进制对象,

findContour 将返回所有绘制为红色的轮廓。

这使得无法将它们转换为多边形,因为需要从外部轮廓中删除内部轮廓,从而在父多边形内部创建一个空洞。这需要将外部轮廓分成至少两个不同的轮廓。

一个工作示例:

我创建了一个只有 0 和 1 的二值图像。其中0表示黑色,白色区域用1表示。我使用 cv2.RETR_LIST 和 cv2.CHAIN_APPROX_NONE 调用了 cv2.findContours 方法,它按预期返回两个轮廓,其中一个轮廓位于另一个轮廓内部(如上图所示)。

当我尝试将这些多边形转换为蒙版图像时,我首先绘制小多边形(只有 244 个点),然后绘制外部多边形(有 793 个点),并使用不同的随机颜色。结果如下。

这不是我所期望的,应该有两种颜色。但是因为内部圆在外部圆的内部,所以我无法生成外部圆缺少内圆的多边形。这需要至少两个多边形作为外部多边形。

使用带有层次结构的drawContours的替代方法,但这不起作用,因为我不需要图像,我需要原始多边形点。

有解决办法吗?

python opencv polygon
1个回答
0
投票

我建议你用

处理你的图像
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

我假设

thresh
是你的二值化图像。

模式

cv.RETR_TREE
使您能够建立您想要的层次结构。如果我相应地处理你的图像,那么我得到

  • len(contours[0]) == 378
    (因此,外轮廓)
  • len(contours[1]) == 116
    (因此,内部轮廓)
  • hierarchy == [[[-1 -1  1 -1]
                   [-1 -1 -1  0]]]
    

在这里,

hierarchy
是最相关的(请参阅doc)。虽然实际上
hierarchy
有 3 个维度,但为了简单起见,我将忽略轴 0 中的“环绕”维度:

  • hierarchy
    中的行指的是
    contours
    中相应的轮廓。
  • 第 0 列和第 1 列指同一层级上的轮廓。由于在您的情况下,我们在同一层次结构级别上没有列,因此所有值都设置为 -1。
  • 第 2 列指的是每个轮廓的第一个子轮廓:
    • 外轮廓(索引 0 处的轮廓)有一个子轮廓;即内部轮廓(索引 1 处的轮廓)。因此,
      contours[0, 2] == 1
    • 内部轮廓(索引 1 处的轮廓)没有子轮廓。于是,
      contours[1, 2] == -1
  • 第 3 列指的是每个轮廓的父轮廓:
    • 外轮廓(索引 0 处的轮廓)没有父轮廓。因此,
      contours[0, 3] == -1
    • 内部轮廓(索引 1 处的轮廓)有一个父级;即外轮廓(索引 0 处的轮廓)。因此,
      contours[1, 3] == 0

有了这些知识,你应该能够建立一个绘制顺序:找到所有没有父级的轮廓并首先绘制它们,然后依次绘制它们的子级。

© www.soinside.com 2019 - 2024. All rights reserved.