快速块匹配的非局部均值去噪算法_Fast Block Matching Non local means

大家都知道,NL-means去噪算法很大的缺陷就是它的运算速度太慢,故,我采取一种快速块匹配对之进行了改进
function  [posIdx, weiIdx]   =  BM_NL_means_test(Img,par)
% Img : 输入图像
% posIdx : 与中心块相似的块的位置索引
% weiIdx : 与中心块相似的块的权重索引

search_r  =  par.s_r; %search block的半径
similarWinNum =  par.nblk; % 相似window的个数
win_r           =  par.win_r; %similarity window的半径
win=2*win_r+1;%
winSize     =  win^2; % 每个similarity window的元素个数
hp            =  par.hp^2; % 高斯参数
step=1;
%在图像四周镜面填充厚度为win_r的像素点,行数和列数增加了win(2*win_r)个
%填充的目的是为了让每一个像素都能被计算到
PaddedImg = padarray(Img,[win_r,win_r],'symmetric','both');
[R , C] = size(PaddedImg);

%  R=row+2*win_r C=col+2*win_r
N          =  R - win + 1; % 最后一个window的起始行坐标(步长1)
M          =  C - win + 1; % 最后一个window的起始列坐标
winNum   =  N * M; % window 的总个数

leftUpRow  =  1:step:N; % 每个window的行起始坐标
leftUpRow  =  [leftUpRow leftUpRow(end)+1:N]; % 添加最后一个块,因为可能最后不一定正好取完
leftUpCol  =  1:step:M; % 每个window的列起始坐标
leftUpCol  =  [leftUpCol leftUpCol(end)+1:M]; % 添加最后一个块,因为可能最后不一定正好取完


%分块:按列取一维块中不同位置的数据(连续的地址,速度可比常规提高10倍)!!!!!!
%这一小段是W dong学者BlockMatching中最精华部分!!!!
X    =  zeros(winSize, M*N, 'single');
k    =  0;
for i  = 1:win
    for j  = 1:win
        k    =  k+1;%每次取R*C个window的第k个像素值
        blk  =  PaddedImg(i:end-win+i,j:end-win+j);%这是算法精华所在噢~
        X(k,:) =  blk(:)';%每列皆是一个window的win*win个像素,共R2*C2列,完成降维
    end
end
X = X';

I      = reshape(1:winNum, N, M); % 所有块的索引
N1     = length(leftUpRow); % 多少行中心块
M1     = length(leftUpCol); % 多少列中心块中心块
posIdx = zeros(similarWinNum, N1*M1 ); % 每个中心块的相似块索引
weiIdx = zeros(similarWinNum, N1*M1 ); % 每个中心块对应的相似块的权重
%
rmin   = bsxfun(@max, bsxfun(@minus, leftUpRow, search_r), 1); % 搜索窗的行最小坐标
rmax   = bsxfun(@min, bsxfun(@plus, leftUpRow, search_r), N); % 搜索窗的行最大坐标
cmin   = bsxfun(@max, bsxfun(@minus, leftUpCol, search_r), 1); % 搜索窗的列最小坐标
cmax   = bsxfun(@min, bsxfun(@plus, leftUpCol, search_r), M); % 搜索窗的列最大坐标
%其实 经过padarry填充以及后来减去win宽度后,此处的N1,N2恰好是初始噪声图的维度一模一样的噢~(R,C)
% step=1是M1/N1是和M/N一样大的
for  i  =  1 : N1
    for  j  =  1 : M1 
        
        offInAllWin   = (leftUpCol(j)-1)*N + leftUpRow(i); % 当前中心块在所有块中的索引
        offInCentralWin  = (j-1)*N1 + i; % 当前中心块在所有中心块中的索引

        idx   = I(rmin(i):rmax(i), cmin(j):cmax(j));  %在由[rmin:rmax, cmin:cmax]确定的搜索窗中搜索相似块
        idx   = idx(:);%当前搜索框中所有块的索引

        B       =   X(idx, :);        
        v       =   X(offInAllWin, :);  
        %将搜索窗口的所有window都与当前中心window求它们间的距离
        dis     =   (B(:,1) - v(1)).^2;
        for k = 2:winSize
            dis   =  dis + (B(:,k) - v(k)).^2;
        end
        dis   = dis ./ (winSize); % 归一化
       
        similarWinInd = minN(dis, similarWinNum); % 找到距离最小的几个块的索引
        posIdx(:,offInCentralWin)  =  idx(similarWinInd); % 保存相似块索引       
        
        wei   =  exp( -dis(similarWinNum) ./ hp ); % 高斯
        weiIdx(:,offInCentralWin)  =  wei ./ (sum(wei(:))+eps); % 归一化             
    end
end

function index = minN(data, N)
% 功能 :找到 data 中最小的 N 个数,并返回索引
[~, index] = sort(data);
index = index(1:N);

 主函数

par.s_r       =5; % search window的半径
par.nblk      =35; % 用来加权和去噪的相似块的个数(当然了,也可以是search win所有块)
par.win_r     =2; % similarity window的半径
par.step=1;
par.hp       =  13.5; % 高斯平滑参数
tic
I=double(imread('taylor.jpg'));
randn('state',0);%保证每次的高斯随机白噪声是一样的随机序列
Img=I+10*randn(size(I));
[row , col] = size(Img);
[posIdx, weiIdx]=BM_NL_means_test(Img,par);
pixel_posIdx = double(Img(posIdx));
Recon_X=sum((pixel_posIdx.*weiIdx),1);
Denoising_Im=reshape(Recon_X,row,col);
toc
% figure,imshow(I/256);%原图
% figure,imshow(Img/256);%加噪声后
% figure,imshow(Denoising_Im/256);%去噪后

参考文献和资料:

1.http://see.xidian.edu.cn/faculty/wsdong/wsdong_Publication.htm 《Sparsity-based Image Denoising via Dictionary Learning and Structural》源码中find_block_fast.m

2.《A non-local algorithm for image denoising》Antoni Buades, Bartomeu Coll等人

3. http://blog.csdn.net/wenxuegeng/article/details/51476980 Non Local Means-块匹配MATLAB和GPU实现

4. http://www.cnblogs.com/luo-peng/p/4785922.html 非局部均值去噪(NL-means)

若有疑问,欢迎邮件交流~

你可能感兴趣的:(图像去噪算法改进,matlab,快速匹配,非局部均值,图像相似块匹配,图像去噪)