Connexions

You are here: Home » Content » Signal Processing in Processing: Filtri Elementari
Content Actions

Signal Processing in Processing: Filtri Elementari

Module by: Davide Rocchesso, Pietro Polotti

Summary: Si illustrano i filtri fondamentali per i segnali 1D e 2D e si forniscono esempi in Processing.

Filtri FIR

Si chiamano filtri Finite Impulse Response (FIR) tutti i filtri caratterizzati da una risposta all'impulso con un numero finito di campioni. Essi si realizzano mediante l'operazione di convoluzione. Cioè, per ogni campione di uscita prodotto viene calcolata una somma pesata di un numero finito di campioni dell'ingresso.

Filtro di media

Il più semplice filtro FIR non banale è il filtro che effettua la media di due campioni contigui, la cui convoluzione si può esprimere come
yn=0.5xn+0.5xn-1 y n 0.5 x n 0.5 x n 1 (1)
e quindi la risposta all'impulso ha valore 0.5 0.5 negli istanti 0 0 e 1 1, e valore nullo altrove.
Immettendo un segnale sinusoidale nel filtro, l'uscita sarà ancora un segnale sinusoidale scalato in ampiezza e ritardato in fase secondo quanto prescritto dalla risposta in frequenza, che risulta essere
Hω=cosω2-ω2 H ω ω 2 ω 2 (2)
il cui modulo e fase sono rappresentati in Figura 1.
Risposta di ampiezza e di fase per il filtro di media
fir1.png
Figura 1
Quello appena presentato è un filtro del primo ordine (e di lunghezza 2 2), in quanto utilizza un solo campione del passato della sequenza di ingresso. Da Figura 1 si vede che la risposta in frequenza è di tipo passa-basso, cioè che le alte frequenze sono attenuate rispetto alle basse frequenze. Attenuare le alte frequenze significa smussare le variazioni repentine del segnale, rendendolo così più liscio. Se si vuole una risposta in frequenza più ripida da un filtro FIR bisogna aumentare l'ordine, cioè aumentare il numero di campioni del segnale di ingresso che vengono elaborati.

Filtro FIR del secondo ordine simmetrico

Un filtro FIR del secondo ordine simmetrico ha risposta all'impulso della forma a 0 a 1 a 0 a 0 a 1 a 0 , e la risposta in frequenza risulta essere Hω= a 1 +2 a 0 cosω-ω H ω a 1 2 a 0 ω ω . La convoluzione si può esprimere come
yn= a 0 xn+ a 1 xn-1+ a 0 xn-2 y n a 0 x n a 1 x n 1 a 0 x n 2 (3)
Nel caso particolare in cui a 0 =0.17654 a 0 0.17654 e a 1 =0.64693 a 1 0.64693 la risposta in frequenza (modulo e fase) è rappresentata in Figura 2.
Risposta di ampiezza e di fase per un filtro FIR del secondo ordine
fir2.png
Figura 2

Filtri passa-alto

Per i semplici filtri passa-basso appena visti, è sufficiente cambiare il segno di un coefficiente per ottenere una risposta di tipo passa-alto, cioè una enfatizzazione delle alte frequenze rispetto alle basse frequenze. Ad esempio, la Figura 3 riporta il modulo delle risposte in frequenza di filtri FIR passa-alto rispettivamente del primo e del secondo ordine, le cui risposte all'impulso sono, rispettivamente 0.5-0.5 0.5 0.5 e 0.17654-0.646930.17654 0.17654 0.64693 0.17654 .
Risposta di ampiezza per un filtro FIR passa-alto del primo (sinistra) e del secondo (destra) ordine.
fir1hp2.pngfir2hp2.png
Subfigure 3.1
Subfigure 3.2
Figura 3
Enfatizzare le alte frequenze significa rendere più evidenti le variazioni repentine del segnale, siano esse transienti nel caso dei suoni, o contorni nel caso delle immagini.

Filtri FIR in 2D

In 2D, la risposta all'impulso di un filtro FIR è una maschera di convoluzione con un numero finito di elementi, cioè una matrice. In particolare, il filtro di media si può rappresentare mediante la maschera di convoluzione 19111111111 1 9 1 1 1 1 1 1 1 1 1 .
Esempio 1: Noise cleaning 
I filtri passa-basso (e quindi, in particolare, i filtri di media) operano uno smoothing del segnale di ingresso, cioè smussano le discontinuità producendo un segnale dal profilo più dolce. Ciò può servire a ridurre la percettibilità di un rumore sovrapposto a un segnale audio o ad una immagine. Ad esempio, il codice sotto riportato carica una immagine, la corrompe con rumore bianco, e quindi ne sottopone metà ad un filtraggio di media, ottenendo Figura 4.
Smoothing
vetroRottoSporco.gif
Figura 4
   
