在opencv-python中用颜色填充区域

时间:2021-03-26 11:38:15

标签: python opencv

opencv-python 如何用白色填充特定区域?

我正在尝试使用 cv2.findContours() 中的轮廓制作蒙版。 但无法找到填充这两个特定区域的方法。

(cv2.drawContours(thickness = -1) 没有像我预期的那样工作。)

示例:

来自:enter image description here

至:enter image description here

1 个答案:

答案 0 :(得分:2)

您可以构建一个轮廓层次树并迭代该树,直到达到内部轮廓。

参见:Contours Hierarchy

在您的情况下,层次结构是:

  • 圆的外部。
  • 圆的内部(内部标记为单独的轮廓)。
  • 内部轮廓大,小轮廓很少。
    我们想要填充小轮廓而不是大轮廓。

我们可以使用以下阶段:

  • 查找轮廓和层次结构,使用 RETR_TREE 在轮廓内创建轮廓树。
  • 找到面积最大的轮廓(假设圆是最大的轮廓) - 父轮廓。
  • 找到父轮廓的子节点的子节点。
  • 迭代兄弟姐妹,找到面积最大的兄弟姐妹(我们需要忽略它)。
  • 再次迭代兄弟姐妹并填充除最大的兄弟姐妹轮廓之外的所有兄弟姐妹轮廓。

代码如下:

import numpy as np
import cv2

# Read input image
img = cv2.imread('input.png', cv2.IMREAD_GRAYSCALE)

# Apperanly there is a white rectangle around the image - crop the inner area.
img = img[4:-4, 4:-4]


# Find contours and hierarchy, use RETR_TREE for creating a tree of contours within contours
cnts, hiers = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:]  # [-2:] indexing takes return value before last (due to OpenCV compatibility issues).

img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)  # Convert image to BGR for testing - fill contours with green color.

# https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html
# Hierarchy Representation in OpenCV
# Each contour has its own information regarding what hierarchy it is, who is its child, who is its parent etc. 
# OpenCV represents it as an array of four values : [Next, Previous, First_Child, Parent]
hiers = hiers[0]  # Remove redundant dimension of hiers.

# Find contour with the maximum area (assume the circle is the largest contour).
c = max(cnts, key=cv2.contourArea)

parent_idx = cnts.index(c)

parent_hier = hiers[parent_idx]  # Get the first outer contour - assume there is only one in our case.
parent_idx = parent_hier[2]  # Index of the first child.
parent_hier = hiers[parent_idx] # Ooops - the inner contour is the inner part of the circle - need one more inner hierarchy

child_idx = parent_hier[2]  # Index of the first child

# Iterate all childes and find the contour with the maximum area - we need to ignore it.
max_area = 0
while child_idx != -1:
    child_hier = hiers[child_idx]  # Next child in hierarchy
    c = cnts[child_idx]  # Get the contour with the same index
    area = cv2.contourArea(c)
    max_area = max(area, max_area)
    child_idx = child_hier[0]  # Get index of next contour in the same hierarchy of the child.


child_idx = parent_hier[2]  # Index of the first child

# Iterate all childes (there are supposed to be three "large" childes and few small childes in our case).
while child_idx != -1:
    child_hier = hiers[child_idx]  # Next child in hierarchy
    c = cnts[child_idx]  # Get the contour with the same index

    if cv2.contourArea(c) < max_area:
        # Fill the contour with green color
        cv2.drawContours(img, [c], -1, (0, 255, 0), -1)

    child_idx = child_hier[0]  # Get index of next contour in the same hierarchy of the child.

结果:
enter image description here

相关问题