Matrici e filtri di convoluzione
10 January 2009 da Francesco
Per matrice di convoluzione si intende una matrice che viene applicata ad un’immagine per ottenere una seconda immagine con caratteristiche particolari. I filtri di convoluzione sono appunto quei filtri, presenti in quasi tutti i programmi di grafica, che modificano l’immagine imprimendogli alcuni effetti come per esempio la sfocatura (blur), una maggiore definizione (sharpen), etc… quasi tutti questi filtri fanno uso di matrici di convoluzione, e vedremo come creare un semplice programma in C++ che, data un’immagine in input ed una matrice di convoluzione produca l’immagine di output.
Sebbene le matrici di convoluzione, chiamate anche “kernel“, possano essere di qualsiasi dimensione, le piu’ usate sono quelle 5×5 e 3x3. In questo articolo prenderemo in considerazione solo le seconde, che sono sufficienti a creare una grande varieta’ di effetti. La matrice va applicata separatamente ad ogni canale dell’immagine (R, G, B) nel seguente modo. Supponiamo di operare esclusivamente sul canale R, visto che le operazioni sono analoghe agli altri canali, e di avere pixel con i valori indicati nella matrice a sinistra a cui vogliamo applicare la matrice di convoluzione presente a destra:
|
|
Il pixel evidenziato in rosso e’ quello su cui stiamo lavorando in questo momento, mentre la matrice a destra e’ il nostro kernel. Per applicare il filtro di convoluzione sul pixel dobbiamo immaginare di sovrapporre l’elemento centrale della matrice kernel con il pixel che stiamo considerando e di fare la somma di tutti i prodotti degli elementi sovrapposti. In poche parole dobbiamo moltiplicare gli elementi corrispondenti tra le due matrici e sommare tutti i risultati. Notate che non stiamo effettuando una normale moltiplicazione tra matrici (cioe’ un prodotto riga per colonna)!
Nel nostro caso il calcolo e’:
255*0 + 180*0 + 100*0 + 125*0 + 175*1 + 150*0 + 0*0 + 123*0 + 20*0 == 175
La matrice di convoluzione che abbiamo scelto, potrebbe essere paragonata alla matrice identita’ nel caso di un prodotto tra matrici. Come la matrice identita’ non cambia il risultato, cosi’ questa matrice fornisce come risultato lo stesso pixel e quindi l’immagine di output rimane invariata. Ovviamente questo e’ un caso particolare, e alla fine dell’articolo vedremo alcuni degli effetti prodotti da altre matrici particolari.
Comunque, quando la matrice di convoluzione viene applicata a tutti i pixel dell’immagine il lavoro e’ terminato ed abbiamo ottenuto la nostra immagine modificata. Vediamo alcune parti del codice in C++ che trovate allegato alla fine dell’articolo. Ah, il codice fa uso, come al solito, delle librerie EasyBMP per la gestione delle BMP.
int mat[DIM][DIM];
typedef struct pixel {
int red, green, blue;
};
Creiamo una matrice DIMxDIM (dove DIM = 3 nel nostro caso), che sara’ la nostra matrice di convoluzione, e creiamo un nostro tipo per descrivere i pixels. Dopo aver fatto inserire all’utente i 9 valori degli elementi della matrice, possiamo iniziare i calcoli. Nelle righe 38-56 (non le scrivo qua perche’ vengono formattate male) svolgiamo i calcoli veri e propri. Gli indici i e j sono le coordinate x e y del pixel che stiamo esaminando; notate che escludiamo i pixel appartenenti al bordo esterno dell’immagine semplicemente perche’ non hanno 8 pixel confinanti come tutti gli altri, e quindi verrebbe piu’ difficile applicare la matrice perche’ dovremmo escludere alcuni pixel dal conteggio; il risultato non cambia di molto.
I nuovi valori dei pixel vengono salvati in un array di oggetti pixel (il typedef che abbiamo definito poco piu’ su). Quello che ci manca è riportare questi valori in un intervallo 0…255. Sappiamo infatti che 255 e’ il valore massimo per ogni componente di un pixel, ma dall’applicazione del nostro filtro, potremmo avere (e’ spesso e’ cosi’) valori che superano questa soglia. Per fare cio’ calcoliamo la somma di tutti gli elementi della matrice di convoluzione e dividiamo tutti i valori di output per questa somma. Se dopo questa operazione ci saranno ulteriori valori > 255, li imposteremo uguali a 255, cosi’ come imposteremo a 0 quelli < 0.
Vediamo un esempio:
![]() |
MATRICE DI CONVOLUZIONE 0 -1 0 -1 4 -1 0 -1 0 |
![]() |
In questo esempio, e’ stata applicata all’immagine una matrice per individuare i bordi (edge detection). Le immagini sono piuttosto pesanti essendo BMP e quindi non compresse.
Su Internet si trovano facilmente altre matrici di convoluzione associate a risultati particolari. Ecco il codice del programma. Alla prossima.
Tags: C++, filtri convoluzione, image processing, matrici convoluzione
Pubblicato in Informatica | Commenti (0)
No comments yet


