非局部均值(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!!