2012-11-27 22 views
6

Voglio estrarre la silhouette di un'immagine e sto provando a farlo usando la funzione contorno di MatplotLib. Questo è il mio codice:Estrai contorno esterno o sagoma dell'immagine in Python

from PIL import Image 
from pylab import * 

# read image to array 
im = array(Image.open('HOJA.jpg').convert('L')) 

# create a new figure 
figure() 

# show contours with origin upper left corner 
contour(im, origin='image') 
axis('equal') 

show() 

Questa è la mia immagine originale:

Original

E questo è il mio risultato:

Contour

Ma voglio solo mostrare l'esterno contorno, la silhouette. Solo le righe di lettura in questo esempio.

Come posso farlo? Ho letto la documentazione della funzione contour, ma non riesco a ottenere ciò che voglio.

Se si conosce un modo migliore per farlo in Python, per favore dimmi! (MatplotLib, OpenCV, ecc.)

risposta

12

Se si desidera attenersi al proprio approccio di contorno, è sufficiente aggiungere un argomento di livelli con un valore che "limita" l'immagine tra lo sfondo bianco e la foglia.

È possibile utilizzare l'istogramma per trovare un valore appropriato. Ma in questo caso qualsiasi valore leggermente inferiore a 255 andrà bene.

Quindi:

contour(im, levels=[245], colors='black', origin='image') 

enter image description here

Assicurarsi si checkout Scikit-Image, se si vuole fare un po 'serio di elaborazione delle immagini. Esso contiene diversi algoritmi di rilevamento dei bordi ecc

http://scikit-image.org/docs/dev/auto_examples/

+0

Ottima risposta! E grazie per il vostro consiglio su Scikit-Image, lo verificherò! – Xithias

0

Consiglierei utilizzando OpenCV per le prestazioni. Ha le funzioni findContour accessibili da Python utilizzando l'associazione cv2. Questa funzione può essere impostata per restituire solo il contorno esterno.

Dovrai anche impostare la soglia dell'immagine.

+0

Potresti pubblicare il codice per estrarre il contorno esterno usando OpenCV? – Xithias

+0

Stavo per risponderti. Troppo tardi sembra! –

4

Per coloro che vogliono la soluzione OpenCV, eccolo:

ret,thresh = cv2.threshold(image,245,255,0) 
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) 

tam = 0 

for contorno in contours: 
    if len(contorno) > tam: 
     contornoGrande = contorno 
     tam = len(contorno) 

cv2.drawContours(image,contornoGrande.astype('int'),-1,(0,255,0),2) 

cv2.imshow('My image',image) 

cv2.waitKey() 
cv2.destroyAllWindows() 

In questo esempio, traggo solo la più grande contorno. Ricorda che 'immagine' deve essere una matrice a canale singolo.

È necessario modificare i parametri della funzione di soglia, la funzione findContours e la funzione drawContours per ottenere ciò che si desidera.

faccio la conversione a 'int' nella funzione drawContours perché c'è un bug nel Apri CV 2.4.Versione 3 e se non si esegue questa conversione, il programma si interrompe. This is the bug.

Problemi correlati