2012-08-02 18 views
7

Próbuję wdrożyć algorytm znaleziony here w python z OpenCV. Jestem nowicjuszem w OpenCV, więc jestem przy mnie gotowy.Python OpenCV Drzewo hierarchii konturu

Próbuję zaimplementować część algorytmu, który usuwa nieistotne granice krawędzi w oparciu o liczbę wewnętrznych granic, które mają.

  • Jeśli aktualna granica krawędź ma dokładnie jeden lub dwa wewnętrzne granice brzegowe, granice wewnętrzne mogą być ignorowane
  • Jeśli aktualna granica krawędź ma więcej niż dwie wewnętrzne granice krawędzi, to może być ignorowane

Mam problem z określeniem struktury drzewa konturów, które wyodrębniłem z obrazu.

Mój obecny źródło:

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

Sądziłem, że za pomocą RETR_TREE dałby mi piękny zagnieżdżony tablicę konturów ale to nie wydaje się być przypadek. Jak mogę odzyskać strukturę drzewa moich konturów?

+1

można znaleźć więcej szczegółów na temat hierarchii w tym artykule: http://opencvpython.blogspot.com/2013/01/contours-5-hierarchy.html –

Odpowiedz

9

Głównym zamieszaniem jest prawdopodobnie fakt, że zwrócona hierarchia jest tablicą o większej liczbie wymiarów niż jest to konieczne. Ponadto wygląda na to, że funkcja Python FindContours zwraca krotkę, która jest LISTĄ konturów, oraz NDARRAY hierarchii ...

Możesz uzyskać rozsądną tablicę informacji hierarchicznych, która jest bardziej zgodna z C docs po prostu biorąc hierarchii [0]. Byłby wtedy odpowiedni kształt, aby zapinać suwak, na przykład za pomocą konturów.

Poniżej jest przykład, że wyciągnie peryferyjnych prostokąty w kolorze zielonym i najgłębsze prostokąty w kolorze czerwonym na tym zdjęciu:

enter image description here

wyjściowa:

enter image description here

Note, przez sposób, w jaki sformułowanie w dokumentach OpenCV jest trochę niejednoznaczne, ale hierarchyDataOfAContour[2] opisuje dzieci tego konturu (jeśli jest ujemny, to jest kontur wewnętrzny) i hierarchyDataOfAContour[3] opisuje rodziców tego konturu (jeśli jest ujemny, to jest kontur zewnętrzny).

Uwaga: Przyjrzałem się implementacji algorytmu, o którym wspomniałem w papierze OCR, i zobaczyłem, że FindContours dawało mi wiele powtórzeń prawie identycznych konturów. To komplikowałoby znalezienie "Skrzynek brzegowych", jak opisuje ten artykuł. Może tak być dlatego, że progi Canny'ego były zbyt niskie (zauważ, że bawiłem się nimi w sposób opisany w artykule), ale może istnieć jakiś sposób na zmniejszenie tego efektu lub po prostu przyjrzeć się średniemu odchyleniu czterech rogów wszystkich skrzynki i eliminacji duplikatów ...

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

Dzięki za odpowiedź . Wpadłem również na ten sam problem z uzyskiwaniem podwójnych konturów. Napisałem do grupy OpenCV, ale nic nie słyszałem: http://tech.groups.yahoo.com/group/OpenCV/message/88940 – jasonlfunk

+0

Mam zaimplementowany algorytm tak dobrze, jak wiedziałem. Wygląda na to, że działa całkiem nieźle. Sprawdź to na https: // github.com/jasonlfunk/ocr-text-extraction – jasonlfunk

+0

Wygląda dobrze. Jeszcze jedną rzeczą, którą możesz chcieć sprawdzić, jest "Transformacja szerokości skoku". Google to ... Link do pierwszego trafienia (papier przez Ephesiein) jest zepsuty, teraz możesz go zobaczyć w "Quick View" – bellkev