2012-08-02 367 views
7

我试图在OpenCV中使用python实现发现here的算法。我是OpenCV的新手,对我一无所知。Python OpenCV轮廓树的层次结构

我想实现的算法,删除不相关的边界边界的基础上,他们有内部边界的数量的一部分。

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

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

我的电流源:

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会给我的等值线的一个很好的嵌套数组,但似乎并不如此。我如何检索轮廓的树状结构?

+1

你可以找到这篇文章上的层次结构的详细信息:http://opencvpython.blogspot.com/2013/01/contours-5-hierarchy.html – 2013-01-11 11:40:47

回答

9

这里的主要困惑可能是返回的层次结构是一个numpy数组,其维度超过必要值。最重要的是,它看起来像Python FindContours函数返回一个元组,它是一个轮廓列表和NDARRAY的层次结构...

您可以得到一个更合理的层次结构信息数组, C文档只是采取层次结构[0]。例如,用等高线进行压缩将是一个合适的形状。

下面是,将绘制在绿色的最外层矩形和最里面的长方形红色这个形象的例子:

enter image description here

输出:

enter image description here

注意,由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() 
+0

感谢您的回答。我也遇到了获取重复轮廓的相同问题。我发布到OpenCV小组​​,但没有听到任何声音:http://tech.groups.yahoo.com/group/OpenCV/message/88940 – jasonlfunk 2012-08-04 15:43:41

+0

我已经实现了算法,以及我知道如何。它似乎工作得很好。通过https:// github查看。com/jasonlfunk/ocr-text-extraction – jasonlfunk 2012-08-04 15:44:47

+0

看起来不错。另一件你可能想要检查的事情是“行程宽度变换”。谷歌它...第一击(Epshtein纸)链接现在已经被打破,你可以在“快速浏览”中看到它, – bellkev 2012-08-07 06:19:40