两个非均值滤波算法(NM)代码

来源:互联网 发布:电子图书数据库读秀 编辑:程序博客网 时间:2024/05/21 18:33
function DeNimg = Non_Local_Means(Nimg,PSH,WSH,Sigma)
% Non_Local_Means滤波器
%函数输入: 
%         Nimg:  输入的图像矩阵 + 带噪声的
%         PSH:  扩展窗尺寸大小
%         WSH: 窗尺寸大小
%         Sigma:方差
%函数输出: 
%         DeNimg: 重构滤波图像

if ~isa(Nimg,'double')
    Nimg = double(Nimg)/255;
end

% 图像维数
[Height,Width] = size(Nimg);
u = zeros(Height,Width); % 初始化去噪图像矩阵
M = u; % 初始化权值矩阵
Z = M; % 初始化叠加权值 accumlated weights
% 避免边界效应
PP = padarray(Nimg,[PSH,PSH],'symmetric','both');
PW = padarray(Nimg,[WSH,WSH],'symmetric','both');
% padarray使用
% A =
%      1     3     4
%      2     3     4
%      3     4     5
% B = padarray(A, 2 * [1 1], 0, 'both')
%      0     0     0     0     0     0     0
%      0     0     0     0     0     0     0
%      0     0     1     3     4     0     0
%      0     0     2     3     4     0     0
%      0     0     3     4     5     0     0
%      0     0     0     0     0     0     0
%      0     0     0     0     0     0     0
% 主循环
for dx = -WSH:WSH
    for dy = -WSH:WSH
        if dx ~= 0 || dy ~= 0
            Sd = integral_img(PP,dx,dy);  % 插值图像
            % 获取对应像素点的平方差矩阵
            SDist = Sd(PSH+1:end-PSH,PSH+1:end-PSH)+Sd(1:end-2*PSH,1:end-2*PSH)-Sd(1:end-2*PSH,PSH+1:end-PSH)-Sd(PSH+1:end-PSH,1:end-2*PSH);       
            % 计算每一个像素点的权值
            w = exp(-SDist/(2*Sigma^2));
            % 得到相应的噪声点
            v = PW((WSH+1+dx):(WSH+dx+Height),(WSH+1+dy):(WSH+dy+Width));
            % 更新去噪图像矩阵
            u = u+w.*v;
            % 更新权值去噪图像矩阵
            M = max(M,w);
            % 更新叠加权值 accumlated weights
            Z = Z+w;
        end
    end
end
% 重构图像        
f = 1;
u = u+f*M.*Nimg;
u = u./(Z+f*M);
DeNimg = u; % 重构去噪图像

function Sd = integral_img(v,dx,dy)
% 根据平方差,插值图像
% 变换计算:tx = vx+dx; ty = vy+dy
t = img_Shift(v,dx,dy);
% 平方差图像
diff = (v-t).^2;
% 沿行插值
Sd = cumsum(diff,1);  % 行叠加
% 沿列插值
Sd = cumsum(Sd,2);    % 列叠加

function t = img_Shift(v,dx,dy)
% 在xy坐标系下,进行图像变换操作
t = zeros(size(v));
type = (dx>0)*2+(dy>0);
switch type
    case 0 % dx<0,dy<0: 向右下方移动
        t(-dx+1:end,-dy+1:end) = v(1:end+dx,1:end+dy);
    case 1 % dx<0,dy>0: 向左下方移动
        t(-dx+1:end,1:end-dy) = v(1:end+dx,dy+1:end);
    case 2 % dx>0,dy<0: 向右上方移动
        t(1:end-dx,-dy+1:end) = v(dx+1:end,1:end+dy);
    case 3 % dx>0,dy>0: 向左上方移动
        t(1:end-dx,1:end-dy) = v(dx+1:end,dy+1:end);

end

参考:http://www.ilovematlab.cn/thread-449040-1-1.html

function  [output]=NLmeansfilter(input,t,f,h)                
[m n]=size(input); 
%t:搜索框半径;f:相似框半径;h:滤波频率百分比
Output=zeros(m,n);
input2 = padarray(input,[f f],'symmetric');              
 %将边缘对称折叠上去  
 % f :加宽的宽度值
 kernel = make_kernel(f);                              %计算得到一个高斯核,用于后续的计算
 kernel = kernel / sum(sum(kernel));             %sum:对矩阵k的每一列求和,k表示矩阵k的总和
 h=h*h;
 for i=1:m
 for j=1:n
         i1 = i+ f;
         j1 = j+ f;      
         W1= input2(i1-f:i1+f , j1-f:j1+f);     
         wmax=0; 
         average=0;
         sweight=0;
         rmin = max(i1-t,f+1);      %确定相似框的边长,其实可以在代入数据的时候就设置搜索框和边界框边长的大小关系,就不用求最大最小值了
         rmax = min(i1+t,m+f);      %这段主要是控制不超出索引值
         smin = max(j1-t,f+1);
         smax = min(j1+t,n+f);
         for r=rmin:1:rmax
         for s=smin:1:smax                 
                if(r==i1 && s==j1) continue; end;      
                W2= input2(r-f:r+f , s-f:s+f);                
                d = sum(sum(kernel.*(W1-W2).*(W1-W2)));
                w=exp(-d/h);                 
                if w>wmax      
                   wmax=w;                   
                end
                sweight = sweight + w;
                average = average + w*input2(r,s);                                  
         end 
         end
        average = average + wmax*input2(i1,j1);
        sweight = sweight + wmax;       
        if sweight > 0
            output(i,j) = average / sweight;
        else
            output(i,j) = input(i,j);
        end                
 end
 end    






 function [kernel] = make_kernel(f)            %这是一个高斯核   
kernel=zeros(2*f+1,2*f+1);   
for d=1:f    
  value= 1 / (2*d+1)^2 ;    
  for i=-d:d
  for j=-d:d
    kernel(f+1-i,f+1-j)= kernel(f+1-i,f+1-j) + value ;
  end
  end
end
kernel = kernel ./ f;    

参考自:http://blog.csdn.net/frankgoogle/article/details/52209901#reply

0 0
原创粉丝点击