自适应中值滤波的原理
自适应中值滤波的思想是根据噪声密度改变滤波窗口的大小,同时对噪声点和信号点采取不同的处理方法。对噪声点进行中值滤波,对信号点保持其灰度值不变。
设为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都不是噪声优先输出当前窗口中心值 else outbuffer[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; }
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-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins % Digital Image Processing Using MATLAB, Prentice-Hall, 2004 % $Revision: 1.5 $ $Date: 2003/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:Smax zmin = 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; end end % 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);