2013-04-01 26 views
7

Ho un'applicazione OpenCV alimentata da un flusso di webcam dell'interno di un ufficio (molti dettagli) dove devo trovare un marker artificiale. Il marcatore è un quadrato nero su sfondo bianco. Uso Canny per trovare bordi e cvFindContours per il contouring, quindi approxPolyDP e co. per filtrare e trovare candidati, quindi utilizzare l'istogramma locale per filtrare ulteriormente, bla bla bla ...Conversione OpenCV Bordi Canny ai contorni

Questo funziona più o meno, ma non esattamente come voglio. FindContours restituisce sempre un ciclo chiuso, anche se Canny crea una linea non chiusa. Prendo un contorno che cammina su entrambi i lati della linea formando un anello. Per i bordi chiusi nell'immagine Canny (il mio marker), ottengo 2 contorni, uno all'interno e uno all'esterno. devo problemi con questa operazione:

  • ottengo 2 contorni per ciascun marcatore (non così grave)

  • il filtraggio più banale non è utilizzabile (rifiuto non chiuso contorno)

Quindi la mia domanda: è possibile ottenere contorni non chiusi per bordi Canny non chiusi? O qual è il modo standard per risolvere i 2 problemi di cui sopra?

Canny è uno strumento molto valido, ma ho bisogno di convertire l'immagine b/n 2D in qualcosa di facilmente processabile. Qualcosa come i componenti collegati che elencano tutti i pixel in ordine di marcia del componente. Quindi posso filtrare i loop e inserirli in approxPolyDP.

Aggiornamento: Ho perso alcuni dettagli importanti: il marcatore può essere in qualsiasi orientamento (non è rivolto verso la fotocamera, senza angoli retti), infatti quello che sto facendo è la stima dell'orientamento 3D, basata sulla proiezione 2D di il marcatore

risposta

10

Ho trovato una soluzione semplice e pulita per i 2 problemi nella domanda. Il trucco è abilitare la generazione della gerarchia a 2 livelli (in findCountours) e cercare i contorni che hanno un genitore. Ciò restituirà il contorno interno dei bordi Canny chiusi e nulla più. I bordi non chiusi vengono eliminati automaticamente e ogni indicatore avrà un contorno singolo.

vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
findContours(CannyImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0,0)); 
for (unsigned int i=0; i<contours.size(); i++) 
    if (hierarchy[i][3] >= 0) //has parent, inner (hole) contour of a closed edge (looks good) 
     drawContours(contourImage, contours, i, Scalar(255, 0, 0), 1, 8); 

Funziona anche il contrario, cioè: cerca i contorni che hanno un figlio (gerarchia [i] [2]> = 0), ma nel mio caso i risultati dei rendimenti di controllo genitore migliore.

+2

Non sono davvero d'accordo con la modifica, dato che findContours() e drawContours() non operano necessariamente sulla stessa immagine, a meno che non si voglia immediatamente eliminare il cestino contorno immagine da sovrascrivere. La modifica ha anche rimosso le informazioni che l'input di findContours() proviene da Canny(). –

1

Questo come lo farei 1. Canny per il rilevamento dei bordi 2. Utilizzare houghtransform per rilevare i bordi. 3. Rileva i due bordi che fanno un angolo di 90.

+0

Grazie, è una buona idea per i rettangoli frontali, ma sfortunatamente devo individuarli in qualsiasi orientamento. In effetti, il compito che sto svolgendo è quello di stimare l'orientamento dei marker nello spazio 3D (con i parametri della camma intrinseca noti). –

+0

È possibile utilizzare OpenSURF per qualsiasi orientamento per rilevare il marker con i modelli corrispondenti –

2

Ho avuto lo stesso problema con contorni duplicati e anche dilatano ed erodere non poteva risolverlo:

Mat src=imread("E:\\test.bmp"),gry,bin,nor,dil,erd; 
GaussianBlur(src, nor, Size(5,5),0); 
cvtColor(nor,gry,CV_BGR2GRAY); 
Canny(gry,bin,100,150,5,true); 
dilate(bin,dil,Mat()); 
erode(dil,erd,Mat()); 
Mat tmp=bin.clone(); 
vector<vector<Point>> conts; 
vector<Vec4i> hier; 
findContours(tmp,conts,hier,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE); 

Questa immagine (Test.bmp) contiene 3 contorni ma findContours restituito 6! Ho usato soglia e problema risolto:

Mat src=imread("E:\\test.bmp"),gry,bin,nor,dil,erd; 
GaussianBlur(src, nor, Size(5,5),0); 
cvtColor(nor,gry,CV_BGR2GRAY); 
threshold(gry,bin,0,255,THRESH_BINARY+THRESH_OTSU);  
vector<vector<Point>> conts; 
vector<Vec4i> hier; 
findContours(bin,conts,hier,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE); 

Ora restituisce 4 contorni quali il 1 ° uno è il confine immagine (profilo con indice 0) e possono essere facilmente ignorati.

Problemi correlati