非局部均值(NL-means)是近年来提出的一项新型的去噪技术。该方法充分利用了图像中的冗余信息,在去噪的同时能最大程度地保持图像的细节特征。基本思想是:当前像素的估计值由图像中与它具有相似邻域结构的像素加权平均得到。
理论上,该算法需要在整个图像范围内判断像素间的相似度,也就是说,每处理一个像素点时,都要计算它与图像中所有像素点间的相似度。但是考虑到效率问题,实现的时候,会设定两个固定大小的窗口:搜索窗口和邻域窗口。邻域窗口在搜索窗口中滑动,根据邻域间的相似性确定像素的权值。
下图是NL-means算法执行过程,大窗口是以目标像素为中心的搜索窗口,两个灰色小窗口分别是以、为中心的邻域窗口。其中以为中心的邻域窗口在搜索窗口中滑动,通过计算两个邻域窗口间的相似程度为赋以权值 。
NL-means执行过程
设含噪声图像为,去噪后的图像为。中像素点处的灰度值通过如下方式得到:
其中权值表示像素点和间的相似度,它的值由以、为中心的矩形邻域、间的距离决定:
其中
为归一化系数,为平滑参数,控制高斯函数的衰减程度。越大高斯函数变化越平缓,去噪水平越高,但同时也会导致图像越模糊。越小,边缘细节成分保持得越多,但会残留过多的噪声点。的具体取值应当以图像中的噪声水平为依据。
程序:
close all; clear all; clc I=double(imread('lena.tif')); I=I+10*randn(size(I)); tic O1=NLmeans(I,2,5,10); toc imshow([I,O1],[]);
function DenoisedImg=NLmeans(I,ds,Ds,h) %I:含噪声图像 %ds:邻域窗口半径 %Ds:搜索窗口半径 %h:高斯函数平滑参数 %DenoisedImg:去噪图像 I=double(I); [m,n]=size(I); DenoisedImg=zeros(m,n); PaddedImg = padarray(I,[ds,ds],'symmetric','both'); kernel=ones(2*ds+1,2*ds+1); kernel=kernel./((2*ds+1)*(2*ds+1)); h2=h*h; for i=1:m for j=1:n i1=i+ds; j1=j+ds; W1=PaddedImg(i1-ds:i1+ds,j1-ds:j1+ds);%邻域窗口1 wmax=0; average=0; sweight=0; %%搜索窗口 rmin = max(i1-Ds,ds+1); rmax = min(i1+Ds,m+ds); smin = max(j1-Ds,ds+1); smax = min(j1+Ds,n+ds); for r=rmin:rmax for s=smin:smax if(r==i1&&s==j1) continue; end W2=PaddedImg(r-ds:r+ds,s-ds:s+ds);%邻域窗口2 Dist2=sum(sum(kernel.*(W1-W2).*(W1-W2)));%邻域间距离 w=exp(-Dist2/h2); if(w>wmax) wmax=w; end sweight=sweight+w; average=average+w*PaddedImg(r,s); end end average=average+wmax*PaddedImg(i1,j1);%自身取最大权值 sweight=sweight+wmax; DenoisedImg(i,j)=average/sweight; end end
结果:
可以看出,NL-means去噪效果的确很好。但是该算法的最大缺陷就是计算复杂度太高,程序非常耗时,导致该算法不够实用。上例中256*256的lena图耗时高达33.913968s!!