2012-08-02 16 views
7

Sto cercando di implementare l'algoritmo trovato here in python con OpenCV. Sono nuovo di OpenCV così nudo con me.Python OpenCV Gerarchia ad albero Contour

Sto cercando di implementare la parte dell'algoritmo che rimuove i limiti del bordo irrilevanti in base al numero di limiti interni che hanno.

  • Se la corrente di confine bordo ha esattamente uno o due interni confini bordo, i confini interni possono essere ignorati
  • Se la corrente di confine comune ha più di due confini bordo interne, può essere ignorato

Ho problemi a determinare la struttura ad albero dei contorni che ho estratto dall'immagine.

La mia fonte di corrente:

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

ho pensato che utilizzando RETR_TREE mi avrebbe dato un bel array nidificato dei contorni, ma che non sembra essere il caso. Come posso recuperare la struttura ad albero dei miei contorni?

+1

potete trovare maggiori dettagli su gerarchia su questo articolo: http://opencvpython.blogspot.com/2013/01/contours-5-hierarchy.html –

risposta

9

La confusione principale qui è probabilmente il fatto che la gerarchia restituita è una matrice numpy con più dimensioni del necessario. Inoltre, sembra che la funzione Python FindContours restituisca una tupla che è una LISTA dei contorni e NDARRAY della gerarchia ...

È possibile ottenere una serie ragionevole di informazioni sulla gerarchia più in linea con i documenti C semplicemente prendendo la gerarchia [0]. Sarebbe quindi una forma appropriata per comprimere, ad esempio, con i contorni.

seguito è un esempio che, trarrà i rettangoli più esterni in verde e rettangoli intimi in rosso su questa immagine:

enter image description here

uscita:

enter image description here

nota, da il modo in cui la dicitura nei documenti OpenCV è un po 'ambigua, ma descrive i figli di quel contorno (se è negativo, quindi quello è un contorno interno) e hierarchyDataOfAContour[3] descrive i genitori di quel contorno (se è negativo allora quello è un contorno esterno).

Nota: ho cercato di implementare l'algoritmo a cui ci si riferiva nel documento OCR e ho visto che FindContours mi stava dando molte ripetizioni di contorni quasi identici. Ciò complicherebbe il ritrovamento di "Edge Boxes" come descritto nel documento. Ciò potrebbe essere dovuto al fatto che le soglie Canny erano troppo basse (si noti che stavo giocando con loro come descritto nel documento), ma ci può essere un modo per ridurre questo effetto o semplicemente guardare la deviazione media dei quattro angoli di tutti i scatole e eliminare i duplicati ...

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

Grazie per la risposta . Ho anche avuto lo stesso problema di ottenere contorni duplicati. Ho postato nel gruppo OpenCV ma non ho sentito nulla: http://tech.groups.yahoo.com/group/OpenCV/message/88940 – jasonlfunk

+0

Ho implementato l'algoritmo e ho saputo come. Sembra che funzioni abbastanza bene. Dai un'occhiata a https: // github.it/jasonlfunk/ocr-text-extraction – jasonlfunk

+0

Sembra buono. Un'altra cosa che potresti voler controllare è la "Trasformazione larghezza tratto". Google it ... Il link del primo hit (carta di Epshtein) è rotto in questo momento è possibile vederlo in "Quick View" – bellkev

Problemi correlati