1.概述
在图像处理中,在进行如边缘检测这样的进一步处理之前,通常需要首先进行一定程度的降噪。中值滤波是一种非线性数字滤波器技术,经常用于去除图像或者其它信号中的噪声。这个设计思想就是检查输入信号中的采样并判断它是否代表了信号,使用奇数个采样组成的观察窗实现这项功能。观察窗口中的数值进行排序,位于观察窗中间的中值作为输出。然后,丢弃最早的值,取得新的采样,重复上面的计算过程。中值滤波是图像处理中的一个常用步骤,它对于斑点噪声和椒盐噪声来说尤其有用。保存边缘的特性使它在不希望出现边缘模糊的场合也很有用。
1.1中值滤波快速算法
很多人提出了各种中值滤波的快速算法,其共同特点是只考虑滑动窗口中移入和移出的数据,避免了传统算法中因排序所需的大量数据比较,从而较大地提高了速度。本文从另一个角度提出了一种快速算法,考虑的对象是单个滑
动窗内的像素。具体步骤如下:
(1) X考虑待处理的窗口内像素为i={X1,,Xc,,Xn},加权窗为Wi={W1,W2, Wn} X。对中心像素c进行比较,将窗口内的像素分为小于、等于和大于Xc3类[3],并加上相应权值来统计每一类的个数分别记为Left、Center和Right。把小于和大于Xc的像素分别放入数组LEFT[]和RIGHT[]。例如X3则Left=Left+W3,并加入W3个X3到数组LEFT[m]、LEFT[m+1]、直到LEFT[m+W3-1],令m=Left,取下一个像素重复以
上步骤,取完为止。
(2) 比较Left和RightX,如两者相等则中值为中心像素c。
(3) |Left-Right|若rX,则中值为中心像素c。
(4) |Left-Right|>Cente若r,则分为和Left>RightRight>Left两种情况。以Left>Right为例,X说明中值在小于c的这一类中, 即 在 数 组 LEFT[Left]中 。 计 算 差 值 △ =Left-Right-Center。表示中值就是数组LEFT[Left]中最大的△个数的中值。计算index=(△+1)/2.表示中值就是LEFT[Left]中第index
大这个数(Right>Left)情况下分析类似。
(5) 最后对LEFT[Left]或RIGHT[Right]进行局部排序,排序到第index个大小时结束。
流程图如下:
2 调试
2. 1 中值滤波快速算法
测试结果:
根据测试,处理同样一副椒盐噪声图像,与一般的中值滤波方法相比,采用3*3的滤波窗口,本文的中值滤波的快速算法在时间上大约可以缩短一半,而对于更大的滤波窗口来说,窗口越大采用本文的方法实验结果越明显。由此可见,本中值滤波在实际应用中可以更为快速的解决问题。
椒盐噪声图像滤波:
高斯图像滤波:
CCS代码:
#include
#include
#include"IMG_thr_le2min.h"
#define IMAGEWIDTH 256
#define IMAGEHEIGHT 256
#define Uint8 unsigned char
unsigned chargrey[IMAGEHEIGHT][IMAGEWIDTH];
void ReadImage(char *cFileName);
void bmpDataPart(FILE* fpbmp);
void fastmiddle();
Uint8 GetMedianLocalSort(Uint8 *array,Uint8length,Uint8 index,int type);
void main()
{
ReadImage("D:\\Administrator\\MyPictures\\Lena1.bmp");
fastmiddle();
while (1);
}
void ReadImage(char *cFileName)
{
FILE*fp;
if ( fp=fopen(cFileName,"rb" ) )
{
bmpDataPart(fp);
fclose(fp);
}
}
void bmpDataPart(FILE* fpbmp)
{
int i,j=0;
unsigned char*pix=NULL;
fseek(fpbmp, 55L,SEEK_SET);
pix=(unsignedchar*)malloc(256);
for(j=0;j
{
fread(pix,1, 256, fpbmp);
for(i=0;i
{
grey[IMAGEHEIGHT-1-j][i] =pix[i];
}
}
}
void fastmiddle()
{
inti=0,j=0;
intwheight=1,wwidth=1; //窗口大小(2*wheight+1)* (2*wwidth+1)
intk=0,l=0;
Uint8left[9],right[9],X;
Uint8leftnum=0,rightnum=0,centernum=0,index=0;
for(i=0;i
{
for(j=0;j
{
if((i>wheight-1) && (iwwidth-1) &&(j
{
X=grey[i][j];
leftnum=0;
rightnum=0;
centernum=0;
index=0;
for(k=i-wheight;k<=i+wheight;k++)
for(l=j-wwidth;l<=j+wwidth;l++)
{
if(grey[k][l]>X )
{
left[leftnum] = grey[k][l];
leftnum++;
}
else if(grey[k][l]
{
right[rightnum] =grey[k][l];
rightnum++;
}
else
centernum++;
}
if(leftnum == rightnum)
continue;//grey[i][j]=X;
else
if(abs(leftnum-rightnum)< centernum)
continue;//grey[i][j]=X;
else
if(leftnum>rightnum)
{
index=(leftnum-rightnum-centernum+1)/2;
grey[i][j]=GetMedianLocalSort(left,leftnum,index,1);
}
else
{
index=(rightnum-leftnum-centernum+1)/2;
grey[i][j]=GetMedianLocalSort(right,rightnum,index,2);
}
}
}
}
}
Uint8 GetMedianLocalSort(Uint8 *array,Uint8length,Uint8 index,int type)
{
intMedian=0,i=0,j=0;
if(type==1)
{
for(i=0;i
{
for(j=i+1;j
{
if(array[i]>array[j])
{
Median=array[i];
array[i]=array[j];
array[j]=Median;
}
}
}
returnarray[index-1];
}
if(type==2)
{
for(i=0;i
{
for(j=i+1;j
{
if(array[i]
{
Median=array[i];
array[i]=array[j];
array[j]=Median;
}
}
}
returnarray[index-1];
}
return-1;
}