// smoothed_glass
// smoothing filter, adapted from REAS:
// http://www.processing.org/learning/examples/blur.html

size(210, 170); 
PImage a;  // Declare variable "a" of type PImage 
a = loadImage("vetro.jpg"); // Load the images into the program 
image(a, 0, 0); // Displays the image from point (0,0) 
 
// corrupt the central strip of the image with random noise 
float noiseAmp = 0.2;
loadPixels(); 
for(int i=0; i<height; i++) { 
  for(int j=width/4; j<width*3/4; j++) { 
    int rdm = constrain((int)(noiseAmp*random(-255, 255) + 
	      red(pixels[i*width + j])), 0, 255); 
    pixels[i*width + j] = color(rdm, rdm, rdm);
  } 
} 
updatePixels(); 
  
int n2 = 3/2; 
int m2 = 3/2; 
float  val = 1.0/9.0;
int[][] output = new int[width][height]; 
float[][] kernel = { {val, val, val}, 
                     {val, val, val}, 
                     {val, val, val} }; 
  
// Convolve the image 
for(int y=0; y<height; y++) { 
  for(int x=0; x<width/2; x++) { 
    float sum = 0; 
    for(int k=-n2; k<=n2; k++) { 
      for(int j=-m2; j<=m2; j++) { 
        // Reflect x-j to not exceed array boundary 
        int xp = x-j; 
        int yp = y-k; 
        if (xp < 0) { 
          xp = xp + width; 
        } else if (x-j >= width) { 
          xp = xp - width; 
        } 
        // Reflect y-k to not exceed array boundary 
        if (yp < 0) { 
          yp = yp + height; 
        } else if (yp >= height) { 
          yp = yp - height; 
        } 
        sum = sum + kernel[j+m2][k+n2] * red(get(xp, yp)); 
      } 
    } 
    output[x][y] = int(sum);  
  } 
} 
 
// Display the result of the convolution 
// by copying new data into the pixel buffer 
loadPixels(); 
for(int i=0; i<height; i++) { 
  for(int j=0; j<width/2; j++) { 
    pixels[i*width + j] = 
	      color(output[j][i], output[j][i], output[j][i]);
  } 
} 
updatePixels(); 
         
	
A scopo di smoothing, viene molto usata una maschera di convoluzione i cui valori sono letti da una campana gaussiana in due variabili. Più è larga la campana e più accentuato sarà l'effetto di smoothing, con conseguente perdita di dettagli. Un esempio di maschera gaussiana è 12731474141626164726412674162616414741 1 273 1 4 7 4 1 4 16 26 16 4 7 26 41 26 7 4 16 26 16 4 1 4 7 4 1 .
Se invece si vogliono rendere più evidenti i contorni e i tratti salienti (edge crispening o sharpening) di una immagine bisogna effettuare un filtraggio di tipo passa-alto. In modo analogo a quanto visto in Sezione 4 ciò si può fare con una maschera di convoluzione il cui valore centrale ha segno opposto rispetto ai valori di cui si circonda. Ad esempio, la maschera di convoluzione -1-1-1-19-1-1-1-1 -1 -1 -1 -1 9 -1 -1 -1 -1 produce l'effetto di Figura 5.
Edge crispening
vetroSharpened.gif
Figura 5

Filtraggio non lineare: filtro di mediana

Un filtro in cui la maschera di convoluzione dipende dal segnale perde le caratteristiche di linearità. I filtri di mediana usano la maschera per selezionare un insieme di pixel della immagine di ingresso, e sostituiscono il pixel centrale individuato dalla maschera con il valore mediano dell'insieme. Dato una insieme di N N (dispari) numeri, l'elemento mediano dell'insieme è quello che individua N-12 N 1 2 elementi più piccoli di sè, e N-12 N 1 2 elementi più grandi. Una tipica maschera per filtro mediano ha la forma di croce. Ad esempio, una maschera a croce 3×3 3 3 può individuare, quando applicata in un certo punto di una certa immagine, i pixel di valore x4x79912x9x x 4 x 7 99 12 x 9 x , e quindi sostituire al valore 99 99 il valore mediano 9 9.
Problem 1
Si riscriva l'operazione di filtraggio filtra() del Sound Chooser presentato nel modulo Media Representation in Processing in modo che realizzi il filtro FIR la cui risposta in frequenza è rappresentata in Figura 2. Cosa succede se il filtro viene applicato più volte?
[ Click for Solution 1 ]
Solution 1
          
 //filtra = new function
void filtra(float[] DATAF, float[] DATA, float a0, float a1) {

  for(int i = 3; i < DATA.length; i++){
    DATAF[i] = a0*DATA[i]+a1*DATA[i-1]+a0*DATA[i-2];//filtraggio FIR del secondo ordine simmetrico
  }
}
 
 	      
	    
