2015-02-23 48 views
5

Ho seguito questo tutorial dal numero documentation ufficiale. Corro il loro codice:Come posso visualizzare i contorni di un'immagine usando OpenCV Python?

import numpy as np 
import cv2 

im = cv2.imread('test.jpg') 
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 
ret,thresh = cv2.threshold(imgray,127,255,0) 
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cv2.drawContours(img, contours, -1, (0,255,0), 3) 

che è ok: nessun errore, ma niente è displayed.I vuole visualizzare il risultato hanno ottenuto, come hanno mostrato sul immagine:

enter image description here

Come posso visualizzare il risultato dei countours come quello (solo il risultato sinistro o quello giusto)? So che devo usare cv2.imshow(something) ma come in questo caso specifico?

risposta

9

Prima di tutto, questo esempio mostra solo come disegnare contorni con la semplice approssimazione. Se dovessi mostrare quell'immagine ora, otterrai solo ciò che vedi sul lato destro di quella figura. Se si desidera ottenere l'immagine sul lato sinistro, è necessario rilevare il contorno completo. Nello specifico, è necessario sostituire il flag cv2.CHAIN_APPROX_SIMPLE con cv2.CHAIN_APPROX_NONE. Date un'occhiata al documento OpenCV su findContours per ulteriori dettagli: http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#findcontours

Inoltre, il vostro codice disegna i contorni sull'immagine, ma non visualizza i risultati. Avrai bisogno di chiamare cv2.imshow per quello.

Come tale, creare due immagini in questo modo:

# Your code 
import numpy as np 
import cv2 

im = cv2.imread('test.jpg') 
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 
ret,thresh = cv2.threshold(imgray,127,255,0) 

# Detect contours using both methods on the same image 
contours1, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) 
contours2, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 

# Copy over the original image to separate variables 
img1 = im.copy() 
img2 = im.copy() 

# Draw both contours onto the separate images 
cv2.drawContours(img1, contours1, -1, (255,0,0), 3) 
cv2.drawContours(img2, contours2, -1, (255,0,0), 3) 

Ora, per ottenere la cifra che vedete qui sopra, ci sono due modi per farlo:

  1. Crea un immagine che memorizza entrambi questi risultati insieme, quindi mostra questa immagine combinata.
  2. Utilizzare matplotlib, combinato con subplot e imshow in modo da poter visualizzare due immagini in una finestra.

ti faccio vedere come si fa utilizzando entrambi i metodi:

Metodo # 1

Semplicemente pila lato due immagini affiancate, quindi mostrare l'immagine dopo:

out = np.hstack([img1, img2]) 

# Now show the image 
cv2.imshow('Output', out) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 

I li impila orizzontalmente in modo che siano un'immagine combinata, quindi mostrarli con cv2.imshow.

Metodo # 2

È possibile utilizzare matplotlib:

import matplotlib.pyplot as plt 

# Spawn a new figure 
plt.figure() 
# Show the first image on the left column 
plt.subplot(1,2,1) 
plt.imshow(img1[:,:,::-1]) 
# Turn off axis numbering 
plt.axis('off') 

# Show the second image on the right column 
plt.subplot(1,2,2) 
plt.imshow(img2[:,:,::-1]) 
# Turn off the axis numbering 
plt.axis('off') 

# Show the figure 
plt.show() 

Questo dovrebbe visualizzare sia immagini in sottofigure separati all'interno di una finestra globale figura. Se date un'occhiata a come sto chiamando imshow qui, vedrete che sto scambiando i canali RGB perché OpenCV legge in immagini in formato BGR. Se si desidera visualizzare le immagini con matplotlib, è necessario invertire i canali poiché le immagini sono in formato RGB (come dovrebbero essere).


Per rispondere alla sua domanda nei commenti, si prenderebbe quale struttura di contorno che si desidera (o contours1contours2) e cercare i punti di contorno. contours è un elenco di tutti i contorni possibili e all'interno di ciascun contorno c'è una matrice 3D che è modellata in un formato N x 1 x 2. N sarebbe il numero totale di punti che rappresentano il contorno. Rimuoverò la seconda dimensione di singleton in modo che possiamo ottenere che questa sia una matrice N x 2. Inoltre, usiamo la rappresentazione completa dei contorni per ora:

points = contours1[0].ravel().reshape((len(contours1[0]),2)) 

sto per scontato che l'immagine ha solo un oggetto, da qui la mia indicizzazione in contours1 con indice 0. I dipanare la matrice in modo che diventa un vettore a riga singola, quindi rimodella la matrice in modo che diventi N x 2. Quindi, siamo in grado di trovare il punto di minimo da:

min_x = np.argmin(points[:,0]) 
min_point = points[min_x,:] 

np.argmin trova la posizione del valore più piccolo in una matrice che si fornisce. In questo caso, vogliamo operare lungo la coordinata x o le colonne. Una volta trovata questa posizione, semplicemente indicizziamo il nostro array di punti di contorno 2D ed estraiamo il punto del contorno.

+0

questa è una risposta più dettagliata e completa. Grazie mille –

+0

Oh mio piacere :) Non intendevo rubarlo da runDOSrun, ma in mia difesa, stavo lavorando a questa risposta mentre lui postava. Buona fortuna! – rayryeng

+0

Posso sembrare scortese se ti faccio una domanda finale perché questo sito dice che devo aspettare 90 minuti prima di chiedere nuovamente. Voglio stampare le coordinate del pixel che è l'armadio dell'asse Y (significa che la sua coordinata x è la più piccola) e che appartiene ai contorni. Potrebbe essere troppo semplice per te? Sono solo al livello principiante –

3

aggiungere queste 2 righe alla fine:

cv2.imshow("title", im) 
cv2.waitKey() 

Inoltre, essere consapevoli del fatto che avete img invece di im nella tua ultima riga.

+0

grazie mille. Ho sollevato la tua risposta che è corretta, ma ho accettato una più lunga e dettagliata. Grazie ancora, signore. –

+1

@Kabyle Prego! L'ottima risposta di Rayryeng meritava un 'accettazione;) – runDOSrun

+1

@runDOSrun - Grazie :) Non intendevo portare i riflettori da te, ma stavo lavorando alla mia risposta mentre tu postavi. Grazie per aver pubblicato una risposta 'tl; dr'! – rayryeng

1

È necessario aggiungere cv2.imshow ("Title", img) alla fine del codice. Dovrebbe apparire così:

import numpy as np 
import cv2 

im = cv2.imread('test.jpg') 
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 
ret,thresh = cv2.threshold(imgray,127,255,0) 
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cv2.drawContours(im, contours, -1, (0,255,0), 3) 
cv2.imshow("title", im) 
cv2.waitKey() 
+0

Basta invitare la mia risposta e accettare l'altra! Saluti! –

+0

Alla fine ho accettato la lunga risposta perché ci sono molti dettagli in essa che ho bisogno di leggere di nuovo e capire. Ma ho votato in su per la tua risposta e quella precedente che era troppo difficile per me. Grazie mille ancora –

Problemi correlati