2011-09-14 17 views
10

Sto lavorando a un'immagine nera & come la prima dal collegamento: http://imageshack.us/g/33/firstwm.png/ Ha un sacco di "rumore", quindi ho applicato un filtro mediano su di esso per smussarlo, ottenendo così la seconda immagine.Come si uniformano le curve (contorni) in OpenCV?

cvSmooth(TempImage, TempImage, CV_MEDIAN, 5, 0); 

Dopo questo ottengo i contorni e li disegno su un'altra immagine come la terza immagine dal collegamento. Il mio problema è che i contorni sono ancora un po 'pixelati (taglienti). C'è un modo per rendere più liscia l'immagine B & W per ottenere contorni migliori? O forse fare qualcosa con i contorni. Ho anche provato a dilatare ed erodere con kernel diversi ma il problema rimane lo stesso. Grazie per tutto ciò che aiuta.

EDIT: cercato anche:

cvSmooth(TempImage, TempImage, CV_GAUSSIAN, 9, 9, 3); 
cvThreshold(TempImage, TempImage, 127, 255, CV_THRESH_BINARY); 

stessi risultati come filtro mediano, ok, ma lascia ancora dei contorni pixel.

+1

Passando attraverso un kernel gaussiano, e poi sogliatura dovrebbe levigare i bordi. Forse questo è il risultato che vuoi? – swalog

+0

Sto supponendo che il "rumore" di cui parli sia i componenti ad alta frequenza che sembravi aver rimosso nel tuo secondo esempio. È [questo] (http://i.imgur.com/33GIT.png) un risultato desiderato? Se si desidera solo l'output binario, una [hard threshold] (http://i.imgur.com/VelRg.png) sarebbe la cosa più vicina. – swalog

+0

Sì, l'output desiderato è quello di rimuovere il rumore in modo da avere i contorni più morbidi possibili, ho provato anche la soglia Gaussiana + al tuo suggerimento, ma ho ottenuto gli stessi risultati del filtro mediano. – Adrian

risposta

8

enter image description here

Se questo è il risultato levigante che stai dopo, si può ottenere facendo una sfocatura gaussiana, seguita da una di soglia. Cioè utilizzando cvSmooth con CV_GAUSSIAN come parametro. Seguito da un cvThreshold.

Se si desidera una transizione più uniforme della soglia (come this), è possibile ottenere ciò con i livelli di regolazione (rimappando la gamma di colori in modo da conservare parte della transizione del bordo).

aggiornamento Per spiegare come ottenere il bordo liscio (anti-alias) sulla soglia, considerare cosa fa la soglia. In pratica elabora ciascun pixel dell'immagine, uno alla volta. Se il valore del pixel è inferiore alla soglia, viene impostato su nero (0), se non è impostato su bianco (255).

L'operatore di soglia è quindi molto semplice, tuttavia è possibile utilizzare qualsiasi altra funzione di mappatura generale. Fondamentalmente è una funzione f(i), dove i è il valore del pixel di intensità (compreso tra 0-255) e f(i) è il valore mappato. Per soglia di questa funzione è semplice

f(i) = { 0, for i < threshold 
      255, for i >= threshold 

Quello che hai è un'immagine levigata (da cvSmooth utilizzando un kernel gaussiano, che vi dà il "liscio" smoothing, se questo ha un senso). Quindi hai una transizione morbida dei valori sui bordi, che va da 0 a 255. Quello che vuoi fare è rendere questa transizione molto più piccola, in modo da ottenere un buon margine. Se diventi balistico, vai direttamente da 0 a 255, che è lo stesso della soglia binaria che hai già fatto.

Ora, si consideri una funzione che mappa, forse un intervallo di 4 valori di intensità (127 + - 4) nell'intervallo completo di 0-255. Cioè

  f(i) = { 0, for i < 123 
        255, for i >= 131 
     linear mapping, for 123 <= i < 131 

E si ottiene l'output desiderato. Daremo una rapida occhiata e vediamo se è già implementato in openCV. Non dovrebbe essere troppo difficile codificarlo da solo.

aggiornamento 2 La versione contorno sarebbe qualcosa di simile:

   f(i) = { 255, for  i < 122 
    linear mapping (255->0), for 122 <= i < 126 
         0, for 126 <= i < 127 
    linear mapping (0->255), for 127 <= i < 131 
         255, for 131 <= i 
+0

Oh, ora capisco cosa stai dicendo, per questo potrei usare cvLUT invece di cvThreshold. Ma ora che ci penso dopo aver applicato i cvFindContours per ottenere i contorni, tornerò al contorno di pixel :(. Grazie per la risposta comunque, se tra qualche giorno non si aprirà una risposta migliore, contrassegnerò i tuoi come corretto – Adrian

+0

Si consideri che si ha il bordo sfumato uniforme dopo l'operazione di livellamento.E 'comunque possibile ottenere un'immagine di contorno dall'aspetto piacevole usando cvLUT e i valori di tabella corretti. In breve avrebbe tre intervalli, da bianco a nero (inizio della linea) dal nero al nero (all'interno della linea) e dal nero al bianco (fine della riga) Se segue la stessa struttura di cui sopra, tutti i valori al di fuori di questo sono mappati al bianco. contorno :) – swalog

+0

Vedere l'aggiornamento 2 nella risposta. Sto anche solo indovinando i buoni valori, quindi potresti voler giocarci :) – swalog

Problemi correlati