1. 程式人生 > >數字影象處理,自適應中值濾波的C++實現

數字影象處理,自適應中值濾波的C++實現

自適應中值濾波的原理

     自適應中值濾波的思想是根據噪聲密度改變濾波視窗的大小,同時對噪聲點和訊號點採取不同的處理方法。對噪聲點進行中值濾波,對訊號點保持其灰度值不變。

       設為fij為點(i,j)的灰度值,Sij為當前工作視窗,fmin,fmax和fmed分別為Sij中的灰度最小值、灰度最大值和灰度中值,令maxize為預設的允許最大視窗。自適應中值濾波的步驟如下:

1)若 fmin< fmed <fmax,則轉至第2步;否則增大視窗的尺寸。若的尺寸小於的尺寸,則重複第1步;否則輸出。

2)若 fmin< fij <fmax,則輸出fij;否則輸出fmed

可以看出,演算法中噪聲的檢測和認定時以fminfmax為基準的,如果 fmin< fmed <fmax,表明fmed 不是噪聲,

接著根據fmin< fij <fmax判斷fij 是否為噪聲,當fmedfij 都不是脈衝噪聲時,優先輸出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;	
}

實驗結果:

以下所有結果均為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-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);


參考資源:

【1】自適應中值濾波演算法在影象處理中的應用,劉 穎,陳謹女,長安大學電子與控制工程工程學院 【2】一種改進的自適應中值濾波方法,衛保國,西北工業大學電子資訊學院,2008