Creando un ciclo for che reiteri l'operazione di filtraggio un certo numero di volte, si può verificare che l'effetto del filtraggio passa-basso viene accentuato. Questo risultato abbastanza intuitivo corrisponde al fatto che un filtraggio successivo attraverso m m filtri di ordine N N (nel nostro caso N=2 N 2 ) è equivalente ad un filtraggio attraverso un filtro di ordine mN m N
[ Hide Solution 1 ]
Problem 2
Considerato il codice Processing dell'esempio di blurring contenuto tra gli esempi di Processing, lo si modifichi in modo da effettuare un filtraggio gaussiano.
[ Click for Solution 2 ]
Solution 2
          
 
// smoothing Gaussian filter, adapted from REAS:
// http://www.processing.org/learning/examples/blur.html

size(200, 200); 
PImage a;  // Declare variable "a" of type PImage 
a = loadImage("vetro.jpg"); // Load the images into the program 
image(a, 0, 0); // Displays the image from point (0,0) 
 
int n2 = 5/2; 
int m2 = 5/2; 
int[][] output = new int[width][height]; 
float[][] kernel = { {1, 4, 7, 4, 1}, 
                     {4, 16, 26, 16, 4}, 
                     {7, 26, 41, 26, 7}, 
                     {4, 16, 26, 16, 4},
                     {1, 4, 7, 4, 1} }; 
 
for (int i=0; i<5; i++)
  for (int j=0; j< 5; j++)
    kernel[i][j] = kernel[i][j]/273; 
// Convolve the image 
for(int y=0; y<height; y++) { 
  for(int x=0; x<width/2; x++) { 
    float sum = 0; 
    for(int k=-n2; k<=n2; k++) { 
      for(int j=-m2; j<=m2; j++) { 
        // Reflect x-j to not exceed array boundary 
        int xp = x-j; 
        int yp = y-k; 
        if (xp < 0) { 
          xp = xp + width; 
        } else if (x-j >= width) { 
          xp = xp - width; 
        } 
        // Reflect y-k to not exceed array boundary 
        if (yp < 0) { 
          yp = yp + height; 
        } else if (yp >= height) { 
          yp = yp - height; 
        } 
        sum = sum + kernel[j+m2][k+n2] * red(get(xp, yp)); 
      } 
    } 
    output[x][y] = int(sum);  
  } 
} 
 
// Display the result of the convolution 
// by copying new data into the pixel buffer 
loadPixels(); 
for(int i=0; i<height; i++) { 
  for(int j=0; j<width/2; j++) { 
    pixels[i*width + j] = color(output[j][i], output[j][i], output[j][i]); 
  } 
} 
updatePixels(); 
 	      
	    
[ Hide Solution 2 ]
Problem 3
Si modifichi il codice di Esempio 1 in modo da confrontare la maschera di convoluzione del filtro di media con la 110111121111 1 10 1 1 1 1 2 1 1 1 1 . Cosa succede se si aumenta ancora il valore del punto centrale della maschera di convoluzione? Si provi quindi a realizzare il filtro di mediana con una maschera a croce 3×3 3 3 .
[ Click for Solution 3 ]
Solution 3
Ecco il filtro di mediana:
          
// smoothed_glass
// smoothing filter, adapted from REAS:
// http://www.processing.org/learning/examples/blur.html

size(210, 170); 
PImage a;  // Declare variable "a" of type PImage 
a = loadImage("vetro.jpg"); // Load the images into the program 
image(a, 0, 0); // Displays the image from point (0,0) 
 
// corrupt the central strip of the image with random noise 
float noiseAmp = 0.1;
loadPixels(); 
for(int i=0; i<height; i++) { 
  for(int j=width/4; j<width*3/4; j++) { 
    int rdm = constrain((int)(noiseAmp*random(-255, 255) + 
      red(pixels[i*width + j])), 0, 255); 
    pixels[i*width + j] = color(rdm, rdm, rdm);
  } 
} 
updatePixels(); 
  
int[][] output = new int[width][height]; 
int[] sortedValues = {0, 0, 0, 0, 0};
int grayVal;
  
