三种平滑滤波器的比较(均值,中值和带方向特性的边沿保持)
在获取的原始图像中一般带有一些噪声,为了消除这些噪声,可以对图像应用一些平滑滤波器,但平滑滤波器往往又容易造成图像模糊.下面比较了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;
}