Non-Local Means 非局部均值去噪滤波

        传统的高斯滤波,均值滤波,为局部滤波,即对周围邻域的点加权生成当前点,加权因子反应出周围点对当前点的影响,这些加权因子基于某种理论获得,如高斯滤波基于低通,均值滤波认为点与点之间的影响是均匀的。

1.经典的Non-Local Means 滤波

        Non-local Means 非局部均值去噪滤波可以视为局部均值滤波的特例,它的目的是使用与当前点纹理类似的区域,对当前点加权。也即加权因子,是基于被加权点与当前点的邻域的相似性产生,即:

       其中I是一个较大范围的搜索/加权框,w(x,y)是依赖邻域【黑灰色部分】算出的权重:

Non-Local Means 非局部均值去噪滤波_第1张图片

      w(x,y)一般定义为一个与欧式距离(2范数)相关的函数,设x,y的邻域宏块的欧式距离为d,即

d=||block(x)-block(y)||/block_size

则y加权到x点的加权因子为 

  w(x,y)=exp(-(d*d/(h*h)))   

h为衰减因子,h越小,加权因子越小,则加权点对当前点的影响越小,一般边缘保持得好但是噪声会严重,反之则边缘保持差图像更加光滑。

        实际操作中,要更新当前点,先计算出以当前点为中心的搜索框I所有点的加权因子,取最大的加权因子付给当前点位置,然后对于这个同搜索框尺寸加权矩阵W进行归一化,最终当前点的结果为:

p=sum(W.*I)

        计算欧式距离时,有时会考虑周围点对中心点的影响,会利用核函数对欧式距离加权,即加权因子重写为为:

                                                                            w(x,y)=exp(-(k*d*d/(h*h)))

使用核函数对距离进行加权的matlab代码为:

clc;
clear all;
close all;

%---------------------------%
%       input
%---------------------------%
src=imread('test.jpg');
src=rgb2gray(src);
src=double(src);
figure,imshow(src,[]),title('src image')

%---------------------------%
%       parameter
%---------------------------%
[m,n]=size(src);
ds=2;% block size for calculate weight
Ds=5;% search block
h=10;% decay factor
offset=ds+Ds;
PaddedImg = padarray(src,[ds+Ds,ds+Ds],'symmetric','both');% 扩展图像,便于处理
%距离加权核

%非均值核
[x,y]=meshgrid(-ds:ds,-ds:ds);
kernel=1./(x.*x+y.*y+1);

%均值核
% kernel=ones(2*ds+1,2*ds+1);

kernel=kernel./((2*ds+1)*(2*ds+1));
dst=zeros(m,n);% output

%---------------------------%
%  Non-Local Means Denoising
%---------------------------%
for i=1:m
    for j=1:n
        
        %当前点坐标和邻域窗口
        i1=i+offset;
        j1=j+offset;
        W1=PaddedImg(i1-ds:i1+ds,j1-ds:j1+ds);
        
        %加权因子矩阵和图像
        weight=zeros(2*Ds+1,2*Ds+1);
        image=PaddedImg(i1-Ds:i1+Ds,j1-Ds:j1+Ds);

        for r=-Ds:Ds
            for s=-Ds:Ds
                
                %跳过当前点
                if(r==0&&s==0)
                    continue;
                end
                
                %待加权点坐标和邻域窗口
                i2=i1+r;
                j2=j1+s;
                W2=PaddedImg(i2-ds:i2+ds,j2-ds:j2+ds);
                
                %核加权的距离和加权因子
                distance=sum(sum(kernel.*(W1-W2).*(W1-W2)));
                weight(r+Ds+1,s+Ds+1)=exp(-distance/(h*h));
            end
        end
        
        %最大权重赋给当前点,归一化权重
        weight(Ds+1,Ds+1)=max(max(weight));
        weight=weight/(sum(weight(:)));
        
        dst(i,j)=sum(sum(image.*weight));
    end
end

%---------------------------%
%       output
%---------------------------%
figure,imshow(dst,[]),title('dst');

效果如下:

Non-Local Means 非局部均值去噪滤波_第2张图片

 

2.使用积分图加速

        假设图像共像个素点,搜索窗口大小,领域窗口大小, 计算两个矩形邻域间相似度的时间为,对于每个像素点需要计算它与搜索窗口内个像素间的相似度,故NL-means复杂度为 

        积分图加速本质是,将图像的所有点,计算某一偏离坐标点方向的权重,一次性计算出来,而不是单次计算某一点的所有偏离点。具体,计算当前图像与一定偏移后的图像的diff并平方,继而计算与原图像同等尺寸的积分图,则每一个点与偏离它在一定偏移的坐标点的距离,通过积分图就可以计算出来了。积分图的作用体现在使用线性计算,减少重复计算,即存储换时间。

Non-Local Means 非局部均值去噪滤波_第3张图片

       具体源码如下:

clc;
clear all;
close all;

%---------------------------%
%       input
%---------------------------%
src=imread('lena.jpg');
src=rgb2gray(src);
src=double(src);
figure,imshow(src,[]),title('src image')

%---------------------------%
%       parameter
%---------------------------%
[m,n]=size(src);
ds=2;% block size for calculate weight
Ds=5;% search block
h=10;% decay factor
offset=ds+Ds;
PaddedImg = padarray(src,[ds+Ds,ds+Ds],'symmetric','both');% 扩展图像,便于处理

%---------------------------%
%  Non-Local Means Denoising
%---------------------------%
sumimage=zeros(m,n);
sumweight=zeros(m,n);
maxweight=zeros(m,n);
image=PaddedImg(1+Ds:Ds+m+ds,1+Ds:Ds+n+ds);
[M,N]=size(image);
for r=-Ds:Ds
    for s=-Ds:Ds
        
        %跳过当前点偏移
        if(r==0&&s==0)
            continue;
        end
        
        %求得差值积分图
        wimage=PaddedImg(1+Ds+r:Ds+m+ds+r,1+Ds+s:Ds+n+ds+s);
        diff=image-wimage;
        diff=diff.^2;
        J=cumsum(diff,1);
        J=cumsum(J,2);
        
        %计算距离
        distance=J(M-m+1:M,N-n+1:N)+J(1:m,1:n)-J(M-m+1:M,1:n)-J(1:m,N-n+1:N);
        distance=distance/((2*ds+1).^2);
        
        %计算权重并获得单个偏移下的加权图像
        weight=exp(-distance./(h*h));
        sumimage=sumimage+weight.*wimage(ds+1:ds+m,ds+1:ds+n);
        sumweight=sumweight+weight;
        maxweight=max(maxweight,weight);
    end
end
sumimage=sumimage+maxweight.*image(ds+1:ds+m,ds+1:ds+n);
sumweight=sumweight+maxweight;
dst=sumimage./sumweight;

%---------------------------%
%       output
%---------------------------%
figure,imshow(dst,[]),title('dst');

效果如下:

Non-Local Means 非局部均值去噪滤波_第4张图片

 

 

参考:

[1]FromentJ. Parameter-Free Fast Pixelwise Non-Local Means Denoising[J]. Image ProcessingOn Line, 2014, 4: 300-326

[2] 非局部均值去噪(NL-means)

你可能感兴趣的:(图像处理算法,Non-Local,Means,非局部均值,积分图加速,图像滤波)