原文:http://blog.csdn.net/baimafujinji/article/details/73302911
有一个说法:好奇心和懒惰是推动人类发明创造的两大动力!所以今天我又再次展现了我的好奇心。何况”我的眼里为什么常含着泪水,因为我有一个算法不会。“ 为了节约一点泪水,还是应该把一些算法搞清楚。
如果说让你对一幅含有噪声的图像进行去噪,你会想到什么最原始、最简单的、教科书上就会讲到的方法。我猜或许应该是Box Filter(也称均值滤波)或者Gaussian Filter,关于Box Filter可以参考本博主之间的一篇文章(文章链接)。但是无论Box Filter还是Gaussian Filter,它们的一个共有的不足就在于对待噪声和图像的纹理细节都采用一视同仁的处理方式,结果导致噪声被去掉的同时,图像的纹理和细节也会被一同磨平。这个Side effect是我们所不想见到的!
于是,几乎所有真正有价值的图像降噪方法都在试图让程序可以自适应地区隔无用的噪声和有用的图像纹理细节,然后再采取不同的处理方式,从而实现details preserving(或者edge preserving)。而且这样的方法还特别特别多,例如比较有名的双边滤波、基于PM方程的各向异性扩散滤波,以及基于TV-norm的去噪方法等等。关于这些内容你也可以参考《图像处理中的数学修炼》一书。在实际中,这些算法都具有非常广泛而重要的用途,例如医学影像处理中常常需要利用数字图像处理的技术对X-ray或者MRI图像等进行降噪,再比如现在手机中比较popular的美颜嫩肤都要以上面提到的那些details preserving的denoise算法。但是,上面提到的那些算法动辄就要用到像偏微分方程或者欧拉-拉格朗日方程等深奥晦涩的数学知识。我们能不能从一个比较简单的方法入手来一窥details preserving的denoise算法的能力和效果呢?这个可以有!
我们引入经典教科书中都会使用的一个图像退化模型,并以此作为算法讨论的开始。如下图所示,输入待处理图像f(x,y)在退化函数H的作用下,由于受到噪声η(x,y)的影响,最终得到一个退化图像g(x,y)。图像复原的过程就是在给定g(x,y)以及关于退化函数H和加性噪声η(x,y)的一些信息后,设法估计出原始图像的近似值f̂ (x,y)。当然,我们期望最终的近似值可以最大限度地逼近原始图像。显然关于H和η的信息掌握得越多,那么最终得到的估计结果就越接近原始图像。
如果H是一个线性移不变系统,那么在时域中给出的退化过程可由如下公式给出:
当然,上面这个算法其实还有一个地方是需要我们加以应对的,那就是我们需要估计σ2g。在wiener2函数的实现过程中,具体做法是:点(x,y)处的局部均值为
这个方法看起来如此的简单,它真的能按照我们预期的那样工作吗?下面就在MATLAB中编程实现这个算法。
function [f,noise] = mywiener2(g, nhood, noise)
if (nargin<3)
noise = [];
end
% Estimate the local mean of f.
localMean = filter2(ones(nhood), g) / prod(nhood);
% Estimate of the local variance of f.
localVar = filter2(ones(nhood), g.^2) / prod(nhood) - localMean.^2;
% Estimate the noise power if necessary.
if (isempty(noise))
noise = mean2(localVar);
end
% Compute result
% f = localMean + (max(0, localVar - noise) ./ ...
% max(localVar, noise)) .* (g - localMean);
%
% Computation is split up to minimize use of memory for temp arrays.
f = g - localMean;
g = localVar - noise;
g = max(g, 0);
f = localMean + ((f ./ max(localVar, noise)) .* g);
下面来试验一下上面这个看起来只有聊聊几行的简单函数是否可以实现保持图像细节的去噪功能。下面的MATLAB代码调用了上述函数,执行下面的代码将得到本文最开始所展示出来的效果图,而且这与直接调用wiener2函数所得之结果也是完全一致的。
RGB = imread('saturn.png');
I = rgb2gray(RGB);
I = I(601:1000,1:600);
J = imnoise(I,'gaussian',0,0.005);
J = im2double(J);
K = mywiener2(J,[5 5]);
figure;
imshow(I), title('original image');
figure;
subplot(1,2,1), subimage(J), title('noised image');
subplot(1,2,2), subimage(K), title('denoised image');
更多图像处理中的数学问题请参考《图像处理中的数学修炼》,也欢迎广大读者到图像处理书籍读者群中参与讨论学习,并交流关于图像去噪算法和PDE图像处理算法的研究心得。