数字图像处理,自适应维纳滤波的C++实现

以下为来自Matlab的基本原理

wiener2

2-D adaptive noise-removal filtering

The syntax wiener2(I,[m n],[mblock nblock],noise) has been removed. Use the wiener2(I,[m n],noise) syntax instead.

Syntax

J = wiener2(I,[m n],noise)
[J,noise] = wiener2(I,[m n])

Description

wiener2 lowpass-filters a grayscale image that has been degraded by constant power additive noise. wiener2 uses a pixelwise adaptive Wiener method based on statistics estimated from a local neighborhood of each pixel.

J = wiener2(I,[m n],noise) filters the image I using pixelwise adaptive Wiener filtering, using neighborhoods of size m-by-n to estimate the local image mean and standard deviation. If you omit the [m n] argument, m and n default to 3. The additive noise (Gaussian white noise) power is assumed to be noise.

[J,noise] = wiener2(I,[m n]) also estimates the additive noise power before doing the filtering. wiener2 returns this estimate in noise.

Class Support

The input image I is a two-dimensional image of class uint8uint16int16single, or double. The output image J is of the same size and class as I.

Examples

For an example, see Remove Noise By Adaptive Filtering.

More About

collapse all

Algorithms

wiener2 estimates the local mean and variance around each pixel.

and

where  is the N-by-M local neighborhood of each pixel in the image Awiener2 then creates a pixelwise Wiener filter using these estimates,

where ν2 is the noise variance. If the noise variance is not given, wiener2 uses the average of all the local estimated variances.

References

[1] Lim, Jae S., Two-Dimensional Signal and Image Processing, Englewood Cliffs, NJ, Prentice Hall, 1990, p. 548, equations 9.26, 9.27, and 9.29.

See Also

filter2 | medfilt2


代码实现

1,算法流程:


2,Matlab代码实现:

简化版本:
function [f,noise] = adpwiener2(g,nhood)
noise = [];
g = im2double(g);

% 计算均值
localMean = filter2(ones(nhood), g) / prod(nhood);

% 计算方差
localVar = filter2(ones(nhood), g.^2) / prod(nhood) - localMean.^2;

% 如果需要,计算噪声能量
if (isempty(noise))
  noise = mean2(localVar);
end

% 计算结果
% f = localMean + (max(0, localVar - noise) ./ ...
%           max(localVar, noise)) .* (g - localMean); 
f = g - localMean;
g = localVar - noise; 
g = max(g, 0);
localVar = max(localVar, noise);
f = f ./ localVar;
f = f .* g;
f = f + localMean;


3,C++代码实现

处理结果与matlab库函数一模一样。
//对应matlab中的filter2,但是此处功能多了一些
double filter2(
	double* srcbuffer,
	int width,
	int height,
	int kernelsize,
	double* dstbuffer1,
	double* dstbuffer2
	)
{
	//kernel的中心位置
	int center_pos = kernelsize / 2;
	int i, j;
	double sumvar = 0.0;
	for (i = 0; i < height; ++i)    // 行
	{
		for (j = 0; j < width; ++j)    // 列
		{
			for (int m = 0; m < kernelsize; ++m)     // kernel行
			{
				int mm = kernelsize - 1 - m;      // 核的行索引

				for (int n = 0; n < kernelsize; ++n) // kernel列
				{
					int nn = kernelsize - 1 - n;  // 核的列索引
					// 输入图像信号的索引,用于检查边界
					int ii = i + (m - center_pos);
					int jj = j + (n - center_pos);
					// 忽视越界
					if (ii >= 0 && ii < height && jj >= 0 && jj < width)
					{
						dstbuffer1[i*width + j] += srcbuffer[ii*width + jj] / (kernelsize*kernelsize);
						dstbuffer2[i*width + j] += srcbuffer[ii*width + jj] * srcbuffer[ii*width + jj] / (kernelsize*kernelsize);
					}
				}
			}
			dstbuffer2[i*width + j] -= dstbuffer1[i*width + j] * dstbuffer1[i*width + j];
			sumvar += dstbuffer2[i*width + j];
		}
	}
	return sumvar / (width*height);//求取noise
}


void adpwiener2(
	unsigned char* inbuffer,
	int kernelsize,
	int width,
	int height,
	unsigned char* outbuffer
	)
{
	double len = 1.0*kernelsize*kernelsize;
	double* srcbuffer = new double[width*height];//对应matlab中的g
	double* localMeanArr = new double[width*height];//对应matlab中的localMean,以下同理
	double* localVarArr = new double[width*height];
	double* dstbuffer = new double[width*height];
	//初始化
	for (int i = 0; i < width*height; i++)
		localVarArr[i] = localMeanArr[i] = 0.0;
	for (int i = 0; i < width*height; i++)
		srcbuffer[i] = double(inbuffer[i]);

	double noise = filter2(srcbuffer, width, height, kernelsize, localMeanArr, localVarArr);

	for (int i = 0; i < width*height; i++)
	{
		dstbuffer[i] = srcbuffer[i] - localMeanArr[i];//f = g - localMean;
		srcbuffer[i] = localVarArr[i] - noise;//g = localVar - noise; 
		if (srcbuffer[i] < 0.0)//g = max(g, 0);
			srcbuffer[i] = 0.0;
		localVarArr[i] = max(localVarArr[i], noise);//localVar = max(localVar, noise);
		dstbuffer[i] = dstbuffer[i] / localVarArr[i] * srcbuffer[i] + localMeanArr[i];//f = f ./ localVar.*+localMean;
		outbuffer[i] = unsigned char(dstbuffer[i]);//转换成图像数据
	}

	delete[] srcbuffer;
	srcbuffer = NULL;
	delete[] localMeanArr;
	localMeanArr = NULL;
	delete[] localVarArr;
	localVarArr = NULL;
	delete[] dstbuffer;
	dstbuffer = NULL;
}




4,实验效果:

对原图处理结果,注意是5*5的窗口

数字图像处理,自适应维纳滤波的C++实现_第1张图片 数字图像处理,自适应维纳滤波的C++实现_第2张图片


对椒盐噪声处理结果,注意是5*5的窗口,结果较差
数字图像处理,自适应维纳滤波的C++实现_第3张图片 数字图像处理,自适应维纳滤波的C++实现_第4张图片

对高斯噪声的处理结果,注意是5*5的窗口,结果较优
数字图像处理,自适应维纳滤波的C++实现_第5张图片数字图像处理,自适应维纳滤波的C++实现_第6张图片

参考文献:

【1】Lim, Jae S. Two-Dimensional Signal and Image Processing. Englewood Cliffs, NJ: Prentice Hall, 1990. pp. 536-540.


你可能感兴趣的:(图像处理算法,图像处理算法)