Blur (gaussien) ?>

Blur (gaussien)

Le premier type de filtre que l’on va voir sont les filtres de « moyennage ». On se base sur le principe que l’information dans une image est redondante. On va se servir de cette redondance pour supprimer le bruit. Pour cela, on calcule la valeur d’un point après filtrage comme étant la moyenne des points de son voisinage.

Si on considère que l’on fait la moyenne sur les 9 points qui entourent le point considéré, le calcul ressemble à :

pix_res(x,y) = (pix(x-1,y-1)+pix(x,y-1)+pix(x+1,y-1)+
               pix(x-1,y  )+pix(x,y  )+pix(x+1,y  )+
               pix(x-1,y+1)+pix(x,y+1)+pix(x+1,y+1))/9.0;
 

Généralement on représente le filtre sous forme d’un masque où chaque case correspond à la valeur par laquelle il faut multiplier le point correspondant dans l’image source. Ensuite on fait la somme de toutes les multiplications et on divise par la somme des coefficients. On obtiendrait pour la moyenne le masque :

1 1 1
1 1 1
1 1 1

Et il faudra diviser le résultat par 9 (9*1).

Si on utilise cette notation c’est parce que l’on ne fait pas la moyenne qu’avec des coefficients de 1. En effet, on peut pondérer les différents points du voisinage avec des coefficients différents. Par exemple, on peut favoriser le point de l’image source sur ses voisins.

Voici un exemple de filtre avec pondération en forme de gaussienne pour éliminer les bruits dit gaussiens :

1 2 1
2 4 2
1 2 1

La somme étant alors à diviser par 16. C’est souvent ce filtre qui est utilisé pour faire du « blur ».

image avant utilisation du filtre gaussien

image avant utilisation du filtre gaussien

image après utilisation du filtre gaussien

image après utilisation du filtre gaussien

Voici le code C qui permet de réaliser ce filtre :

/**************************************************************/
 /* Fait un flou gaussien de l'image psrc et place le résultat */
 /* dans pdest. pdest et psrc doivent avoir la même taille.    */
 void image_blur(image *pdest, image *psrc)
 { int32 vx,vy;
 int i,j;
 float res_r, res_g, res_b;
 pix vpix;
 /* définition du filtre utilisé (en forme de cloche => gaussien) */
 float filter[3][3] = {{1.0,2.0,1.0},
 {2.0,4.0,2.0},
 {1.0,2.0,1.0}};
 float filter_div = 16.0;

/* si les préconditions ne sont pas remplies, on quitte */
 if((pdest == NULL) || (psrc == NULL) ||
 (psrc->width != pdest->width) || (psrc->height != pdest->height))
 return;

for(vy = 0;vy < psrc->height; vy++)
 {
 for(vx = 0;vx < psrc->width; vx++)
 {
 res_r = 0;
 res_g = 0;
 res_b = 0;
 for(j=0;j<3;j++)
 for(i=0;i<3;i++)
 {
 vpix = get_pix(psrc, vx-(3>>1)+i, vy-(3>>1)+j);
 res_r += (float)COL_RED  (vpix) * filter[j][i];
 res_g += (float)COL_GREEN(vpix) * filter[j][i];
 res_b += (float)COL_BLUE (vpix) * filter[j][i];
 }
 res_r /= filter_div;
 res_g /= filter_div;
 res_b /= filter_div;

/* on sature le résultat */
 res_r = (res_r > 255.0)? 255.0 : ((res_r < 0.0)? 0.0:res_r);
 res_g = (res_g > 255.0)? 255.0 : ((res_g < 0.0)? 0.0:res_g);
 res_b = (res_b > 255.0)? 255.0 : ((res_b < 0.0)? 0.0:res_b);

/* on place le résultat dans l'image destination */
 put_pix_alpha_replace(pdest, vx, vy, COL(
 (uint8)res_r,(uint8)res_g,(uint8)res_b));
 }
 }
 }
 /**************************************************************/
Les commentaires sont clos.