Python OpenCV轮廓树层次结构 [英] Python OpenCV Contour tree hierarchy

查看:143
本文介绍了Python OpenCV轮廓树层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施找到的算法

I am trying to implement the algorithm found here in python with OpenCV.

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

I am trying to implement the part of the algorithm that remove irrelevant edge boundaries based on the number of interior boundaries that they have.

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

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

I am having trouble determining the tree structure of the contours I have extracted from the image.

我当前的来源:

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会给我一个很好的嵌套轮廓线数组,但事实并非如此.如何检索轮廓的树形结构?

I assumed that using RETR_TREE would give me a nice nested array of the contours but that doesn't seem to be the case. How do I retrieve the tree structure of my contours?

推荐答案

此处的主要困惑可能是以下事实:返回的层次结构是一个numpy数组,其维数超出了必要.最重要的是,Python FindContours函数返回一个元组,该元组是轮廓的列表,以及层次结构的NDARRAY ...

The main confusion here is probably the fact that the hierarchy returned is a numpy array with more dimensions than necessary. On top of that, it looks like the Python FindContours function returns a tuple that is a LIST of contours, and and NDARRAY of the hierarchy...

仅通过获取等级[0],您就可以得到一个更合理的层次信息数组,这些信息与C文档更加一致.这样便可以形成适合的形状,例如带有轮廓的拉链.

You can get a sensible array of hierarchy information that is more in line with the C docs by just taking hierarchy[0]. It would then be an appropriate shape to zip, for example, with the contours.

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

Below is an example that, will draw the outermost rectangles in green and the innermost rectangles in red on this image:

输出:

顺便说一下,请注意,OpenCV文档中的措辞有点含糊,但是hierarchyDataOfAContour[2]描述了该轮廓的子级(如果为负,则为内部轮廓),而hierarchyDataOfAContour[3]则描述了该轮廓.该轮廓的父级(如果为负,则为外部轮廓).

Note, by the way, that the wording in the OpenCV docs is a little ambiguous, but hierarchyDataOfAContour[2] describes the children of that contour (if it is negative then that is an inner contour), and hierarchyDataOfAContour[3] describes the parents of that contour (if it is negative then that is an exterior contour).

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

Also note: I looked into implementing the algorithm that you referred to in the OCR paper, and I saw that FindContours was giving me a lot of repeats of near-identical contours. This would complicate the finding of "Edge Boxes" as the paper describes. This may be because the Canny thresholds were too low (note that I was playing around with them as described in the paper), but there may be some way to reduce that effect or just look at the average deviation of the four corners of all the boxes and eliminate duplicates...

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()

这篇关于Python OpenCV轮廓树层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