2012-04-20 15 views
7

Attualmente sto lavorando al progetto di elaborazione delle immagini. Sto usando Opencv2.3.1 con VC++. Ho scritto il codice in modo tale che l'immagine di input sia filtrata solo per il colore blu e convertita in un'immagine binaria. L'immagine binaria ha alcuni piccoli oggetti che non voglio. Volevo eliminare quegli oggetti piccoli, quindi ho usato il metodo cvFindContours() di openCV per rilevare i contorni nell'immagine binaria. ma il problema è che non posso eliminare i piccoli oggetti nell'output dell'immagine. Ho usato la funzione cvContourArea(), ma non ha funzionato correttamente .., anche la funzione di erosione non funzionava correttamente.Profili opencv: Come eliminare i contorni piccoli in un'immagine binaria

Quindi, per favore qualcuno mi aiuti con questo problema ..

L'immagine binaria che ho ottenuto:

enter image description here

L'immagine risultato/output che voglio di ottenere:

enter image description here

risposta

1

Sei sicuro che il filtro per area di contorno ridotta non ha funzionato? Ha sempre funzionato per me. Possiamo vedere il tuo codice?

Inoltre, come citato in giudizio, è una buona idea utilizzare entrambi i metodi di erosione e dilatazione per conservare approssimativamente l'area. Per rimuovere piccoli bit rumorosi, utilizzare prima l'erode e per riempire i fori, utilizzare prima la dilatazione.

E un'altra parte, si consiglia di controllare le nuove versioni dei cv * funzioni C++, se non erano a conoscenza di loro già (documentation per findContours). Sono molto più facili da usare, a mio parere.

+0

Grazie per il suggerimento, ma non riesco a capire come scrivere il codice per trovare l'area di ogni blob/contorno che è stata rilevata. Il codice che ho scritto è nel seguente link. Per favore, correggilo e rispondi. : http://textuploader.com/?p=6&id=YwRl. –

+0

oh! Ho appena dimenticato, l'header e il file cpp per cvutility possono essere trovati in questi link: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Si prega di includerli in directory di origine e percorsi di inclusione. –

+0

Non ho molta familiarità con la C api, ma sembra che tu stia solo calcolando l'area del primo contorno. È necessario scorrere i contorni e disegnare solo quelli con area> qualche soglia. Se stai solo cercando di trovare quell'oggetto, dovresti disegnare il contorno con l'area più grande. – fferen

0

A giudicare dalle immagini prima e dopo, è necessario determinare l'area di tutte le aree o blocchi blob, quindi applicare un valore dell'area di soglia. Ciò eliminerebbe tutte le aree meno del valore e lascerebbe solo la grande regione bianca che si vede nella seconda immagine. Dopo aver utilizzato la funzione cvFindContours, prova a utilizzare 0 momenti dell'ordine. Ciò restituirebbe l'area dei BLOB nell'immagine. Questo collegamento potrebbe essere utile per implementare ciò che ho appena descritto. http://www.aishack.in/2010/07/tracking-colored-objects-in-opencv/

+0

Grazie per il suggerimento, ma non riesco a capire come scrivere il codice per trovare l'area di ogni blob/contorno che è stata rilevata. –

+0

Grazie per il suggerimento, ma non riesco a capire come scrivere il codice per trovare l'area di ogni blob/contorno che è stata rilevata. Il codice che ho scritto è nel seguente link. Per favore, correggilo e rispondi. : http://textuploader.com/?p=6&id=YwRl. –

+0

oh! Ho appena dimenticato, l'header e il file cpp per cvutility possono essere trovati in questi link: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Si prega di includerli in directory di origine e percorsi di inclusione. –

10

Ok, credo che il problema potrebbe essere risolto con the bounding box demo recentemente introdotta da OpenCV.

enter image description here

Come avrete probabilmente notato, l'oggetto che vi interessa al dovrebbe essere all'interno del più grande rettangolo di disegnare in figura. Fortunatamente, questo codice non è molto complesso e sono sicuro che puoi capire tutto studiando e sperimentando con esso.

+0

thnx .. lo controllerò. –

7

Ecco la mia soluzione per eliminare i piccoli contorni. L'idea di base è controllare la lunghezza/area per ciascun contorno, quindi eliminare quella più piccola dal contenitore vettoriale.

otterrete normalmente contorni simili

Mat canny_output; //example from OpenCV Tutorial 
vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
Canny(src_img, canny_output, thresh, thresh*2, 3);//with or without, explained later. 
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0)); 

Con Canny() pre-elaborazione, si otterrà segmenti di contorno, tuttavia ciascun segmento viene memorizzato con i pixel di contorno come un anello chiuso.In questo caso, è possibile controllare la lunghezza ed eliminare il piccolo uno come

for (vector<vector<Point> >::iterator it = contours.begin(); it!=contours.end();) 
{ 
    if (it->size()<contour_length_threshold) 
     it=contours.erase(it); 
    else 
     ++it; 
} 

Senza Canny() pre-elaborazione, si otterrà i contorni degli oggetti. somiglianza, si può anche utilizzare un'area per definire una soglia per eliminare piccoli oggetti, come OpenCV esercitazione mostrato

vector<Point> contour = contours[i]; 
double area0 = contourArea(contour); 

questo contourArea() è il numero di pixel non nulle

0

Credo che si può utilizzare morfologica operatori come erode e dilate (leggi di più here)

È necessario eseguire l'erosione con una dimensione del kernel vicino al raggio del cerchio a destra (quello che si desidera eliminare). seguito da una dilatazione che utilizza lo stesso kernel per riempire gli spazi creati dalla fase di erosione.

L'erosione di FYI seguita dalla dilatazione utilizzando lo stesso kernel si chiama apertura.

il codice sarà qualcosa di simile

int erosion_size = 30; // adjust with you application 
Mat erode_element = getStructuringElement(MORPH_ELLIPSE, 
         Size(2*erosion_size + 1, 2*erosion_size+1), 
         Point(erosion_size, erosion_size)); 
erode(binary_img, binary_img, erode_element); 
dilate(binary_img, binary_img, erode_element); 
0

E non è un modo veloce, ma può essere utile in alcuni casi. C'è una nuova funzione in OpencCV 3.0 - connectedComponentsWithStats. Con esso possiamo ottenere l'area dei componenti collegati ed eliminare inutili. Quindi possiamo rimuovere facilmente il cerchio con i fori, con lo stesso riquadro di delimitazione del cerchio solido.

Problemi correlati