三种平滑滤波器的比较(均值,中值和带方向特性的边沿保持)
在获取的原始图像中一般带有一些噪声,为了消除这些噪声,可以对图像应用一些平滑滤波器,但平滑滤波器往往又容易造成图像模糊.下面比较了3种常用的平滑滤波器的平滑效果.
1. 均值滤波
原理是子图像在N*N子块中的,另检测点的灰度为块中灰度的平均值,这种方法通过把突变点的灰度分散在其相邻点中来达到平滑效果,操作起来也简单,但这样平滑往往造成图像的模糊,N选取得约大,模糊越严重.
 
2. 中值滤波
中值滤波平滑也在图像得N*N子块中操作,和均值平滑选择临近点得平均灰度值来作为检测点得灰度值不同,中值平滑使用临近点得中间灰度来作为检测点得灰度,即
f(x,y)=mid{f(1,1),f(1,2)…f(n,n)} n∈[1,N]
3. 带方向检测的边沿保持滤波
这种滤波的方法很多,其中一种是使用5个方向模板
x x x xxxxx
x x x xxxxx
x x x x x x x x xxxxx
x x x xxxxx
x x x xxxxx
统计各个模板的方差D和均值E
定义 
选择S最小的模板的D,再与正方形模板的方差D比较,选择比较小的一个模板作为象素使用的模板,另目标象素的灰度为所选用的模板灰度的均值.
这种带方向特性的模板能够保存图像的边沿,使图像线条边沿不至于因为平滑而变得模糊.但计算量比较大.
看看3种平滑的效果
原始图像 ------------------------------------------
均值滤波器平滑(3*3子块) ---------------------------------------------
中值滤波器平滑(3*3子块) --------------------------------------------
边沿保持滤波器平滑(3*3子块) ----------------------------------------------
可以看到3张图像都变得平滑了,但均值滤波模糊效果非常严重,中值滤波把比较细的线滤掉了,边沿保持滤波对边沿保持的效果比较好,根据需要选择.
下面是我的4种平滑的C代码
//----------------------在VC.NET 中编译通过. /* author:Lingch(Sboom) date:2005-1-26 subject: Smooth Filter */ bool FilterAV(unsigned char *image,int height,int width) //均值滤波器 { int i,j; unsigned char *p=(unsigned char*)malloc(height*width);
for(i=1;i<height-1;i++) { for(j=1;j<width-1;j++) { p[i*width+j]=(unsigned char)(((int)image[(i-1)*width+j-1] +(int)image[(i-1)*width+j] +(int)image[(i-1)*width+j+1] +(int)image[i*width+j-1] +(int)image[i*width+j] +(int)image[i*width+j+1] +(int)image[(i+1)*width+j-1] +(int)image[(i+1)*width+j] +(int)image[(i+1)*width+j+1])/9); } }
for(i=1;i<height-1;i++) { for(j=1;j<width-1;j++) { image[i*width+j]=p[i*width+j]; } }
free(p); return true; } //----------------------------中值滤波器 bool FilterMid(unsigned char *image,int height,int width) { int i,j,k,l; int pos; unsigned char temp; unsigned char psr[9]; unsigned char *p=(unsigned char*)malloc(height*width);
for(i=1;i<height-1;i++) { for(j=1;j<width-1;j++) { //---3*3窗口矩阵 psr[0]=image[(i-1)*width+j-1]; psr[1]=image[(i-1)*width+j]; psr[2]=image[(i-1)*width+j+1]; psr[3]=image[i*width+j-1]; psr[4]=image[i*width+j]; psr[5]=image[i*width+j+1]; psr[6]=image[(i+1)*width+j-1]; psr[7]=image[(i+1)*width+j]; psr[8]=image[(i+1)*width+j+1];
//--------选择排序 for(k=0;k<9;k++) { pos=k; for(l=k;l<9;l++) { if(psr[l]<psr[pos]) pos=l; } temp=psr[k]; psr[k]=psr[pos]; psr[pos]=temp; } //------取中值 p[i*width+j]=psr[4]; } }
for(i=1;i<height-1;i++) { for(j=1;j<width-1;j++) { image[i*width+j]=p[i*width+j]; } } free(p); return true; } //-----------------边沿保持滤波器 bool Filter5(unsigned char *image ,int height,int width) { int i,j,k,l; double av[5],av2[5]; double s; double sd[4];
unsigned char *p=(unsigned char*)malloc(height*width);
for(i=2;i<height-2;i++) { for(j=2;j<width-2;j++) { av[0]=0.0;av[1]=0.0;av[2]=0.0;av[3]=0.0;av[4]=0.0; av2[0]=0.0;av2[1]=0.0;av2[2]=0.0;av2[3]=0.0;av2[4]=0.0; av[0]=( +image[i*width+j-1] +image[i*width+j] +image[i*width+j+1] )/3; av2[0]=( +image[i*width+j-1]*image[i*width+j-1] +image[i*width+j]*image[i*width+j] +image[i*width+j+1]*image[i*width+j+1] )/3-av[0]*av[0];
av[1]=( +image[(i+1)*width+j-1] +image[i*width+j] +image[(i-1)*width+j+1] )/3; av2[1]=( +image[(i+1)*width+j-1]*image[(i+1)*width+j-1] +image[i*width+j]*image[i*width+j] +image[(i-1)*width+j+1]*image[(i-1)*width+j+1] )/3-av[1]*av[1];
av[2]=( +image[(i-1)*width+j] +image[i*width+j] +image[(i+1)*width+j] )/3; av2[2]=( +image[(i-1)*width+j]*image[(i-1)*width+j] +image[i*width+j]*image[i*width+j] +image[(i+1)*width+j]*image[(i+1)*width+j] )/3-av[2]*av[2];
av[3]=( +image[(i-1)*width+j-1] +image[i*width+j] +image[(i+1)*width+j+1] )/3; av2[3]=( +image[(i-1)*width+j-1]*image[(i-1)*width+j-1] +image[i*width+j]*image[i*width+j] +image[(i+1)*width+j+1]*image[(i+1)*width+j+1] )/3-av[3]*av[3];
av[4]=0.0;av2[4]=0.0; for(k=i-1;k<=i+1;k++) { for(l=j-1;l<=j+1;l++) { av[4]+=image[k*width+l]; av2[4]+=image[k*width+l]*image[k*width+l]; } } av[4]=av[4]/9.0; av2[4]=av2[4]/9.0-av[4]*av[4];
for(k=0;k<4;k++) sd[k]=av2[k]/av2[(k+2)%4];
l=0; for(k=0;k<4;k++) if(sd[k]<sd[l]) l=k;
if(av2[l]<av[4]) p[i*width+j]=av[l]; else p[i*width+j]=av[4]; } }
for(i=0;i<height;i++) for(j=0;j<width;j++) image[i*width+j]=p[i*width+j];
free(p); return true; } 
|