自适应中值滤波的原理
自适应中值滤波的思想是根据噪声密度改变滤波窗口的大小,同时对噪声点和信号点采取不同的处理方法。对噪声点进行中值滤波,对信号点保持其灰度值不变。
设为fij为点(i,j)的灰度值,Sij为当前工作窗口,fmin,fmax和fmed分别为Sij中的灰度最小值、灰度最大值和灰度中值,令maxize为预设的允许最大窗口。自适应中值滤波的步骤如下:
1)若fmin< fmed <fmax,则转至第2步;否则增大窗口的尺寸。若的尺寸小于的尺寸,则重复第1步;否则输出。
2)若fmin< fij <fmax,则输出fij;否则输出fmed。
可以看出,算法中噪声的检测和认定时以fmin和fmax为基准的,如果fmin< fmed <fmax,表明fmed不是噪声,
接着根据fmin< fij <fmax,判断fij是否为噪声,当fmed与fij都不是脉冲噪声时,优先输出fij。
引入自适应中值滤波算法主要有3 个目的:
一是去除脉冲噪声;
二是平滑其他非脉冲噪声;
三是减少诸如物体边界细化或粗化等失真。
自适应中值滤波的流程图如下图所示。
参考代码:
/自适应中值滤波/int adp_media_filter(unsigned char* inbuffer,int width,int height,int maxwinsize,unsigned char* outbuffer){int pos = (maxwinsize - 1) / 2;memcpy(outbuffer,inbuffer,width*height); for (int m = pos; m < height - pos; m++)//当前中心位置(m,n){for (int n = pos; n < width - pos; n++){int curwinsize = 3;//设置初始滤波窗口大小while (curwinsize <= maxwinsize){int curpos = (curwinsize - 1) / 2;int winpos = 0;int lens = curwinsize*curwinsize;int* windows = new int[lens];for (int i = -curpos; i < curpos + 1; i++)for (int j = -curpos; j < curpos + 1; j++)windows[winpos++] = inbuffer[(m + i)*width + n + j];sort(windows, lens);int fmin = windows[0];int fmax = windows[lens - 1];int fmed = windows[(lens - 1) / 2];int A1 = fmed - fmin;int A2 = fmed - fmax;if (A1 > 0 && A2 < 0)//第一层噪声检测,fmed是不是噪声{//满足fmin< fmed < fmax,表明fmed不是噪声int B1 = inbuffer[m*width + n] - fmin;//当前窗口中心值inbuffer[m*width + n]int B2 = inbuffer[m*width + n] - fmax;//满足fmin< fmn < fmax,表明fmn不是噪声if (B1 > 0 && B2 < 0)//第二层检测,fmn是不是噪声outbuffer[m*width + n] = inbuffer[m*width + n];//fmn和fmed都不是噪声优先输出当前窗口中心值elseoutbuffer[m*width + n] = fmed;//fmn是噪声,输出中间值重新估计该点delete[] windows;windows = NULL;break;}curwinsize += 2;delete[] windows;windows = NULL;}}}//对边界进行处理,与中值滤波一样for (int k = 0;k < pos;k++)for (int l =pos;l < width-pos;l++)outbuffer[k*width+l] = outbuffer[pos*width+l];for(int a=height-pos;a < height;a++)for(int b=pos;b < width-pos;b++)outbuffer[a*width+b] = outbuffer[(height-pos-1)*width+b];for(int c = 0;c < pos;c++)for(int d=0;d < height;d++)outbuffer[d*width+c] = outbuffer[d*width+pos];for (int e = width-pos;e < width;e++)for(int f = 0;f < height;f++)outbuffer[f*width+e] = outbuffer[f*width+width-pos-1];return 0;}
实验结果:
以下所有结果均为C++处理。 1,对原图像进行处理的结果(左为原图) 可以发现,自适应中值滤波对图像边缘的保护相当好2,对乘性噪声图像进行处理的结果(左为噪声图)
注意该噪声为matlab中的乘性噪声,可以发现对乘性噪声的处理效果相当差。
3,对椒盐噪声图像进行处理的结果(左为噪声图)
注意该噪声为matlab中的椒盐噪声,可以发现对椒盐噪声的处理效果优秀。
最后在此处收录一份别人写的matlab程序:
function f = adpmedian(g, Smax)%ADPMEDIAN Perform adaptive median filtering.% F = ADPMEDIAN(G, SMAX) performs adaptive median filtering of% image G. The median filter starts at size 3-by-3 and iterates up% to size SMAX-by-SMAX. SMAX must be an odd integer greater than 1.% Copyright 2002- R. C. Gonzalez, R. E. Woods, & S. L. Eddins% Digital Image Processing Using MATLAB, Prentice-Hall, % $Revision: 1.5 $ $Date: /11/21 14:19:05 $% SMAX must be an odd, positive integer greater than 1.if (Smax <= 1) | (Smax/2 == round(Smax/2)) | (Smax ~= round(Smax))error('SMAX must be an odd integer > 1.')end[M, N] = size(g);% Initial setup.f = g;f(:) = 0;alreadyProcessed = false(size(g));% Begin filtering.for k = 3:2:Smaxzmin = ordfilt2(g, 1, ones(k, k), 'symmetric');zmax = ordfilt2(g, k * k, ones(k, k), 'symmetric');zmed = medfilt2(g, [k k], 'symmetric');processUsingLevelB = (zmed > zmin) & (zmax > zmed) & ...~alreadyProcessed; zB = (g > zmin) & (zmax > g);outputZxy = processUsingLevelB & zB;outputZmed = processUsingLevelB & ~zB;f(outputZxy) = g(outputZxy);f(outputZmed) = zmed(outputZmed);alreadyProcessed = alreadyProcessed | processUsingLevelB;if all(alreadyProcessed(:))break;endend% Output zmed for any remaining unprocessed pixels. Note that this% zmed was computed using a window of size Smax-by-Smax, which is% the final value of k in the loop.f(~alreadyProcessed) = zmed(~alreadyProcessed);