13

我正在尝试使用 OpenCV 实现在 python 中找到的算法。

我正在尝试实现算法的一部分,根据它们拥有的内部边界的数量来删除不相关的边缘边界。

  • 如果当前边缘边界恰好有一个或两个内部边缘边界,则可以忽略内部边界
  • 如果当前边边界有两个以上的内边边界,则可以忽略

我无法确定从图像中提取的轮廓的树结构。

我目前的来源:

import cv2

# Load the image
img = cv2.imread('test.png')
cv2.copyMakeBorder(img, 50,50,50,50,cv2.BORDER_CONSTANT, img, (255,255,255))

# Split out each channel
blue = cv2.split(img)[0]
green = cv2.split(img)[1]
red = cv2.split(img)[2]

# Run canny edge detection on each channel
blue_edges = cv2.Canny(blue, 1, 255)
green_edges = cv2.Canny(green, 1, 255)
red_edges = cv2.Canny(red, 1, 255)

# Join edges back into image
edges = blue_edges | green_edges | red_edges

# Find the contours
contours,hierarchy = cv2.findContours(edges.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

# For each contour, find the bounding rectangle and draw it
for cnt in contours:
    x,y,w,h = cv2.boundingRect(cnt)
    cv2.rectangle(edges,(x,y),(x+w,y+h),(200,200,200),2)

# Finally show the image
cv2.imshow('img',edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

我认为使用 RETR_TREE 会给我一个很好的轮廓嵌套数组,但似乎并非如此。如何检索轮廓的树结构?

4

1 回答 1

19

这里的主要混淆可能是返回的层次结构是一个 numpy 数组,其维度比必要的多。最重要的是,看起来 Python FindContours 函数返回一个元组,它是一个轮廓列表,以及层次结构的 NDARRAY ......

只需采用层次结构[0],您就可以获得更符合 C 文档的层次结构信息的合理数组。然后,它将是一个合适的形状,例如,与轮廓一起拉链。

下面是一个示例,它将在此图像上以绿色绘制最外面的矩形,以红色绘制最里面的矩形:

在此处输入图像描述

输出:

在此处输入图像描述

请注意,顺便说一下,OpenCV 文档中的措辞有点模棱两可,但hierarchyDataOfAContour[2]描述了该轮廓的子代(如果它是负数,则它是内轮廓),并hierarchyDataOfAContour[3]描述了该轮廓的父代(如果它是负数)那么这是一个外部轮廓)。

另请注意:我研究了您在 OCR 论文中提到的算法,我看到 FindContours 给了我很多重复的几乎相同的轮廓。如论文所述,这将使“边缘盒”的发现变得复杂。这可能是因为 Canny 阈值太低(请注意,我在论文中描述过它们),但可能有一些方法可以减少这种影响,或者只查看所有的四个角的平均偏差框并消除重复...

import cv2
import numpy

# Load the image
img = cv2.imread("/ContourTest.PNG")

# Split out each channel
blue, green, red = cv2.split(img)

def medianCanny(img, thresh1, thresh2):
    median = numpy.median(img)
    img = cv2.Canny(img, int(thresh1 * median), int(thresh2 * median))
    return img

# Run canny edge detection on each channel
blue_edges = medianCanny(blue, 0.2, 0.3)
green_edges = medianCanny(green, 0.2, 0.3)
red_edges = medianCanny(red, 0.2, 0.3)

# Join edges back into image
edges = blue_edges | green_edges | red_edges

# Find the contours
contours,hierarchy = cv2.findContours(edges, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

hierarchy = hierarchy[0] # get the actual inner list of hierarchy descriptions

# For each contour, find the bounding rectangle and draw it
for component in zip(contours, hierarchy):
    currentContour = component[0]
    currentHierarchy = component[1]
    x,y,w,h = cv2.boundingRect(currentContour)
    if currentHierarchy[2] < 0:
        # these are the innermost child components
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),3)
    elif currentHierarchy[3] < 0:
        # these are the outermost parent components
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),3)

# Finally show the image
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
于 2012-08-04T10:03:26.410 回答