Hai mai visto un'immagine rumorosa? Intendo un'immagine che non era così chiara durante la visualizzazione? Penso che incontriamo tali immagini molto spesso, soprattutto quando oggi molte immagini vengono prese dalle nostre fotocamere dei telefoni cellulari o dalle fotocamere digitali a bassa risoluzione.
Se avessi solo quell'immagine rumorosa che significa qualcosa per te, ma il problema è che non può essere visualizzato correttamente, ci sarebbe una soluzione per recuperare da tale rumore?
È qui che entra in gioco il filtraggio delle immagini, e questo è ciò che descriverò in questo tutorial. Iniziamo!
Il filtro delle immagini è uno strumento popolare utilizzato nell'elaborazione delle immagini. Alla fine della giornata, utilizziamo il filtro delle immagini per rimuovere il rumore e qualsiasi caratteristica indesiderata da un'immagine, creando una versione migliore e migliorata di quell'immagine. Esistono due tipi di filtri: lineare e non lineare. Esempi di filtri lineari sono filtri medi e laplaciani. I filtri non lineari costituiscono filtri come i filtri mediano, minimo, massimo e Sobel.
Ciascuno di questi filtri ha uno scopo specifico ed è progettato per rimuovere il disturbo o migliorare alcuni aspetti dell'immagine. Ma come viene effettuata la filtrazione? Questo è ciò che vedremo nella prossima sezione.
Per realizzare un processo di filtraggio delle immagini, abbiamo bisogno di un filtro, chiamato anche a maschera. Questo filtro è in genere una finestra quadrata bidimensionale, ovvero una finestra con dimensioni uguali (larghezza e altezza).
Il filtro includerà numeri. Quei numeri sono chiamati coefficienti, e sono ciò che effettivamente determina l'effetto del filtro e l'aspetto dell'immagine di output. La figura seguente mostra un esempio di a 3x3
filtro, con nove valori (coefficienti).
Per applicare il filtro, il 3x3
la finestra viene spostata sull'immagine. Questo processo di scorrimento di una finestra di filtro su un'immagine viene chiamato convoluzione nel dominio spaziale. La finestra verrà posizionata su ciascun pixel (ad esempio, pensiamolo come una cella in una matrice) nell'immagine, dove il centro del filtro dovrebbe sovrapporsi a quel pixel.
Una volta avvenuta questa sovrapposizione, i pixel nell'immagine secondaria su cui si trova il filtro verranno moltiplicati con i corrispondenti coefficienti del filtro. In questo caso, avremo una nuova matrice con nuovi valori simili alla dimensione del filtro (ad es. 3x3
). Infine, il valore centrale del pixel verrà sostituito da un nuovo valore utilizzando una specifica equazione matematica a seconda del tipo di filtro utilizzato (cioè il filtro mediano).
So che il paragrafo precedente è un po 'prolisso. Facciamo un esempio per mostrare come viene applicato un filtro immagine in azione. Supponiamo di avere la seguente sottoimmagine in cui il nostro filtro si sovrappone (io
e j
fare riferimento alla posizione dei pixel nell'immagine secondaria e io
si riferisce all'immagine):
La convoluzione del nostro filtro mostrata nella prima figura con la sotto-immagine sopra apparirà come mostrato di seguito, dove I_new (i, j)
rappresenta il risultato nella posizione (I, j)
.
I_new (i, j) = v1 x I (i-1, j-1) + v2 x I (i-1, j) + v3 x I (i-1, j + 1) + v4 x I (i, j-1) + v5 x I (i, j) + v6 x I (i, j + 1) + v7 x I (i + 1, j-1) + v8 x I (i + 1, j) + v9 x I (i + 1, j + 1)
Il processo viene ripetuto per ciascun pixel dell'immagine, inclusi i pixel al contorno dell'immagine. Ma, come puoi immaginare, parte del filtro risiederà all'esterno dell'immagine quando si posiziona il filtro ai pixel limite. In questo caso, ci esibiamo imbottitura.
Questo processo significa semplicemente che inseriamo nuovi valori di pixel nell'immagine secondaria sotto la parte del filtro che viene fuori dall'immagine prima del processo di convoluzione, poiché quella parte apparentemente non contiene alcun valore di pixel. È al di fuori dell'immagine! Quei pixel imbottiti potrebbero essere zeri o un valore costante. Esistono altri metodi per impostare i valori del padding, ma questi non rientrano nell'ambito di questo tutorial.
Penso che sia abbastanza teoria per ora, quindi andiamo avanti e sporcarci le mani con la codifica! In questo tutorial, spiegherò il filtro mediano (cioè non lineare) e il filtro medio (cioè lineare) e come possiamo implementarli in Python.
Nel filtro mediano, scegliamo una finestra scorrevole che si sposterà su tutti i pixel dell'immagine. Quello che facciamo qui è che raccogliamo i valori dei pixel che rientrano nel filtro e prendiamo la mediana di quei valori. Il risultato sarà assegnato al pixel centrale.
Dì il nostro 3x3
filtro aveva i seguenti valori dopo averlo inserito su un'immagine secondaria:
Vediamo come calcolare la mediana. La mediana, nella sua essenza, è il mezzo numero di un elenco ordinato di numeri. Quindi, per trovare la mediana per il filtro sopra, ordiniamo semplicemente i numeri dal più basso al più alto, e il centro di quei numeri sarà il nostro valore mediano. Ordinamento dei valori nel nostro 3x3
finestra ci darà il seguente:
17 29 43 57 59 63 65 84 98
Per trovare il numero medio (mediana), contiamo semplicemente il numero di valori che abbiamo, aggiungiamo 1 a quel numero e dividiamo per 2. Questo ci darà la posizione del valore medio nella finestra, che è il nostro valore mediano. Quindi il valore mediano sarà nella posizione 9 + 1/2 = 5
, che è 59
. Questo valore sarà il nuovo valore del pixel al centro del nostro 3x3
finestra.
Questo tipo di filtro viene utilizzato per rimuovere il disturbo e funziona meglio con le immagini che soffrono sale e pepe rumore. L'immagine sotto mostra un esempio di un'immagine che soffre di tale rumore:
Ora, scriviamo uno script Python che applicherà il filtro mediano all'immagine sopra. Per questo esempio, useremo la libreria OpenCV. Verifica Installa OpenCV-Python in Windows e installa OpenCV 3.0 e Python 2.7+ su Ubuntu per installare OpenCV.
Per applicare il filtro mediano, utilizziamo semplicemente OpenCV cv2.medianBlur ()
funzione. Il nostro script può quindi apparire come segue:
import cv2 import argparse # crea l'argomento parser e analizza gli argomenti ap = argparse.ArgumentParser () ap.add_argument ('- i', '--image', required = True, help = 'Percorso dell'immagine di input') args = vars (ap.parse_args ()) # legge l'immagine image = cv2.imread (args ['image']) # applica il filtro mediano 3x3 sull'immagine image processed_image = cv2.medianBlur (immagine, 3) # mostra l'immagine cv2. imshow ('Elaborazione filtro mediano', processed_image) # salva l'immagine sul disco cv2.imwrite ('processed_image.png', processed_image) # mette in pausa l'esecuzione dello script fino a quando non viene premuto un tasto sulla tastiera cv2.waitKey (0)
Notare che ho usato argparse
, dato che è una buona pratica essere flessibili qui, e usare la riga di comando per passare l'immagine vogliamo applicare il filtro mediano come argomento al nostro programma.
Dopo aver passato la nostra immagine come argomento da linea di comando, leggiamo quell'immagine usando il cv2.imread ()
funzione. Applichiamo quindi il filtro mediano utilizzando il medianBlur ()
funzione, passando la nostra immagine e la dimensione del filtro come parametri. L'immagine viene visualizzata usando il cv2.imshow ()
funzione, e viene salvato sul disco usando cv2.imwrite ()
.
Il risultato dello script di cui sopra è il seguente:
Bene, cosa ne pensi? Molto bella: un'immagine bella e pulita senza rumore.
Puoi scaricare il codice sopra dal mio repository median-filter su GitHub.
Il filtro medio è un esempio di filtro lineare. Sostituisce sostanzialmente ogni pixel nell'immagine di output con il valore medio (medio) del quartiere. Questo ha l'effetto di levigare l'immagine (riducendo la quantità di variazioni di intensità tra un pixel e il prossimo), rimuovendo il rumore dall'immagine e illuminando l'immagine.
Pertanto, nel filtraggio medio, ogni pixel dell'immagine verrà sostituito con il valore medio dei suoi vicini, incluso il pixel stesso. Il 3x3
il kernel usato per il filtraggio medio è come mostrato nella figura sotto, anche se potrebbero essere utilizzate altre dimensioni del kernel (ad esempio 5x5):
Quello che il kernel precedente sta effettivamente cercando di dirci è che sommiamo tutti gli elementi sotto il kernel e prendiamo la media (media) del totale.
Un punto importante da menzionare qui è che tutti gli elementi del kernel medio dovrebbero:
Facciamo un esempio per rendere le cose più chiare. Diciamo che abbiamo la seguente immagine secondaria:
Quando applichiamo il filtro medio, faremo quanto segue:
(7 + 9 + 23 + 76 + 91 + 7 + 64 + 90 + 32) / 9 = 44
Il risultato esatto è 44.3
, ma ho arrotondato il risultato a 44
. Quindi il nuovo valore per il pixel centrale è 44
invece di 91
.
Ora alla parte di codifica. Diciamo che abbiamo la seguente immagine rumorosa:
Quello che vogliamo fare a questo punto è applicare il filtro medio sull'immagine sopra e vedere gli effetti dell'applicazione di un tale filtro.
Il codice per eseguire questa operazione è il seguente:
import cv2 import numpy come np import argparse # crea l'argomento parser e analizza gli argomenti ap = argparse.ArgumentParser () ap.add_argument ('- i', '--image', required = True, help = 'Percorso dell'input image ') args = vars (ap.parse_args ()) # leggi l'immagine image = cv2.imread (args [' image ']) # applica il filtro medio 3x3 sull'immagine kernel = np.ones ((3,3) , np.float32) / 9 processed_image = cv2.filter2D (image, -1, kernel) # display image cv2.imshow ('Mean Filter Processing', processed_image) # salva l'immagine sul disco cv2.imwrite ('processed_image.png', processed_image) # mette in pausa l'esecuzione dello script fino a quando non viene premuto un tasto sulla tastiera cv2.waitKey (0)
Si noti dal codice che abbiamo usato a 3x3
kernel per il nostro filtro medio. Abbiamo anche usato il filter2D ()
funzione per applicare il filtro medio. Il primo parametro di questa funzione è la nostra immagine di input, la seconda è la profondità desiderata dell'immagine di output ddepth
, e il terzo parametro è il nostro kernel. Assegnazione -1
per il ddepth
parametro significa che l'immagine di output avrà il stesso profondità come immagine di input.
Dopo aver eseguito il codice sulla nostra immagine rumorosa, questo è stato il risultato che ho ottenuto:
Se osservi l'immagine in uscita, possiamo vedere che è più liscia dell'immagine disturbata. Missione compiuta!
Puoi scaricare il codice sopra dal mio repository di media su GitHub.
Come abbiamo visto in questo tutorial, Python ci consente di svolgere attività avanzate come il filtro delle immagini, in particolare attraverso la sua libreria OpenCV, in modo semplice.
Inoltre, non esitare a vedere ciò che abbiamo a disposizione per la vendita e per studiare nel mercato, e non esitare a fare domande e fornire il tuo prezioso feedback utilizzando il feed qui sotto.