// Convolve the image 
for(int y=0; y<height; y++) { 
  for(int x=0; x<width/2; x++) { 
    int indSort = 0;
    for(int k=-1; k<=1; k++) { 
      for(int j=-1; j<=1; j++) { 
        // Reflect x-j to not exceed array boundary 
        int xp = x-j; 
        int yp = y-k; 
        if (xp < 0) { 
          xp = xp + width; 
        } else if (x-j >= width) { 
          xp = xp - width;  
        } 
        // Reflect y-k to not exceed array boundary 
        if (yp < 0) { 
          yp = yp + height; 
        } else if (yp >= height) { 
          yp = yp - height; 
        } 
        if ((((k != j) && (k != (-j))) ) || (k == 0)) { //cross selection
          grayVal = (int)red(get(xp, yp)); 
          indSort = 0;
          while (grayVal < sortedValues[indSort]) {indSort++; }          
          for (int i=4; i>indSort; i--) sortedValues[i] = sortedValues[i-1];
          sortedValues[indSort] = grayVal;
        } 
      } 
    } 
    output[x][y] = int(sortedValues[2]);  
    for (int i=0; i< 5; i++) sortedValues[i] = 0;
  } 
} 
 
// Display the result of the convolution 
// by copying new data into the pixel buffer 
loadPixels(); 
for(int i=0; i<height; i++) { 
  for(int j=0; j<width/2; j++) { 
    pixels[i*width + j] = 
      color(output[j][i], output[j][i], output[j][i]);
  } 
} 
updatePixels(); 
          
[ Hide Solution 3 ]

Filtri IIR

L'operazione di filtraggio rappresentata dalla Equazione 1 è un caso particolare di equazione alle differenze, in cui un campione dell'uscita è funzione soltanto di campioni dell'ingresso. Più in generale, è possibile costruire equazioni alle differenze di tipo ricorsivo, in cui un campione dell'uscita è funzione di un altro campione dell'uscita stessa. Ad esempio, l'equazione alle differenze
yn=0.5yn-1+0.5xn y n 0.5 y n 1 0.5 x n (4)
consente di calcolare in maniera causale ogni campione dell'uscita conoscendo soltanto l'uscita all'istante precedente e l'ingresso allo stesso istante. E' facile rendersi conto che immettendo un impulso nel sistema rappresentato dalla Equazione 4 si ottiene la sequenza di lunghezza infinita y=0.50.250.1250.0625... y 0.5 0.25 0.125 0.0625 ... . Per questo, filtri di questo tipo si chiamano Infinite Impulse Response (IIR). L'ordine di un filtro IIR è pari al numero di campioni passati dell'uscita che esso deve memorizzare per l'uso nella sua equazione alle differenze. Quindi, quello di Equazione 4 è un filtro del primo ordine. A parità di ordine, i filtri IIR consentono risposte in frequenza più ripide di quelle dei filtri FIR, ma introducono sempre delle distorsioni di fase, cioè ritardano le componenti spettrali in maniera dipendente dalla frequenza. Ad esempio, Figura 6 riporta le risposte di ampiezza e fase per il filtro IIR del primo ordine rappresentato dalla equazione alle differenze Equazione 4.Detto a a il coefficiente che pesa la dipendenza dal valore precedente dell'uscita ( 0.5 0.5 nella specifica Equazione 4), la risposta all'impulso è del tipo hn=an h n a n . Quanto più a a si avvicina a 1 1, tanto più la risposta all'impulso si mantiene sostenuta nel tempo e la risposta in frequenza aumenta la sua ripidità, accentuando così il carattere passa-basso del filtro. Naturalmente, valori di a a maggiori di 1 1 provocano una risposta all'impulso divergente, e quindi un comportamento instabile del filtro.
Risposta di ampiezza e di fase per il filtro IIR del primo ordine
iir1resp.png
Figura 6
I filtri IIR trovano soprattutto applicazione nei segnali monodimensionali, quali sono i segnali audio, in particolare per l'elaborazione in tempo reale, campione per campione. Viceversa, non ha molto senso estendere l'elaborazione ricorsiva su due dimensioni, e quindi per le immagini si usano soprattutto filtri FIR.

Filtro risonante

In campo audio assumono particolare importanza i filtri IIR del secondo ordine in quanto consentono di realizzare un risonatore elementare. Data l'equazione alle differenze
yn= a 1 yn-1+ a 2 yn-2+ b 0 xn y n a 1 y n 1 a 2 y n 2 b 0 x n (5)
si può vedere che essa produce la risposta in frequenza di Figura 7. I coefficienti di dipendenza dal passato dell'uscita si possono anche esprimere come a 1 =2rcos ω 0 a 1 2 r ω 0 e a 2 =-r2 a 2 r 2 , dove ω 0 ω 0 è la frequenza del picco di risonanza e r r produce picchi tanto più stretti quanto più è vicino a 1 1.
Risposta di ampiezza e di fase per il filtro IIR del secondo ordine
iir2.png
Figura 7
Problem 4
Si verifichi che l'operazione di filtraggio filtra() del Sound Chooser presentato nel modulo Media Representation in Processing realizza un filtro IIR risonante. Quale è la relazione realizzata tra r r e la posizione del mouse lungo le barrette?

Comments, questions, feedback, criticisms?

Discussion forum

Send feedback