├── BM3D ├── BM3D-SAPCA │ ├── BM3DSAPCA2009.p │ ├── README-BM3D-SAPCA.txt │ ├── demo_BM3DSAPCA.m │ ├── function_AnisLPAICI8.p │ ├── function_CreateLPAKernels.m │ ├── function_LPAKernelMatrixTheta.m │ ├── function_WOSFilters.p │ └── function_Window2D.m ├── BM3D.m ├── BM3DDEB.m ├── BM3DSHARP.m ├── BM3D_CFA.m ├── CBM3D.m ├── CVBM3D.m ├── ClipComp16b.p ├── IDDBM3D │ ├── BM3DDEB_init.m │ ├── BlockMatch.mexw32 │ ├── BlockMatch.mexw64 │ ├── Demo_IDDBM3D.m │ ├── GroupProcessor.mexw32 │ ├── GroupProcessor.mexw64 │ └── IDDBM3D.p ├── LEGAL_NOTICE.txt ├── README.txt ├── VBM3D.m ├── bm3d_CFA_thr.mexa64 ├── bm3d_CFA_thr.mexglx ├── bm3d_CFA_thr.mexmaci64 ├── bm3d_CFA_thr.mexw32 ├── bm3d_CFA_thr.mexw64 ├── bm3d_CFA_wiener.mexa64 ├── bm3d_CFA_wiener.mexglx ├── bm3d_CFA_wiener.mexmaci64 ├── bm3d_CFA_wiener.mexw32 ├── bm3d_CFA_wiener.mexw64 ├── bm3d_thr.mexa64 ├── bm3d_thr.mexglx ├── bm3d_thr.mexmaci ├── bm3d_thr.mexmaci64 ├── bm3d_thr.mexw32 ├── bm3d_thr.mexw64 ├── bm3d_thr_color.mexa64 ├── bm3d_thr_color.mexglx ├── bm3d_thr_color.mexmaci ├── bm3d_thr_color.mexmaci64 ├── bm3d_thr_color.mexw32 ├── bm3d_thr_color.mexw64 ├── bm3d_thr_colored_noise.mexa64 ├── bm3d_thr_colored_noise.mexglx ├── bm3d_thr_colored_noise.mexmaci ├── bm3d_thr_colored_noise.mexmaci64 ├── bm3d_thr_colored_noise.mexw32 ├── bm3d_thr_colored_noise.mexw64 ├── bm3d_thr_sharpen_var.mexa64 ├── bm3d_thr_sharpen_var.mexglx ├── bm3d_thr_sharpen_var.mexmaci ├── bm3d_thr_sharpen_var.mexmaci64 ├── bm3d_thr_sharpen_var.mexw32 ├── bm3d_thr_sharpen_var.mexw64 ├── bm3d_thr_video.mexa64 ├── bm3d_thr_video.mexglx ├── bm3d_thr_video.mexmaci ├── bm3d_thr_video.mexmaci64 ├── bm3d_thr_video.mexw32 ├── bm3d_thr_video.mexw64 ├── bm3d_thr_video_c.mexw32 ├── bm3d_thr_video_c.mexw64 ├── bm3d_wiener.mexa64 ├── bm3d_wiener.mexglx ├── bm3d_wiener.mexmaci ├── bm3d_wiener.mexmaci64 ├── bm3d_wiener.mexw32 ├── bm3d_wiener.mexw64 ├── bm3d_wiener_color.mexa64 ├── bm3d_wiener_color.mexglx ├── bm3d_wiener_color.mexmaci ├── bm3d_wiener_color.mexmaci64 ├── bm3d_wiener_color.mexw32 ├── bm3d_wiener_color.mexw64 ├── bm3d_wiener_colored_noise.mexa64 ├── bm3d_wiener_colored_noise.mexglx ├── bm3d_wiener_colored_noise.mexmaci ├── bm3d_wiener_colored_noise.mexmaci64 ├── bm3d_wiener_colored_noise.mexw32 ├── bm3d_wiener_colored_noise.mexw64 ├── bm3d_wiener_video.mexa64 ├── bm3d_wiener_video.mexglx ├── bm3d_wiener_video.mexmaci ├── bm3d_wiener_video.mexmaci64 ├── bm3d_wiener_video.mexw32 ├── bm3d_wiener_video.mexw64 ├── bm3d_wiener_video_c.mexw32 └── bm3d_wiener_video_c.mexw64 ├── Bilateral Filtering advanced ├── 3096.jpg ├── Main_BFad.m ├── methods │ ├── bfilter2.m │ ├── fun_Joint_bfilter2.p │ └── jbfilter2.m └── result │ ├── Joint_bfilter2_out.png │ ├── bfilter2_out.png │ └── re.png ├── Bilateral Filtering ├── 3096.jpg ├── Main_BF.m ├── Thumbs.db └── bfilter2.m ├── Guided Filtering ├── 3096.jpg ├── Main_filter.m ├── boxfilter.m └── guidedfilter.m ├── LMS自适应算法滤波器 ├── LMSwanmei1.m └── LMSwanmei2.m ├── Mean && Median Filtle ├── 3096.jpg ├── compute_mean_median.m └── main.m ├── NL-means-C++ ├── .DS_Store ├── A non-local algorithm for image denoising.pdf ├── main.cpp └── pic │ ├── .DS_Store │ └── screenshot.png ├── PM └── denoisePM.m ├── TVdenoising └── TV去噪模型2 │ ├── Barbara500.bmp │ ├── In.mat │ ├── TV1.m │ ├── div.m │ ├── mae.m │ ├── minmod.m │ ├── pepper.bmp │ ├── psnr.m │ ├── snr.m │ └── test.m ├── Wiener Filtering ├── 3096.jpg ├── Main_wiener.asv └── Main_wiener.m └── 形态学滤波 ├── 3096.jpg ├── Main_filter.m ├── w_ColorRecons_CO.m └── w_recons_CO.m /BM3D/BM3D-SAPCA/BM3DSAPCA2009.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/BM3D-SAPCA/BM3DSAPCA2009.p -------------------------------------------------------------------------------- /BM3D/BM3D-SAPCA/README-BM3D-SAPCA.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------- 2 | 3 | BM3D-SAPCA : BM3D with Shape-Adaptive Principal Component Analysis 4 | v1.00, 2009 5 | 6 | -------------------------------------------------------------------- 7 | 8 | Copyright (c) 2009-2011 Tampere University of Technology. 9 | All rights reserved. 10 | This work should be used for nonprofit purposes only. 11 | 12 | Author: Alessandro Foi 13 | 14 | BM3D web page: http://www.cs.tut.fi/~foi/GCF-BM3D 15 | 16 | 17 | 18 | BM3D-SAPCA is an algorithm for attenuation of additive white 19 | Gaussian noise (AWGN) from grayscale images. 20 | 21 | 22 | This software package reproduces the results from the article: 23 | 24 | K. Dabov, A. Foi, V. Katkovnik, and K. Egiazarian, 25 | "BM3D Image Denoising with Shape-Adaptive Principal 26 | Component Analysis", Proc. Workshop on Signal Processing 27 | with Adaptive Sparse Structured Representations (SPARS'09), 28 | Saint-Malo, France, April 2009. 29 | 30 | ( PDF available at http://www.cs.tut.fi/~foi/GCF-BM3D ) 31 | 32 | 33 | -------------------------------------------------------------------- 34 | 35 | This demo package includes routines from both the 36 | LASIP 2D demobox (http://www.cs.tut.fi/~lasip/2D/) and the 37 | Pointwise SA-DCT demobox (http://www.cs.tut.fi/~foi/SA-DCT/). 38 | 39 | -------------------------------------------------------------------- 40 | 41 | 42 | 43 | -------------------------------------------------------------------- 44 | Disclaimer 45 | -------------------------------------------------------------------- 46 | 47 | Any unauthorized use of these routines for industrial or profit- 48 | oriented activities is expressively prohibited. By downloading 49 | and/or using any of these files, you implicitly agree to all the 50 | terms of the TUT limited license, as specified in the document 51 | Legal_Notice.txt (included in this package) and online at 52 | http://www.cs.tut.fi/~foi/GCF-BM3D/legal_notice.html 53 | 54 | -------------------------------------------------------------------------------- /BM3D/BM3D-SAPCA/demo_BM3DSAPCA.m: -------------------------------------------------------------------------------- 1 | % BM3D-SAPCA : BM3D with Shape-Adaptive Principal Component Analysis (v1.00, 2009) 2 | % (demo script) 3 | % 4 | % BM3D-SAPCA is an algorithm for attenuation of additive white Gaussian noise (AWGN) 5 | % from grayscale images. This algorithm reproduces the results from the article: 6 | % K. Dabov, A. Foi, V. Katkovnik, and K. Egiazarian, "BM3D Image Denoising with 7 | % Shape-Adaptive Principal Component Analysis", Proc. Workshop on Signal Processing 8 | % with Adaptive Sparse Structured Representations (SPARS'09), Saint-Malo, France, 9 | % April 2009. (PDF available at http://www.cs.tut.fi/~foi/GCF-BM3D ) 10 | % 11 | % 12 | % SYNTAX: 13 | % 14 | % y_est = BM3DSAPCA2009(z, sigma) 15 | % 16 | % where z is an image corrupted by AWGN with noise standard deviation sigma 17 | % and y_est is an estimate of the noise-free image. 18 | % Signals are assumed on the intensity range [0,1]. 19 | % 20 | % 21 | % USAGE EXAMPLE: 22 | % 23 | % y = im2double(imread('Cameraman256.png')); 24 | % sigma=25/255; 25 | % z=y+sigma*randn(size(y)); 26 | % y_est = BM3DSAPCA2009(z,sigma); 27 | % 28 | % 29 | % 30 | % Copyright (c) 2009-2011 Tampere University of Technology. All rights reserved. 31 | % This work should only be used for nonprofit purposes. 32 | % 33 | % author: Alessandro Foi, email: firstname.lastname@tut.fi 34 | % 35 | %% 36 | 37 | clear all 38 | 39 | y = im2double(imread('Cameraman256.png')); 40 | % y = im2double(imread('Lena512.png')); 41 | randn('seed',0); 42 | 43 | sigma=25/255; 44 | z=y+sigma*randn(size(y)); 45 | 46 | y_est = BM3DSAPCA2009(z,sigma); 47 | 48 | PSNR = 10*log10(1/mean((y(:)-y_est(:)).^2)); 49 | disp(['PSNR = ',num2str(PSNR)]) 50 | if exist('ssim_index') 51 | [mssim ssim_map] = ssim_index(y*255, y_est*255); 52 | disp(['SSIM = ',num2str(mssim)]) 53 | end 54 | 55 | -------------------------------------------------------------------------------- /BM3D/BM3D-SAPCA/function_AnisLPAICI8.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/BM3D-SAPCA/function_AnisLPAICI8.p -------------------------------------------------------------------------------- /BM3D/BM3D-SAPCA/function_CreateLPAKernels.m: -------------------------------------------------------------------------------- 1 | % Creates LPA kernels cell array (function_CreateLPAKernels) 2 | % 3 | % Alessandro Foi - Tampere University of Technology - 2003-2005 4 | % --------------------------------------------------------------- 5 | % 6 | % Builds kernels cell arrays kernels{direction,size} 7 | % and kernels_higher_order{direction,size,1:2} 8 | % kernels_higher_order{direction,size,1} is the 3D matrix 9 | % of all kernels for that particular direction/size 10 | % kernels_higher_order{direction,size,2} is the 2D matrix 11 | % containing the orders indices for the kernels 12 | % contained in kernels_higher_order{direction,size,1} 13 | % 14 | % --------------------------------------------------------------------- 15 | % 16 | % kernels_higher_order{direction,size,1}(:,:,1) is the funcion estimate kernel 17 | % kernels_higher_order{direction,size,1}(:,:,2) is a first derivative estimate kernel 18 | % 19 | % kernels_higher_order{direction,size,1}(:,:,n) is a higher order derivative estimate kernel 20 | % whose orders with respect to x and y are specified in 21 | % kernels_higher_order{direction,size,2}(n,:)= 22 | % =[xorder yorder xorder+yorder] 23 | % 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | 26 | function [kernels, kernels_higher_order]=function_createLPAkernels(m,h1,h2,TYPE,window_type,directional_resolution,sig_winds,beta) 27 | 28 | %-------------------------------------------------------------------------- 29 | % LPA ORDER AND KERNELS SIZES 30 | %-------------------------------------------------------------------------- 31 | % m=[2,0]; % THE VECTOR ORDER OF LPA; 32 | 33 | % h1=[1 2 3 4 5]; % sizes of the kernel 34 | % h2=[1 2 3 4 5]; % row vectors h1 and h2 need to have the same lenght 35 | 36 | 37 | %-------------------------------------------------------------------------- 38 | % WINDOWS PARAMETERS 39 | %-------------------------------------------------------------------------- 40 | % sig_winds=[h1*1 ; h1*1]; % Gaussian parameter 41 | % beta=1; % Parameter of window 6 42 | 43 | % window_type=1 ; % window_type=1 for uniform, window_type=2 for Gaussian 44 | % window_type=6 for exponentions with beta 45 | % window_type=8 for Interpolation 46 | 47 | % TYPE=00; % TYPE IS A SYMMETRY OF THE WINDOW 48 | % 00 SYMMETRIC 49 | % 10 NONSYMMETRIC ON X1 and SYMMETRIC ON X2 50 | % 11 NONSYMMETRIC ON X1,X2 (Quadrants) 51 | % 52 | % for rotated directional kernels the method that is used for rotation can be specified by adding 53 | % a binary digit in front of these types, as follows: 54 | % 55 | % 10 56 | % 11 ARE "STANDARD" USING NN (Nearest Neighb.) (you can think of these numbers with a 0 in front) 57 | % 00 58 | % 59 | % 110 60 | % 111 ARE EXACT SAMPLING OF THE EXACT ROTATED KERNEL 61 | % 100 62 | % 63 | % 210 64 | % 211 ARE WITH BILINEAR INTERP 65 | % 200 66 | % 67 | % 310 68 | % 311 ARE WITH BICUBIC INTERP (not reccomended) 69 | % 300 70 | 71 | %-------------------------------------------------------------------------- 72 | % DIRECTIONAL PARAMETERS 73 | %-------------------------------------------------------------------------- 74 | % directional_resolution=4; % number of directions 75 | 76 | 77 | 78 | 79 | 80 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 81 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 82 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 83 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84 | %%%%% From this point onwards this file and the create_LPA_kernels.m should be identical %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 85 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | lenh=max(length(h1),length(h2)); 96 | clear kernels 97 | clear kernels_higher_order 98 | kernels=cell(directional_resolution,lenh); 99 | kernels_higher_order=cell(directional_resolution,lenh,2); 100 | THETASTEP=2*pi/directional_resolution; 101 | THETA=[0:THETASTEP:2*pi-THETASTEP]; 102 | 103 | 104 | s1=0; 105 | for theta=THETA, 106 | s1=s1+1; 107 | for s=1:lenh, 108 | 109 | 110 | [gh,gh1,gh1degrees]=function_LPAKernelMatrixTheta(ceil(h2(s)),ceil(h1(s)),window_type,[sig_winds(1,s) sig_winds(2,s)],TYPE,theta, m); 111 | kernels{s1,s}=gh; % degree=0 kernel 112 | kernels_higher_order{s1,s,1}=gh1; % degree>=0 kernels 113 | kernels_higher_order{s1,s,2}=gh1degrees; % polynomial indexes matrix 114 | 115 | end % different lengths loop 116 | end % different directions loop 117 | 118 | -------------------------------------------------------------------------------- /BM3D/BM3D-SAPCA/function_LPAKernelMatrixTheta.m: -------------------------------------------------------------------------------- 1 | % Return the discrete kernels for LPA estimation and their degrees matrix 2 | % 3 | % function [G, G1, index_polynomials]=function_LPAKernelMatrixTheta(h2,h1,window_type,sig_wind,TYPE,theta, m) 4 | % 5 | % 6 | % Outputs: 7 | % 8 | % G kernel for function estimation 9 | % G1 kernels for function and derivative estimation 10 | % G1(:,:,j), j=1 for function estimation, j=2 for d/dx, j=3 for d/dy, 11 | % contains 0 and all higher order kernels (sorted by degree: 12 | % 1 x y y^2 x^3 x^2y xy^2 y^3 etc...) 13 | % index_polynomials matrix of degrees first column x powers, second 14 | % column y powers, third column total degree 15 | % 16 | % 17 | % Inputs: 18 | % 19 | % h2, h1 size of the kernel (size of the "asymmetrical portion") 20 | % m=[m(1) m(2)] the vector order of the LPA any order combination should work 21 | % "theta" is an angle of the directrd window 22 | % "TYPE" is a type of the window support 23 | % "sig_wind" - vector - sigma parameters of the Gaussian wind 24 | % "beta"- parameter of the power in some weights for the window function 25 | % (these last 3 parameters are fed into function_Window2D function) 26 | % 27 | % 28 | % Alessandro Foi, 6 march 2004 29 | 30 | function [G, G1, index_polynomials]=function_LPAKernelMatrixTheta(h2,h1,window_type,sig_wind,TYPE,theta, m) 31 | global beta 32 | 33 | %G1=0; 34 | m(1)=min(h1,m(1)); 35 | m(2)=min(h2,m(2)); 36 | 37 | % builds ordered matrix of the monomes powers 38 | number_of_polynomials=(min(m)+1)*(max(m)-min(m)+1)+(min(m)+1)*min(m)/2; % =size(index_polynomials,1) 39 | index_polynomials=zeros(number_of_polynomials,2); 40 | index3=1; 41 | for index1=1:min(m)+1 42 | for index2=1:max(m)+2-index1 43 | index_polynomials(index3,:)=[index1-1,index2-1]; 44 | index3=index3+1; 45 | end 46 | end 47 | if m(1)>m(2) 48 | index_polynomials=fliplr(index_polynomials); 49 | end 50 | index_polynomials(:,3)=index_polynomials(:,1)+index_polynomials(:,2); %calculates degrees of polynomials 51 | index_polynomials=sortrows(sortrows(index_polynomials,2),3); %sorts polynomials by degree (x first) 52 | 53 | %===================================================================================================================================== 54 | 55 | halfH=max(h1,h2); 56 | H=-halfH+1:halfH-1; 57 | 58 | 59 | % creates window function and then rotates it 60 | % win_fun=zeros(halfH-1,halfH-1); 61 | for x1=H 62 | for x2=H 63 | if TYPE==00|TYPE==200|TYPE==300 % SYMMETRIC WINDOW 64 | win_fun1(x2+halfH,x1+halfH)=function_Window2D(x1/h1/(1-1000*eps),x2/h2/(1-1000*eps),window_type,sig_wind,beta,h2/h1); % weight 65 | end 66 | if TYPE==11|TYPE==211|TYPE==311 % NONSYMMETRIC ON X1,X2 WINDOW 67 | win_fun1(x2+halfH,x1+halfH)=(x1>=-0.05)*(x2>=-0.05)*function_Window2D(x1/h1/(1-1000*eps),x2/h2/(1-1000*eps),window_type,sig_wind,beta,h2/h1); % weight 68 | end 69 | if TYPE==10|TYPE==210|TYPE==310 % NONSYMMETRIC ON X1 WINDOW 70 | win_fun1(x2+halfH,x1+halfH)=(x1>=-0.05)*function_Window2D(x1/h1/(1-1000*eps),x2/h2/(1-1000*eps),window_type,sig_wind,beta,h2/h1); % weight 71 | end 72 | 73 | if TYPE==100|TYPE==110|TYPE==111 % exact sampling 74 | xt1=x1*cos(-theta)+x2*sin(-theta); 75 | xt2=x2*cos(-theta)-x1*sin(-theta); 76 | if TYPE==100 % SYMMETRIC WINDOW 77 | win_fun1(x2+halfH,x1+halfH)=function_Window2D(xt1/h1/(1-1000*eps),xt2/h2/(1-1000*eps),window_type,sig_wind,beta,h2/h1); % weight 78 | end 79 | if TYPE==111 % NONSYMMETRIC ON X1,X2 WINDOW 80 | 81 | win_fun1(x2+halfH,x1+halfH)=(xt1>=-0.05)*(xt2>=-0.05)*function_Window2D(xt1/h1/(1-1000*eps),xt2/h2/(1-1000*eps),window_type,sig_wind,beta,h2/h1); % weight 82 | end 83 | if TYPE==110 % NONSYMMETRIC ON X1 WINDOW 84 | 85 | win_fun1(x2+halfH,x1+halfH)=(xt1>=-0.05)*function_Window2D(xt1/h1/(1-1000*eps),xt2/h2/(1-1000*eps),window_type,sig_wind,beta,h2/h1); % weight 86 | end 87 | end 88 | 89 | end 90 | end 91 | win_fun=win_fun1; 92 | if (theta~=0)&(TYPE<100) 93 | win_fun=imrotate(win_fun1,theta*180/pi,'nearest'); % use 'nearest' or 'bilinear' for different interpolation schemes ('bicubic'...?) 94 | end 95 | if (theta~=0)&(TYPE>=200)&(TYPE<300) 96 | win_fun=imrotate(win_fun1,theta*180/pi,'bilinear'); % use 'nearest' or 'bilinear' for different interpolation schemes ('bicubic'...?) 97 | end 98 | if (theta~=0)&(TYPE>=300) 99 | win_fun=imrotate(win_fun1,theta*180/pi,'bicubic'); % use 'nearest' or 'bilinear' for different interpolation schemes ('bicubic'...?) 100 | end 101 | 102 | 103 | 104 | % make the weight support a square 105 | win_fun2=zeros(max(size(win_fun))); 106 | win_fun2((max(size(win_fun))-size(win_fun,1))/2+1:max(size(win_fun))-((max(size(win_fun))-size(win_fun,1))/2),(max(size(win_fun))-size(win_fun,2))/2+1:max(size(win_fun))-((max(size(win_fun))-size(win_fun,2))/2))=win_fun; 107 | win_fun=win_fun2; 108 | 109 | 110 | %===================================================================================================================================== 111 | 112 | 113 | %%%% rotated coordinates 114 | H=-(size(win_fun,1)-1)/2:(size(win_fun,1)-1)/2; 115 | halfH=(size(win_fun,1)+1)/2; 116 | h_radious=halfH; 117 | Hcos=H*cos(theta); Hsin=H*sin(theta); 118 | 119 | 120 | %%%% Calculation of FI matrix 121 | FI=zeros(number_of_polynomials); 122 | i1=0; 123 | for s1=H 124 | i1=i1+1; 125 | i2=0; 126 | for s2=H 127 | i2=i2+1; 128 | x1=Hcos(s1+h_radious)-Hsin(s2+h_radious); 129 | x2=Hsin(s1+h_radious)+Hcos(s2+h_radious); 130 | phi=sqrt(win_fun(s2+halfH,s1+halfH))*(prod(((ones(number_of_polynomials,1)*[x1 x2]).^index_polynomials(:,1:2)),2)./prod(gamma(index_polynomials(:,1:2)+1),2).*(-ones(number_of_polynomials,1)).^index_polynomials(:,3)); 131 | FI=FI+phi*phi'; 132 | end % end of s2 133 | end % end of s1 134 | 135 | %FI_inv=((FI+1*eps*eye(size(FI)))^(-1)); % invert FI matrix 136 | FI_inv=pinv(FI); % invert FI matrix (using pseudoinverse) 137 | G1=zeros([size(H,2) size(H,2) number_of_polynomials]); 138 | 139 | %%%% Calculation of mask 140 | i1=0; 141 | for s1=H 142 | i1=i1+1; 143 | i2=0; 144 | for s2=H 145 | i2=i2+1; 146 | x1=Hcos(s1+h_radious)-Hsin(s2+h_radious); 147 | x2=Hsin(s1+h_radious)+Hcos(s2+h_radious); 148 | phi=FI_inv*win_fun(s2+halfH,s1+halfH)*(prod(((ones(number_of_polynomials,1)*[x1 x2]).^index_polynomials(:,1:2)),2)./prod(gamma(index_polynomials(:,1:2)+1),2).*(-ones(number_of_polynomials,1)).^index_polynomials(:,3)); 149 | G(i2,i1,1)=phi(1); % Function Est 150 | G1(i2,i1,:)=phi(:)'; % Function est & Der est on X Y etc... 151 | end % end of s1 152 | end % end of s2 153 | %keyboard -------------------------------------------------------------------------------- /BM3D/BM3D-SAPCA/function_WOSFilters.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/BM3D-SAPCA/function_WOSFilters.p -------------------------------------------------------------------------------- /BM3D/BM3D-SAPCA/function_Window2D.m: -------------------------------------------------------------------------------- 1 | % Returns a scalar/matrix weights (window function) for the LPA estimates 2 | % function w=function_Window2D(X,Y,window,sig_wind, beta); 3 | % X,Y scalar/matrix variables 4 | % window - type of the window weight 5 | % sig_wind - std scaling for the Gaussian ro-weight 6 | % beta -parameter of the degree in the weights 7 | %---------------------------------------------------------------------------------- 8 | % V. Katkovnik & A. Foi - Tampere University of Technology - 2002-2005 9 | 10 | 11 | function w=function_Window2D(X,Y,window,sig_wind, beta,ratio); 12 | 13 | if nargin == 5 14 | ratio=1; 15 | end 16 | 17 | IND=(abs(X)<=1)&(abs(Y)<=1); 18 | IND2=((X.^2+Y.^2)<=1); 19 | IND3=((X.^2+(Y*ratio).^2)<=1); 20 | 21 | 22 | if window==1 % rectangular symmetric window 23 | w=IND; end 24 | 25 | if window==2 %Gaussian 26 | 27 | X=X/sig_wind(1); 28 | Y=Y/sig_wind(2); 29 | w = IND.*exp(-(X.^2 + Y.^2)/2); %*(abs(Y)<=0.1*abs(X));%.*IND2; %((X.^2+Y.^2)<=1); 30 | end 31 | 32 | if window==3 % Quadratic window 33 | w=(1-(X.^2+Y.^2)).*((X.^2+Y.^2)<=1); end 34 | 35 | if window==4 % triangular symmetric window 36 | w=(1-abs(X)).*(1-abs(Y)).*((X.^2+Y.^2)<=1); end 37 | 38 | 39 | if window==5 % Epanechnikov symmetric window 40 | w=(1-X.^2).*(1-Y.^2).*((X.^2+Y.^2)<=1); 41 | end 42 | 43 | if window==6 % Generalized Gaussian 44 | 45 | X=X/sig_wind; 46 | Y=Y/sig_wind; 47 | w = exp(-((X.^2 + Y.^2).^beta)/2).*((X.^2+Y.^2)<=1); end 48 | 49 | 50 | if window==7 51 | 52 | X=X/sig_wind; 53 | Y=Y/sig_wind; 54 | w = exp(-abs(X) - abs(Y)).*IND; end 55 | 56 | if window==8 % Interpolation 57 | 58 | w=(1./(abs(X).^4+abs(Y).^4+0.0001)).*IND2; 59 | end 60 | 61 | if window==9 % Interpolation 62 | 63 | NORM=(abs(X)).^2+(abs(Y)).^2+0.0001; 64 | w=(1./NORM.*(1-sqrt(NORM)).^2).*(NORM<=1); 65 | end 66 | 67 | if window==10 68 | w=((X.^2+Y.^2)<=1); 69 | end 70 | 71 | 72 | if window==11 73 | 74 | temp=asin(Y./sqrt(X.^2+Y.^2+eps)); 75 | temp=temp*0.6; % Width of Beam 76 | temp=(temp>0)*min(temp,1)+(temp<=0)*max(temp,-1); 77 | 78 | w=max(0,IND.*cos(pi*temp)); 79 | 80 | 81 | end 82 | 83 | 84 | 85 | if window==111 86 | 87 | temp=asin(Y./sqrt(X.^2+Y.^2+eps)); 88 | temp=temp*0.8; % Width of Beam 89 | temp=(temp>0)*min(temp,1)+(temp<=0)*max(temp,-1); 90 | 91 | w=max(0,IND3.*(cos(pi*temp)>0)); 92 | % w=((X.^2+Y.^2)<=1); 93 | end 94 | 95 | if window==112 96 | 97 | temp=atan(Y/(X+eps)); 98 | %temp=temp*0.8; % Width of Beam 99 | %temp=(temp>0)*min(temp,1)+(temp<=0)*max(temp,-1); 100 | w=max(0,IND3.*((abs(temp))<=pi/4)); 101 | % w=((X.^2+Y.^2)<=1); 102 | 103 | end 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /BM3D/BM3D.m: -------------------------------------------------------------------------------- 1 | function [PSNR, y_est] = BM3D(y, z, sigma, profile, print_to_screen) 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % 4 | % BM3D is an algorithm for attenuation of additive white Gaussian noise from 5 | % grayscale images. This algorithm reproduces the results from the article: 6 | % 7 | % [1] K. Dabov, A. Foi, V. Katkovnik, and K. Egiazarian, "Image Denoising 8 | % by Sparse 3D Transform-Domain Collaborative Filtering," 9 | % IEEE Transactions on Image Processing, vol. 16, no. 8, August, 2007. 10 | % preprint at http://www.cs.tut.fi/~foi/GCF-BM3D. 11 | % 12 | % 13 | % FUNCTION INTERFACE: 14 | % 15 | % [PSNR, y_est] = BM3D(y, z, sigma, profile, print_to_screen) 16 | % 17 | % ! The function can work without any of the input arguments, 18 | % in which case, the internal default ones are used ! 19 | % 20 | % BASIC USAGE EXAMPLES: 21 | % 22 | % Case 1) Using the default parameters (i.e., image name, sigma, etc.) 23 | % 24 | % [PSNR, y_est] = BM3D; 25 | % 26 | % Case 2) Using an external noisy image: 27 | % 28 | % % Read a grayscale image and scale its intensities in range [0,1] 29 | % y = im2double(imread('Cameraman256.png')); 30 | % % Generate the same seed used in the experimental results of [1] 31 | % randn('seed', 0); 32 | % % Standard deviation of the noise --- corresponding to intensity 33 | % % range [0,255], despite that the input was scaled in [0,1] 34 | % sigma = 25; 35 | % % Add the AWGN with zero mean and standard deviation 'sigma' 36 | % z = y + (sigma/255)*randn(size(y)); 37 | % % Denoise 'z'. The denoised image is 'y_est', and 'NA = 1' because 38 | % % the true image was not provided 39 | % [NA, y_est] = BM3D(1, z, sigma); 40 | % % Compute the putput PSNR 41 | % PSNR = 10*log10(1/mean((y(:)-y_est(:)).^2)) 42 | % % show the noisy image 'z' and the denoised 'y_est' 43 | % figure; imshow(z); 44 | % figure; imshow(y_est); 45 | % 46 | % Case 3) If the original image y is provided as the first input 47 | % argument, then some additional information is printed (PSNRs, 48 | % figures, etc.). That is, "[NA, y_est] = BM3D(1, z, sigma);" in the 49 | % above code should be replaced with: 50 | % 51 | % [PSNR, y_est] = BM3D(y, z, sigma); 52 | % 53 | % 54 | % INPUT ARGUMENTS (OPTIONAL): 55 | % 56 | % 1) y (matrix M x N): Noise-free image (needed for computing PSNR), 57 | % replace with the scalar 1 if not available. 58 | % 2) z (matrix M x N): Noisy image (intensities in range [0,1] or [0,255]) 59 | % 3) sigma (double) : Std. dev. of the noise (corresponding to intensities 60 | % in range [0,255] even if the range of z is [0,1]) 61 | % 4) profile (char) : 'np' --> Normal Profile 62 | % 'lc' --> Fast Profile 63 | % 5) print_to_screen : 0 --> do not print output information (and do 64 | % not plot figures) 65 | % 1 --> print information and plot figures 66 | % 67 | % OUTPUTS: 68 | % 1) PSNR (double) : Output PSNR (dB), only if the original 69 | % image is available, otherwise PSNR = 0 70 | % 2) y_est (matrix M x N): Final estimate (in the range [0,1]) 71 | % 72 | % 73 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 | % 75 | % Copyright (c) 2006-2011 Tampere University of Technology. 76 | % All rights reserved. 77 | % This work should only be used for nonprofit purposes. 78 | % 79 | % AUTHORS: 80 | % Kostadin Dabov, email: dabov _at_ cs.tut.fi 81 | % 82 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 83 | 84 | 85 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 86 | %%%% In case, a noisy image z is not provided, then use the filename 87 | %%%% below to read an original image (might contain path also). Later, 88 | %%%% artificial AWGN noise is added and this noisy image is processed 89 | %%%% by the BM3D. 90 | %%%% 91 | image_name = [ 92 | % 'montage.png' 93 | 'Cameraman256.png' 94 | % 'boat.png' 95 | % 'Lena512.png' 96 | % 'house.png' 97 | % 'barbara.png' 98 | % 'peppers256.png' 99 | % 'fingerprint.png' 100 | % 'couple.png' 101 | % 'hill.png' 102 | % 'man.png' 103 | ]; 104 | 105 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 106 | %%%% Quality/complexity trade-off profile selection 107 | %%%% 108 | %%%% 'np' --> Normal Profile (balanced quality) 109 | %%%% 'lc' --> Low Complexity Profile (fast, lower quality) 110 | %%%% 111 | %%%% 'high' --> High Profile (high quality, not documented in [1]) 112 | %%%% 113 | %%%% 'vn' --> This profile is automatically enabled for high noise 114 | %%%% when sigma > 40 115 | %%%% 116 | %%%% 'vn_old' --> This is the old 'vn' profile that was used in [1]. 117 | %%%% It gives inferior results than 'vn' in most cases. 118 | %%%% 119 | if (exist('profile') ~= 1) 120 | profile = 'np'; %% default profile 121 | end 122 | 123 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 124 | %%%% Specify the std. dev. of the corrupting noise 125 | %%%% 126 | if (exist('sigma') ~= 1), 127 | sigma = 25; %% default standard deviation of the AWGN 128 | end 129 | 130 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 131 | %%%% Following are the parameters for the Normal Profile. 132 | %%%% 133 | 134 | %%%% Select transforms ('dct', 'dst', 'hadamard', or anything that is listed by 'help wfilters'): 135 | transform_2D_HT_name = 'bior1.5'; %% transform used for the HT filt. of size N1 x N1 136 | transform_2D_Wiener_name = 'dct'; %% transform used for the Wiener filt. of size N1_wiener x N1_wiener 137 | transform_3rd_dim_name = 'haar'; %% transform used in the 3-rd dim, the same for HT and Wiener filt. 138 | 139 | %%%% Hard-thresholding (HT) parameters: 140 | N1 = 8; %% N1 x N1 is the block size used for the hard-thresholding (HT) filtering 141 | Nstep = 3; %% sliding step to process every next reference block 142 | N2 = 16; %% maximum number of similar blocks (maximum size of the 3rd dimension of a 3D array) 143 | Ns = 39; %% length of the side of the search neighborhood for full-search block-matching (BM), must be odd 144 | tau_match = 3000;%% threshold for the block-distance (d-distance) 145 | lambda_thr2D = 0; %% threshold parameter for the coarse initial denoising used in the d-distance measure 146 | lambda_thr3D = 2.7; %% threshold parameter for the hard-thresholding in 3D transform domain 147 | beta = 2.0; %% parameter of the 2D Kaiser window used in the reconstruction 148 | 149 | %%%% Wiener filtering parameters: 150 | N1_wiener = 8; 151 | Nstep_wiener = 3; 152 | N2_wiener = 32; 153 | Ns_wiener = 39; 154 | tau_match_wiener = 400; 155 | beta_wiener = 2.0; 156 | 157 | %%%% Block-matching parameters: 158 | stepFS = 1; %% step that forces to switch to full-search BM, "1" implies always full-search 159 | smallLN = 'not used in np'; %% if stepFS > 1, then this specifies the size of the small local search neighb. 160 | stepFSW = 1; 161 | smallLNW = 'not used in np'; 162 | thrToIncStep = 8; % if the number of non-zero coefficients after HT is less than thrToIncStep, 163 | % than the sliding step to the next reference block is incresed to (nm1-1) 164 | 165 | if strcmp(profile, 'lc') == 1, 166 | 167 | Nstep = 6; 168 | Ns = 25; 169 | Nstep_wiener = 5; 170 | N2_wiener = 16; 171 | Ns_wiener = 25; 172 | 173 | thrToIncStep = 3; 174 | smallLN = 3; 175 | stepFS = 6*Nstep; 176 | smallLNW = 2; 177 | stepFSW = 5*Nstep_wiener; 178 | 179 | end 180 | 181 | % Profile 'vn' was proposed in 182 | % Y. Hou, C. Zhao, D. Yang, and Y. Cheng, 'Comment on "Image Denoising by Sparse 3D Transform-Domain 183 | % Collaborative Filtering"', accepted for publication, IEEE Trans. on Image Processing, July, 2010. 184 | % as a better alternative to that initially proposed in [1] (which is currently in profile 'vn_old') 185 | if (strcmp(profile, 'vn') == 1) | (sigma > 40), 186 | 187 | N2 = 32; 188 | Nstep = 4; 189 | 190 | N1_wiener = 11; 191 | Nstep_wiener = 6; 192 | 193 | lambda_thr3D = 2.8; 194 | thrToIncStep = 3; 195 | tau_match_wiener = 3500; 196 | tau_match = 25000; 197 | 198 | Ns_wiener = 39; 199 | 200 | end 201 | 202 | % The 'vn_old' profile corresponds to the original parameters for strong noise proposed in [1]. 203 | if (strcmp(profile, 'vn_old') == 1) & (sigma > 40), 204 | 205 | transform_2D_HT_name = 'dct'; 206 | 207 | N1 = 12; 208 | Nstep = 4; 209 | 210 | N1_wiener = 11; 211 | Nstep_wiener = 6; 212 | 213 | lambda_thr3D = 2.8; 214 | lambda_thr2D = 2.0; 215 | thrToIncStep = 3; 216 | tau_match_wiener = 3500; 217 | tau_match = 5000; 218 | 219 | Ns_wiener = 39; 220 | 221 | end 222 | 223 | decLevel = 0; %% dec. levels of the dyadic wavelet 2D transform for blocks (0 means full decomposition, higher values decrease the dec. number) 224 | thr_mask = ones(N1); %% N1xN1 mask of threshold scaling coeff. --- by default there is no scaling, however the use of different thresholds for different wavelet decompoistion subbands can be done with this matrix 225 | 226 | if strcmp(profile, 'high') == 1, %% this profile is not documented in [1] 227 | 228 | decLevel = 1; 229 | Nstep = 2; 230 | Nstep_wiener = 2; 231 | lambda_thr3D = 2.5; 232 | vMask = ones(N1,1); vMask((end/4+1):end/2)= 1.01; vMask((end/2+1):end) = 1.07; %% this allows to have different threhsolds for the finest and next-to-the-finest subbands 233 | thr_mask = vMask * vMask'; 234 | beta = 2.5; 235 | beta_wiener = 1.5; 236 | 237 | end 238 | 239 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 240 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 241 | %%%% Note: touch below this point only if you know what you are doing! 242 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 243 | 244 | %%% Check whether to dump information to the screen or remain silent 245 | dump_output_information = 1; 246 | if (exist('print_to_screen') == 1) & (print_to_screen == 0), 247 | dump_output_information = 0; 248 | end 249 | 250 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 251 | %%%% Create transform matrices, etc. 252 | %%%% 253 | [Tfor, Tinv] = getTransfMatrix(N1, transform_2D_HT_name, decLevel); %% get (normalized) forward and inverse transform matrices 254 | [TforW, TinvW] = getTransfMatrix(N1_wiener, transform_2D_Wiener_name, 0); %% get (normalized) forward and inverse transform matrices 255 | 256 | if (strcmp(transform_3rd_dim_name, 'haar') == 1) | (strcmp(transform_3rd_dim_name(end-2:end), '1.1') == 1), 257 | %%% If Haar is used in the 3-rd dimension, then a fast internal transform is used, thus no need to generate transform 258 | %%% matrices. 259 | hadper_trans_single_den = {}; 260 | inverse_hadper_trans_single_den = {}; 261 | else 262 | %%% Create transform matrices. The transforms are later applied by 263 | %%% matrix-vector multiplication for the 1D case. 264 | for hpow = 0:ceil(log2(max(N2,N2_wiener))), 265 | h = 2^hpow; 266 | [Tfor3rd, Tinv3rd] = getTransfMatrix(h, transform_3rd_dim_name, 0); 267 | hadper_trans_single_den{h} = single(Tfor3rd); 268 | inverse_hadper_trans_single_den{h} = single(Tinv3rd'); 269 | end 270 | end 271 | 272 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 273 | %%%% 2D Kaiser windows used in the aggregation of block-wise estimates 274 | %%%% 275 | if beta_wiener==2 & beta==2 & N1_wiener==8 & N1==8 % hardcode the window function so that the signal processing toolbox is not needed by default 276 | Wwin2D = [ 0.1924 0.2989 0.3846 0.4325 0.4325 0.3846 0.2989 0.1924; 277 | 0.2989 0.4642 0.5974 0.6717 0.6717 0.5974 0.4642 0.2989; 278 | 0.3846 0.5974 0.7688 0.8644 0.8644 0.7688 0.5974 0.3846; 279 | 0.4325 0.6717 0.8644 0.9718 0.9718 0.8644 0.6717 0.4325; 280 | 0.4325 0.6717 0.8644 0.9718 0.9718 0.8644 0.6717 0.4325; 281 | 0.3846 0.5974 0.7688 0.8644 0.8644 0.7688 0.5974 0.3846; 282 | 0.2989 0.4642 0.5974 0.6717 0.6717 0.5974 0.4642 0.2989; 283 | 0.1924 0.2989 0.3846 0.4325 0.4325 0.3846 0.2989 0.1924]; 284 | Wwin2D_wiener = Wwin2D; 285 | else 286 | Wwin2D = kaiser(N1, beta) * kaiser(N1, beta)'; % Kaiser window used in the aggregation of the HT part 287 | Wwin2D_wiener = kaiser(N1_wiener, beta_wiener) * kaiser(N1_wiener, beta_wiener)'; % Kaiser window used in the aggregation of the Wiener filt. part 288 | end 289 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 290 | %%%% If needed, read images, generate noise, or scale the images to the 291 | %%%% [0,1] interval 292 | %%%% 293 | if (exist('y') ~= 1) | (exist('z') ~= 1) 294 | y = im2double(imread(image_name)); %% read a noise-free image and put in intensity range [0,1] 295 | randn('seed', 0); %% generate seed 296 | z = y + (sigma/255)*randn(size(y)); %% create a noisy image 297 | else % external images 298 | 299 | image_name = 'External image'; 300 | 301 | % convert z to double precision if needed 302 | z = double(z); 303 | 304 | % convert y to double precision if needed 305 | y = double(y); 306 | 307 | % if z's range is [0, 255], then convert to [0, 1] 308 | if (max(z(:)) > 10), % a naive check for intensity range 309 | z = z / 255; 310 | end 311 | 312 | % if y's range is [0, 255], then convert to [0, 1] 313 | if (max(y(:)) > 10), % a naive check for intensity range 314 | y = y / 255; 315 | end 316 | end 317 | 318 | 319 | 320 | if (size(z,3) ~= 1) | (size(y,3) ~= 1), 321 | error('BM3D accepts only grayscale 2D images.'); 322 | end 323 | 324 | 325 | % Check if the true image y is a valid one; if not, then we cannot compute PSNR, etc. 326 | y_is_invalid_image = (length(size(z)) ~= length(size(y))) | (size(z,1) ~= size(y,1)) | (size(z,2) ~= size(y,2)); 327 | if (y_is_invalid_image), 328 | dump_output_information = 0; 329 | end 330 | 331 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 332 | %%% Print image information to the screen 333 | %%%% 334 | if dump_output_information == 1, 335 | fprintf('Image: %s (%dx%d), sigma: %.1f\n', image_name, size(z,1), size(z,2), sigma); 336 | end 337 | 338 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 339 | %%%% Step 1. Produce the basic estimate by HT filtering 340 | %%%% 341 | tic; 342 | y_hat = bm3d_thr(z, hadper_trans_single_den, Nstep, N1, N2, lambda_thr2D,... 343 | lambda_thr3D, tau_match*N1*N1/(255*255), (Ns-1)/2, (sigma/255), thrToIncStep, single(Tfor), single(Tinv)', inverse_hadper_trans_single_den, single(thr_mask), Wwin2D, smallLN, stepFS ); 344 | estimate_elapsed_time = toc; 345 | 346 | if dump_output_information == 1, 347 | PSNR_INITIAL_ESTIMATE = 10*log10(1/mean((y(:)-double(y_hat(:))).^2)); 348 | fprintf('BASIC ESTIMATE, PSNR: %.2f dB\n', PSNR_INITIAL_ESTIMATE); 349 | end 350 | 351 | 352 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 353 | %%%% Step 2. Produce the final estimate by Wiener filtering (using the 354 | %%%% hard-thresholding initial estimate) 355 | %%%% 356 | tic; 357 | y_est = bm3d_wiener(z, y_hat, hadper_trans_single_den, Nstep_wiener, N1_wiener, N2_wiener, ... 358 | 'unused arg', tau_match_wiener*N1_wiener*N1_wiener/(255*255), (Ns_wiener-1)/2, (sigma/255), 'unused arg', single(TforW), single(TinvW)', inverse_hadper_trans_single_den, Wwin2D_wiener, smallLNW, stepFSW, single(ones(N1_wiener)) ); 359 | wiener_elapsed_time = toc; 360 | 361 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 362 | %%%% Calculate the final estimate's PSNR, print it, and show the 363 | %%%% denoised image next to the noisy one 364 | %%%% 365 | y_est = double(y_est); 366 | 367 | PSNR = 0; %% Remains 0 if the true image y is not available 368 | if (~y_is_invalid_image), % checks if y is a valid image 369 | PSNR = 10*log10(1/mean((y(:)-y_est(:)).^2)); % y is valid 370 | end 371 | 372 | if dump_output_information == 1, 373 | fprintf('FINAL ESTIMATE (total time: %.1f sec), PSNR: %.2f dB\n', ... 374 | wiener_elapsed_time + estimate_elapsed_time, PSNR); 375 | 376 | figure, imshow(z); title(sprintf('Noisy %s, PSNR: %.3f dB (sigma: %d)', ... 377 | image_name(1:end-4), 10*log10(1/mean((y(:)-z(:)).^2)), sigma)); 378 | 379 | figure, imshow(y_est); title(sprintf('Denoised %s, PSNR: %.3f dB', ... 380 | image_name(1:end-4), PSNR)); 381 | 382 | end 383 | 384 | return; 385 | 386 | 387 | 388 | 389 | 390 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 391 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 392 | % Some auxiliary functions 393 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 394 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 395 | 396 | 397 | 398 | 399 | function [Tforward, Tinverse] = getTransfMatrix (N, transform_type, dec_levels) 400 | % 401 | % Create forward and inverse transform matrices, which allow for perfect 402 | % reconstruction. The forward transform matrix is normalized so that the 403 | % l2-norm of each basis element is 1. 404 | % 405 | % [Tforward, Tinverse] = getTransfMatrix (N, transform_type, dec_levels) 406 | % 407 | % INPUTS: 408 | % 409 | % N --> Size of the transform (for wavelets, must be 2^K) 410 | % 411 | % transform_type --> 'dct', 'dst', 'hadamard', or anything that is 412 | % listed by 'help wfilters' (bi-orthogonal wavelets) 413 | % 'DCrand' -- an orthonormal transform with a DC and all 414 | % the other basis elements of random nature 415 | % 416 | % dec_levels --> If a wavelet transform is generated, this is the 417 | % desired decomposition level. Must be in the 418 | % range [0, log2(N)-1], where "0" implies 419 | % full decomposition. 420 | % 421 | % OUTPUTS: 422 | % 423 | % Tforward --> (N x N) Forward transform matrix 424 | % 425 | % Tinverse --> (N x N) Inverse transform matrix 426 | % 427 | 428 | if exist('dec_levels') ~= 1, 429 | dec_levels = 0; 430 | end 431 | 432 | if N == 1, 433 | Tforward = 1; 434 | elseif strcmp(transform_type, 'hadamard') == 1, 435 | Tforward = hadamard(N); 436 | elseif (N == 8) & strcmp(transform_type, 'bior1.5')==1 % hardcoded transform so that the wavelet toolbox is not needed to generate it 437 | Tforward = [ 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274; 438 | 0.219417649252501 0.449283757993216 0.449283757993216 0.219417649252501 -0.219417649252501 -0.449283757993216 -0.449283757993216 -0.219417649252501; 439 | 0.569359398342846 0.402347308162278 -0.402347308162278 -0.569359398342846 -0.083506045090284 0.083506045090284 -0.083506045090284 0.083506045090284; 440 | -0.083506045090284 0.083506045090284 -0.083506045090284 0.083506045090284 0.569359398342846 0.402347308162278 -0.402347308162278 -0.569359398342846; 441 | 0.707106781186547 -0.707106781186547 0 0 0 0 0 0; 442 | 0 0 0.707106781186547 -0.707106781186547 0 0 0 0; 443 | 0 0 0 0 0.707106781186547 -0.707106781186547 0 0; 444 | 0 0 0 0 0 0 0.707106781186547 -0.707106781186547]; 445 | elseif (N == 8) & strcmp(transform_type, 'dct')==1 % hardcoded transform so that the signal processing toolbox is not needed to generate it 446 | Tforward = [ 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274; 447 | 0.490392640201615 0.415734806151273 0.277785116509801 0.097545161008064 -0.097545161008064 -0.277785116509801 -0.415734806151273 -0.490392640201615; 448 | 0.461939766255643 0.191341716182545 -0.191341716182545 -0.461939766255643 -0.461939766255643 -0.191341716182545 0.191341716182545 0.461939766255643; 449 | 0.415734806151273 -0.097545161008064 -0.490392640201615 -0.277785116509801 0.277785116509801 0.490392640201615 0.097545161008064 -0.415734806151273; 450 | 0.353553390593274 -0.353553390593274 -0.353553390593274 0.353553390593274 0.353553390593274 -0.353553390593274 -0.353553390593274 0.353553390593274; 451 | 0.277785116509801 -0.490392640201615 0.097545161008064 0.415734806151273 -0.415734806151273 -0.097545161008064 0.490392640201615 -0.277785116509801; 452 | 0.191341716182545 -0.461939766255643 0.461939766255643 -0.191341716182545 -0.191341716182545 0.461939766255643 -0.461939766255643 0.191341716182545; 453 | 0.097545161008064 -0.277785116509801 0.415734806151273 -0.490392640201615 0.490392640201615 -0.415734806151273 0.277785116509801 -0.097545161008064]; 454 | elseif (N == 8) & strcmp(transform_type, 'dst')==1 % hardcoded transform so that the PDE toolbox is not needed to generate it 455 | Tforward = [ 0.161229841765317 0.303012985114696 0.408248290463863 0.464242826880013 0.464242826880013 0.408248290463863 0.303012985114696 0.161229841765317; 456 | 0.303012985114696 0.464242826880013 0.408248290463863 0.161229841765317 -0.161229841765317 -0.408248290463863 -0.464242826880013 -0.303012985114696; 457 | 0.408248290463863 0.408248290463863 0 -0.408248290463863 -0.408248290463863 0 0.408248290463863 0.408248290463863; 458 | 0.464242826880013 0.161229841765317 -0.408248290463863 -0.303012985114696 0.303012985114696 0.408248290463863 -0.161229841765317 -0.464242826880013; 459 | 0.464242826880013 -0.161229841765317 -0.408248290463863 0.303012985114696 0.303012985114696 -0.408248290463863 -0.161229841765317 0.464242826880013; 460 | 0.408248290463863 -0.408248290463863 0 0.408248290463863 -0.408248290463863 0 0.408248290463863 -0.408248290463863; 461 | 0.303012985114696 -0.464242826880013 0.408248290463863 -0.161229841765317 -0.161229841765317 0.408248290463863 -0.464242826880013 0.303012985114696; 462 | 0.161229841765317 -0.303012985114696 0.408248290463863 -0.464242826880013 0.464242826880013 -0.408248290463863 0.303012985114696 -0.161229841765317]; 463 | elseif strcmp(transform_type, 'dct') == 1, 464 | Tforward = dct(eye(N)); 465 | elseif strcmp(transform_type, 'dst') == 1, 466 | Tforward = dst(eye(N)); 467 | elseif strcmp(transform_type, 'DCrand') == 1, 468 | x = randn(N); x(1:end,1) = 1; [Q,R] = qr(x); 469 | if (Q(1) < 0), 470 | Q = -Q; 471 | end; 472 | Tforward = Q'; 473 | else %% a wavelet decomposition supported by 'wavedec' 474 | %%% Set periodic boundary conditions, to preserve bi-orthogonality 475 | dwtmode('per','nodisp'); 476 | 477 | Tforward = zeros(N,N); 478 | for i = 1:N 479 | Tforward(:,i)=wavedec(circshift([1 zeros(1,N-1)],[dec_levels i-1]), log2(N), transform_type); %% construct transform matrix 480 | end 481 | end 482 | 483 | %%% Normalize the basis elements 484 | Tforward = (Tforward' * diag(sqrt(1./sum(Tforward.^2,2))))'; 485 | 486 | %%% Compute the inverse transform matrix 487 | Tinverse = inv(Tforward); 488 | 489 | return; 490 | 491 | -------------------------------------------------------------------------------- /BM3D/BM3DDEB.m: -------------------------------------------------------------------------------- 1 | function [ISNR, y_hat_RWI] = BM3DDEB(experiment_number, test_image_name) 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % 4 | % Copyright (c) 2008-2014 Tampere University of Technology. All rights reserved. 5 | % This work should only be used for nonprofit purposes. 6 | % 7 | % AUTHORS: 8 | % Kostadin Dabov 9 | % Alessandro Foi email: alessandro.foi _at_ tut.fi 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | % 12 | % This function implements the image deblurring method proposed in: 13 | % 14 | % [1] K. Dabov, A. Foi, V. Katkovnik, and K. Egiazarian, "Image 15 | % restoration by sparse 3D transform-domain collaborative filtering," 16 | % Proc SPIE Electronic Imaging, January 2008. 17 | % 18 | % FUNCTION INTERFACE: 19 | % 20 | % [PSNR, y_hat_RWI] = BM3DDEB(experiment_number, test_image_name) 21 | % 22 | % INPUT: 23 | % 1) experiment_number: 1 -> PSF 1, sigma^2 = 2 24 | % 2 -> PSF 1, sigma^2 = 8 25 | % 3 -> PSF 2, sigma^2 = 0.308 26 | % 4 -> PSF 3, sigma^2 = 49 27 | % 5 -> PSF 4, sigma^2 = 4 28 | % 6 -> PSF 5, sigma^2 = 64 29 | % 30 | % 2) test_image_name: a valid filename of a grayscale test image 31 | % 32 | % OUTPUT: 33 | % 1) ISNR: the output improvement in SNR, dB 34 | % 2) y_hat_RWI: the restored image 35 | % 36 | % ! The function can work without any of the input arguments, 37 | % in which case, the internal default ones are used ! 38 | % 39 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 40 | 41 | %%%% Fixed regularization parameters (obtained empirically after a rough optimization) 42 | Regularization_alpha_RI = 4e-4; 43 | Regularization_alpha_RWI = 5e-3; 44 | 45 | %%%% Experiment number (see below for details, e.g. how the blur is generated, etc.) 46 | if (exist('experiment_number') ~= 1) 47 | experiment_number = 3; % 1 -- 6 48 | end 49 | 50 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 51 | %%%% Select a single image filename (might contain path) 52 | %%%% 53 | if (exist('test_image_name') ~= 1) 54 | test_image_name = [ 55 | % 'Lena512.png' 56 | 'Cameraman256.png' 57 | % 'barbara.png' 58 | % 'house.png' 59 | ]; 60 | end 61 | 62 | %%%% Select 2D transforms ('dct', 'dst', 'hadamard', or anything that is listed by 'help wfilters'): 63 | transform_2D_HT_name = 'dst'; %% 2D transform (of size N1 x N1) used in Step 1 64 | transform_2D_Wiener_name = 'dct'; %% 2D transform (of size N1_wiener x N1_wiener) used in Step 2 65 | transform_3rd_dimage_name = 'haar'; %% 1D tranform used in the 3-rd dim, the same for both steps 66 | 67 | %%%% Step 1 (BM3D with collaborative hard-thresholding) parameters: 68 | N1 = 8; %% N1 x N1 is the block size 69 | Nstep = 3; %% sliding step to process every next refernece block 70 | N2 = 16; %% maximum number of similar blocks (maximum size of the 3rd dimensiona of a 3D array) 71 | Ns = 39; %% length of the side of the search neighborhood for full-search block-matching (BM) 72 | tau_match = 6000;%% threshold for the block distance (d-distance) 73 | lambda_thr2D = 0; %% threshold for the coarse initial denoising used in the d-distance measure 74 | lambda_thr3D = 2.9; %% threshold for the hard-thresholding 75 | beta = 0; %% the beta parameter of the 2D Kaiser window used in the reconstruction 76 | 77 | %%%% Step 2 (BM3D with collaborative Wiener filtering) parameters: 78 | N1_wiener = 8; 79 | Nstep_wiener = 2; 80 | N2_wiener = 16; 81 | Ns_wiener = 39; 82 | tau_match_wiener = 800; 83 | beta_wiener = 0; 84 | 85 | %%%% Specify whether to print results and display images 86 | print_to_screen = 1; 87 | 88 | 89 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 90 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 91 | %%%% Note: touch below this point only if you know what you are doing! 92 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 93 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 94 | 95 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 96 | %%%% Make parameters compatible with the interface of the mex-functions 97 | %%%% 98 | 99 | [Tfor, Tinv] = getTransfMatrix(N1, transform_2D_HT_name, 0); %% get (normalized) forward and inverse transform matrices 100 | [TforW, TinvW] = getTransfMatrix(N1_wiener, transform_2D_Wiener_name, 0); %% get (normalized) forward and inverse transform matrices 101 | 102 | if (strcmp(transform_3rd_dimage_name, 'haar') == 1), 103 | %%% Fast internal transform is used, no need to generate transform 104 | %%% matrices. 105 | hadper_trans_single_den = {}; 106 | inverse_hadper_trans_single_den = {}; 107 | else 108 | %%% Create transform matrices. The transforms are later applied by 109 | %%% vector-matrix multiplications 110 | for hpow = 0:ceil(log2(max(N2,N2_wiener))), 111 | h = 2^hpow; 112 | [Tfor3rd, Tinv3rd] = getTransfMatrix(h, transform_3rd_dimage_name, 0); 113 | hadper_trans_single_den{h} = single(Tfor3rd); 114 | inverse_hadper_trans_single_den{h} = single(Tinv3rd'); 115 | end 116 | end 117 | 118 | if beta == 0 & beta_wiener == 0 119 | Wwin2D = ones(N1,N1); 120 | Wwin2D_wiener = ones(N1_wiener,N1_wiener); 121 | else 122 | Wwin2D = kaiser(N1, beta) * kaiser(N1, beta)'; % Kaiser window used in the hard-thresholding part 123 | Wwin2D_wiener = kaiser(N1_wiener, beta_wiener) * kaiser(N1_wiener, beta_wiener)'; % Kaiser window used in the Wiener filtering part 124 | end 125 | 126 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 127 | %%%% Read an image and generate a blurred and noisy image 128 | %%%% 129 | y = im2double(imread(test_image_name)); 130 | 131 | if experiment_number==1 132 | sigma=sqrt(2)/255; 133 | for x1=-7:7; for x2=-7:7; v(x1+8,x2+8)=1/(x1^2+x2^2+1); end, end; v=v./sum(v(:)); 134 | end 135 | if experiment_number==2 136 | sigma=sqrt(8)/255; 137 | s1=0; for a1=-7:7; s1=s1+1; s2=0; for a2=-7:7; s2=s2+1; v(s1,s2)=1/(a1^2+a2^2+1); end, end; v=v./sum(v(:)); 138 | end 139 | if experiment_number==3 140 | BSNR=40; sigma=-1; % if "sigma=-1", then the value of sigma depends on the BSNR 141 | v=ones(9); v=v./sum(v(:)); 142 | end 143 | if experiment_number==4 144 | sigma=7/255; 145 | v=[1 4 6 4 1]'*[1 4 6 4 1]; v=v./sum(v(:)); % PSF 146 | end 147 | if experiment_number==5 148 | sigma=2/255; 149 | v=fspecial('gaussian', 25, 1.6); 150 | end 151 | if experiment_number==6 152 | sigma=8/255; 153 | v=fspecial('gaussian', 25, .4); 154 | end 155 | 156 | 157 | [Xv, Xh] = size(y); 158 | [ghy,ghx] = size(v); 159 | big_v = zeros(Xv,Xh); big_v(1:ghy,1:ghx)=v; big_v=circshift(big_v,-round([(ghy-1)/2 (ghx-1)/2])); % pad PSF with zeros to whole image domain, and center it 160 | V = fft2(big_v); % frequency response of the PSF 161 | y_blur = imfilter(y, v(end:-1:1,end:-1:1), 'circular'); % performs blurring (by circular convolution) 162 | 163 | randn('seed',0); %%% fix seed for the random number generator 164 | if sigma == -1; %% check whether to use BSNR in order to define value of sigma 165 | sigma=sqrt(norm(y_blur(:)-mean(y_blur(:)),2)^2 /(Xh*Xv*10^(BSNR/10))); % compute sigma from the desired BSNR 166 | end 167 | 168 | %%%% Create a blurred and noisy observation 169 | z = y_blur + sigma*randn(Xv,Xh); 170 | 171 | tic; 172 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 173 | %%%% Step 1: Final estimate by Regularized Inversion (RI) followed by 174 | %%%% BM3D with collaborative hard-thresholding 175 | %%%% 176 | 177 | %%%% Step 1.1. Regularized Inversion 178 | RI= conj(V)./( (abs(V).^2) + Regularization_alpha_RI * Xv*Xh*sigma^2); % Transfer Matrix for RI %% Standard Tikhonov Regularization 179 | zRI=real(ifft2( fft2(z).* RI )); % Regularized Inverse Estimate (RI OBSERVATION) 180 | 181 | stdRI = zeros(N1, N1); 182 | for ii = 1:N1, 183 | for jj = 1:N1, 184 | UnitMatrix = zeros(N1,N1); UnitMatrix(ii,jj)=1; 185 | BasisElementPadded = zeros(Xv, Xh); BasisElementPadded(1:N1,1:N1) = Tinv*UnitMatrix*Tinv'; 186 | TransfBasisElementPadded = fft2(BasisElementPadded); 187 | stdRI(ii,jj) = sqrt( (1/(Xv*Xh)) * sum(sum(abs(TransfBasisElementPadded.*RI).^2)) )*sigma; 188 | end, 189 | end 190 | 191 | %%%% Step 1.2. Colored noise suppression by BM3D with collaborative hard- 192 | %%%% thresholding 193 | 194 | y_hat_RI = bm3d_thr_colored_noise(zRI, hadper_trans_single_den, Nstep, N1, N2, lambda_thr2D,... 195 | lambda_thr3D, tau_match*N1*N1/(255*255), (Ns-1)/2, sigma, 0, single(Tfor), single(Tinv)',... 196 | inverse_hadper_trans_single_den, single(stdRI'), Wwin2D, 0, 1 ); 197 | 198 | PSNR_INITIAL_ESTIMATE = 10*log10(1/mean((y(:)-y_hat_RI(:)).^2)); 199 | ISNR_INITIAL_ESTIMATE = PSNR_INITIAL_ESTIMATE - 10*log10(1/mean((y(:)-z(:)).^2)); 200 | 201 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 202 | %%%% Step 2: Final estimate by Regularized Wiener Inversion (RWI) followed 203 | %%%% by BM3D with collaborative Wiener filtering 204 | %%%% 205 | 206 | %%%% Step 2.1. Regularized Wiener Inversion 207 | Wiener_Pilot = abs(fft2(double(y_hat_RI))); %%% Wiener reference estimate 208 | RWI = conj(V).*Wiener_Pilot.^2./(Wiener_Pilot.^2.*(abs(V).^2) + Regularization_alpha_RWI*Xv*Xh*sigma^2); % Transfer Matrix for RWI (uses standard regularization 'a-la-Tikhonov') 209 | zRWI = real(ifft2(fft2(z).*RWI)); % RWI OBSERVATION 210 | 211 | stdRWI = zeros(N1_wiener, N1_wiener); 212 | for ii = 1:N1_wiener, 213 | for jj = 1:N1_wiener, 214 | UnitMatrix = zeros(N1_wiener,N1_wiener); UnitMatrix(ii,jj)=1; 215 | BasisElementPadded = zeros(Xv, Xh); BasisElementPadded(1:N1_wiener,1:N1_wiener) = TinvW*UnitMatrix*TinvW'; 216 | TransfBasisElementPadded = fft2(BasisElementPadded); 217 | stdRWI(ii,jj) = sqrt( (1/(Xv*Xh)) * sum(sum(abs(TransfBasisElementPadded.*RWI).^2)) )*sigma; 218 | end, 219 | end 220 | 221 | %%%% Step 2.2. Colored noise suppression by BM3D with collaborative Wiener 222 | %%%% filtering 223 | y_hat_RWI = bm3d_wiener_colored_noise(zRWI, y_hat_RI, hadper_trans_single_den, Nstep_wiener, N1_wiener, N2_wiener, ... 224 | 0, tau_match_wiener*N1_wiener*N1_wiener/(255*255), (Ns_wiener-1)/2, 0, single(stdRWI'), single(TforW), single(TinvW)',... 225 | inverse_hadper_trans_single_den, Wwin2D_wiener, 0, 1, single(ones(N1_wiener)) ); 226 | 227 | elapsed_time = toc; 228 | 229 | 230 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 231 | %%%% Calculate the final estimate's PSNR and ISNR, print them, and show the 232 | %%%% restored image 233 | %%%% 234 | PSNR = 10*log10(1/mean((y(:)-y_hat_RWI(:)).^2)); 235 | ISNR = PSNR - 10*log10(1/mean((y(:)-z(:)).^2)); 236 | 237 | if print_to_screen == 1 238 | fprintf('Image: %s, Exp %d, Time: %.1f sec, PSNR-RI: %.2f dB, PSNR-RWI: %.2f, ISNR-RWI: %.2f dB\n', ... 239 | test_image_name, experiment_number, elapsed_time, PSNR_INITIAL_ESTIMATE, PSNR, ISNR); 240 | figure,imshow(z); 241 | figure,imshow(double(y_hat_RWI)); 242 | end 243 | 244 | return; 245 | 246 | 247 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 248 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 249 | % Some auxiliary functions 250 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 251 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 252 | 253 | 254 | 255 | function [Tforward, Tinverse] = getTransfMatrix (N, transform_type, dec_levels) 256 | % 257 | % Create forward and inverse transform matrices, which allow for perfect 258 | % reconstruction. The forward transform matrix is normalized so that the 259 | % l2-norm of each basis element is 1. 260 | % 261 | % [Tforward, Tinverse] = getTransfMatrix (N, transform_type, dec_levels) 262 | % 263 | % INPUTS: 264 | % 265 | % N --> Size of the transform (for wavelets, must be 2^K) 266 | % 267 | % transform_type --> 'dct', 'dst', 'hadamard', or anything that is 268 | % listed by 'help wfilters' (bi-orthogonal wavelets) 269 | % 'DCrand' -- an orthonormal transform with a DC and all 270 | % the other basis elements of random nature 271 | % 272 | % dec_levels --> If a wavelet transform is generated, this is the 273 | % desired decomposition level. Must be in the 274 | % range [0, log2(N)-1], where "0" implies 275 | % full decomposition. 276 | % 277 | % OUTPUTS: 278 | % 279 | % Tforward --> (N x N) Forward transform matrix 280 | % 281 | % Tinverse --> (N x N) Inverse transform matrix 282 | % 283 | 284 | if exist('dec_levels') ~= 1, 285 | dec_levels = 0; 286 | end 287 | 288 | if N == 1, 289 | Tforward = 1; 290 | elseif strcmp(transform_type, 'hadamard') == 1, 291 | Tforward = hadamard(N); 292 | elseif (N == 8) & strcmp(transform_type, 'bior1.5')==1 % hardcoded transform so that the wavelet toolbox is not needed to generate it 293 | Tforward = [ 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274; 294 | 0.219417649252501 0.449283757993216 0.449283757993216 0.219417649252501 -0.219417649252501 -0.449283757993216 -0.449283757993216 -0.219417649252501; 295 | 0.569359398342846 0.402347308162278 -0.402347308162278 -0.569359398342846 -0.083506045090284 0.083506045090284 -0.083506045090284 0.083506045090284; 296 | -0.083506045090284 0.083506045090284 -0.083506045090284 0.083506045090284 0.569359398342846 0.402347308162278 -0.402347308162278 -0.569359398342846; 297 | 0.707106781186547 -0.707106781186547 0 0 0 0 0 0; 298 | 0 0 0.707106781186547 -0.707106781186547 0 0 0 0; 299 | 0 0 0 0 0.707106781186547 -0.707106781186547 0 0; 300 | 0 0 0 0 0 0 0.707106781186547 -0.707106781186547]; 301 | elseif (N == 8) & strcmp(transform_type, 'dct')==1 % hardcoded transform so that the signal processing toolbox is not needed to generate it 302 | Tforward = [ 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274; 303 | 0.490392640201615 0.415734806151273 0.277785116509801 0.097545161008064 -0.097545161008064 -0.277785116509801 -0.415734806151273 -0.490392640201615; 304 | 0.461939766255643 0.191341716182545 -0.191341716182545 -0.461939766255643 -0.461939766255643 -0.191341716182545 0.191341716182545 0.461939766255643; 305 | 0.415734806151273 -0.097545161008064 -0.490392640201615 -0.277785116509801 0.277785116509801 0.490392640201615 0.097545161008064 -0.415734806151273; 306 | 0.353553390593274 -0.353553390593274 -0.353553390593274 0.353553390593274 0.353553390593274 -0.353553390593274 -0.353553390593274 0.353553390593274; 307 | 0.277785116509801 -0.490392640201615 0.097545161008064 0.415734806151273 -0.415734806151273 -0.097545161008064 0.490392640201615 -0.277785116509801; 308 | 0.191341716182545 -0.461939766255643 0.461939766255643 -0.191341716182545 -0.191341716182545 0.461939766255643 -0.461939766255643 0.191341716182545; 309 | 0.097545161008064 -0.277785116509801 0.415734806151273 -0.490392640201615 0.490392640201615 -0.415734806151273 0.277785116509801 -0.097545161008064]; 310 | elseif (N == 8) & strcmp(transform_type, 'dst')==1 % hardcoded transform so that the PDE toolbox is not needed to generate it 311 | Tforward = [ 0.161229841765317 0.303012985114696 0.408248290463863 0.464242826880013 0.464242826880013 0.408248290463863 0.303012985114696 0.161229841765317; 312 | 0.303012985114696 0.464242826880013 0.408248290463863 0.161229841765317 -0.161229841765317 -0.408248290463863 -0.464242826880013 -0.303012985114696; 313 | 0.408248290463863 0.408248290463863 0 -0.408248290463863 -0.408248290463863 0 0.408248290463863 0.408248290463863; 314 | 0.464242826880013 0.161229841765317 -0.408248290463863 -0.303012985114696 0.303012985114696 0.408248290463863 -0.161229841765317 -0.464242826880013; 315 | 0.464242826880013 -0.161229841765317 -0.408248290463863 0.303012985114696 0.303012985114696 -0.408248290463863 -0.161229841765317 0.464242826880013; 316 | 0.408248290463863 -0.408248290463863 0 0.408248290463863 -0.408248290463863 0 0.408248290463863 -0.408248290463863; 317 | 0.303012985114696 -0.464242826880013 0.408248290463863 -0.161229841765317 -0.161229841765317 0.408248290463863 -0.464242826880013 0.303012985114696; 318 | 0.161229841765317 -0.303012985114696 0.408248290463863 -0.464242826880013 0.464242826880013 -0.408248290463863 0.303012985114696 -0.161229841765317]; 319 | elseif strcmp(transform_type, 'dct') == 1, 320 | Tforward = dct(eye(N)); 321 | elseif strcmp(transform_type, 'dst') == 1, 322 | Tforward = dst(eye(N)); 323 | elseif strcmp(transform_type, 'DCrand') == 1, 324 | x = randn(N); x(1:end,1) = 1; [Q,R] = qr(x); 325 | if (Q(1) < 0), 326 | Q = -Q; 327 | end; 328 | Tforward = Q'; 329 | else %% a wavelet decomposition supported by 'wavedec' 330 | %%% Set periodic boundary conditions, to preserve bi-orthogonality 331 | dwtmode('per','nodisp'); 332 | 333 | Tforward = zeros(N,N); 334 | for i = 1:N 335 | Tforward(:,i)=wavedec(circshift([1 zeros(1,N-1)],[dec_levels i-1]), log2(N), transform_type); %% construct transform matrix 336 | end 337 | end 338 | 339 | %%% Normalize the basis elements 340 | Tforward = (Tforward' * diag(sqrt(1./sum(Tforward.^2,2))))'; 341 | 342 | %%% Compute the inverse transform matrix 343 | Tinverse = inv(Tforward); 344 | 345 | return; -------------------------------------------------------------------------------- /BM3D/BM3DSHARP.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/BM3DSHARP.m -------------------------------------------------------------------------------- /BM3D/BM3D_CFA.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/BM3D_CFA.m -------------------------------------------------------------------------------- /BM3D/CBM3D.m: -------------------------------------------------------------------------------- 1 | function [PSNR, yRGB_est] = CBM3D(yRGB, zRGB, sigma, profile, print_to_screen, colorspace) 2 | % 3 | % CBM3D is algorithm for attenuation of additive white Gaussian noise from 4 | % color RGB images. This algorithm reproduces the results from the article: 5 | % 6 | % [1] K. Dabov, A. Foi, V. Katkovnik, and K. Egiazarian, "Color image 7 | % denoising via sparse 3D collaborative filtering with grouping constraint in 8 | % luminance-chrominance space," submitted to IEEE Int. Conf. Image Process., 9 | % January 2007, in review, preprint at http://www.cs.tut.fi/~foi/GCF-BM3D. 10 | % 11 | % FUNCTION INTERFACE: 12 | % 13 | % [PSNR, yRGB_est] = CBM3D(yRGB, zRGB, sigma, profile, print_to_screen, colorspace) 14 | % 15 | % ! The function can work without any of the input arguments, 16 | % in which case, the internal default ones are used ! 17 | % 18 | % BASIC USAGE EXAMPLES: 19 | % 20 | % Case 1) Using the default parameters (i.e., image name, sigma, etc.) 21 | % 22 | % [PSNR, yRGB_est] = CBM3D; 23 | % 24 | % Case 2) Using an external noisy image: 25 | % 26 | % % Read an RGB image and scale its intensities in range [0,1] 27 | % yRGB = im2double(imread('image_House256rgb.png')); 28 | % % Generate the same seed used in the experimental results of [1] 29 | % randn('seed', 0); 30 | % % Standard deviation of the noise --- corresponding to intensity 31 | % % range [0,255], despite that the input was scaled in [0,1] 32 | % sigma = 25; 33 | % % Add the AWGN with zero mean and standard deviation 'sigma' 34 | % zRGB = yRGB + (sigma/255)*randn(size(yRGB)); 35 | % % Denoise 'zRGB'. The denoised image is 'yRGB_est', and 'NA = 1' 36 | % % because the true image was not provided 37 | % [NA, yRGB_est] = CBM3D(1, zRGB, sigma); 38 | % % Compute the putput PSNR 39 | % PSNR = 10*log10(1/mean((yRGB(:)-yRGB_est(:)).^2)) 40 | % % show the noisy image 'zRGB' and the denoised 'yRGB_est' 41 | % figure; imshow(min(max(zRGB,0),1)); 42 | % figure; imshow(min(max(yRGB_est,0),1)); 43 | % 44 | % Case 3) If the original image yRGB is provided as the first input 45 | % argument, then some additional information is printed (PSNRs, 46 | % figures, etc.). That is, "[NA, yRGB_est] = BM3D(1, zRGB, sigma);" in the 47 | % above code should be replaced with: 48 | % 49 | % [PSNR, yRGB_est] = CBM3D(yRGB, zRGB, sigma); 50 | % 51 | % 52 | % INPUT ARGUMENTS (OPTIONAL): 53 | % 1) yRGB (M x N x 3): Noise-free RGB image (needed for computing PSNR), 54 | % replace with the scalar 1 if not available. 55 | % 2) zRGB (M x N x 3): Noisy RGBimage (intensities in range [0,1] or [0,255]) 56 | % 3) sigma (double) : Std. dev. of the noise (corresponding to intensities 57 | % in range [0,255] even if the range of zRGB is [0,1]) 58 | % 4) profile (char) : 'np' --> Normal Profile 59 | % 'lc' --> Fast Profile 60 | % 5) print_to_screen : 0 --> do not print output information (and do 61 | % not plot figures) 62 | % 1 --> print information and plot figures 63 | % 6) colorspace (char): 'opp' --> use opponent colorspace 64 | % 'yCbCr' --> use yCbCr colorspace 65 | % 66 | % OUTPUTS: 67 | % 1) PSNR (double) : Output PSNR (dB), only if the original 68 | % image is available, otherwise PSNR = 0 69 | % 2) yRGB_est (M x N x 3): Final RGB estimate (in the range [0,1]) 70 | % 71 | % 72 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73 | % 74 | % Copyright (c) 2007-2011 Tampere University of Technology. 75 | % All rights reserved. 76 | % This work should only be used for nonprofit purposes. 77 | % 78 | % AUTHORS: 79 | % Kostadin Dabov, email: dabov _at_ cs.tut.fi 80 | % 81 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 82 | 83 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84 | %%%% In case, there is no input image (zRGB or yRGB), then use the filename 85 | %%%% below to read an original image (might contain path also). Later, 86 | %%%% artificial AWGN noise is added and this noisy image is processed 87 | %%%% by the CBM3D. 88 | %%%% 89 | image_name = [ 90 | % 'kodim12.png' 91 | 'image_Lena512rgb.png' 92 | % 'image_House256rgb.png' 93 | % 'image_Peppers512rgb.png' 94 | % 'image_Baboon512rgb.png' 95 | % 'image_F16_512rgb.png' 96 | ]; 97 | 98 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 99 | %%%% Quality/complexity trade-off 100 | %%%% 101 | %%%% 'np' --> Normal Profile (balanced quality) 102 | %%%% 'lc' --> Low Complexity Profile (fast, lower quality) 103 | %%%% 104 | %%%% 'high' --> High Profile (high quality, not documented in [1]) 105 | %%%% 106 | %%%% 'vn' --> This profile is automatically enabled for high noise 107 | %%%% when sigma > 40 108 | %%%% 109 | %%%% 'vn_old' --> This is the old 'vn' profile that was used in [1]. 110 | %%%% It gives inferior results than 'vn' in most cases. 111 | %%%% 112 | if (exist('profile') ~= 1) 113 | profile = 'np'; %% default profile 114 | end 115 | 116 | 117 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 118 | %%%% Specify the std. dev. of the corrupting noise 119 | %%%% 120 | if (exist('sigma') ~= 1), 121 | sigma = 50; %% default standard deviation of the AWGN 122 | end 123 | 124 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 125 | %%%% Colorspace in which we perform denoising. BM is applied to the first 126 | %%%% component and the matching information is re-used for the other two. 127 | %%%% 128 | if (exist('colorspace') ~= 1), 129 | colorspace = 'opp'; %%% (valid colorspaces are: 'yCbCr' and 'opp') 130 | end 131 | 132 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 133 | %%%% Following are the parameters for the Normal Profile. 134 | %%%% 135 | 136 | %%%% Select transforms ('dct', 'dst', 'hadamard', or anything that is listed by 'help wfilters'): 137 | transform_2D_HT_name = 'bior1.5'; %% transform used for the HT filt. of size N1 x N1 138 | transform_2D_Wiener_name = 'dct'; %% transform used for the Wiener filt. of size N1_wiener x N1_wiener 139 | transform_3rd_dim_name = 'haar'; %% transform used in the 3-rd dim, the same for HT and Wiener filt. 140 | 141 | %%%% Hard-thresholding (HT) parameters: 142 | N1 = 8; %% N1 x N1 is the block size used for the hard-thresholding (HT) filtering 143 | Nstep = 3; %% sliding step to process every next reference block 144 | N2 = 16; %% maximum number of similar blocks (maximum size of the 3rd dimension of a 3D array) 145 | Ns = 39; %% length of the side of the search neighborhood for full-search block-matching (BM), must be odd 146 | tau_match = 3000;%% threshold for the block-distance (d-distance) 147 | lambda_thr2D = 0; %% threshold parameter for the coarse initial denoising used in the d-distance measure 148 | lambda_thr3D = 2.7; %% threshold parameter for the hard-thresholding in 3D transform domain 149 | beta = 2.0; %% parameter of the 2D Kaiser window used in the reconstruction 150 | 151 | %%%% Wiener filtering parameters: 152 | N1_wiener = 8; 153 | Nstep_wiener = 3; 154 | N2_wiener = 32; 155 | Ns_wiener = 39; 156 | tau_match_wiener = 400; 157 | beta_wiener = 2.0; 158 | 159 | %%%% Block-matching parameters: 160 | stepFS = 1; %% step that forces to switch to full-search BM, "1" implies always full-search 161 | smallLN = 'not used in np'; %% if stepFS > 1, then this specifies the size of the small local search neighb. 162 | stepFSW = 1; 163 | smallLNW = 'not used in np'; 164 | thrToIncStep = 8; %% used in the HT filtering to increase the sliding step in uniform regions 165 | 166 | if strcmp(profile, 'lc') == 1, 167 | 168 | Nstep = 6; 169 | Ns = 25; 170 | Nstep_wiener = 5; 171 | N2_wiener = 16; 172 | Ns_wiener = 25; 173 | 174 | thrToIncStep = 3; 175 | smallLN = 3; 176 | stepFS = 6*Nstep; 177 | smallLNW = 2; 178 | stepFSW = 5*Nstep_wiener; 179 | 180 | end 181 | 182 | % Profile 'vn' was proposed in 183 | % Y. Hou, C. Zhao, D. Yang, and Y. Cheng, 'Comment on "Image Denoising by Sparse 3D Transform-Domain 184 | % Collaborative Filtering"', accepted for publication, IEEE Trans. on Image Processing, July, 2010. 185 | % as a better alternative to that initially proposed in [1] (which is currently in profile 'vn_old') 186 | if (strcmp(profile, 'vn') == 1) | (sigma > 40), 187 | 188 | N2 = 32; 189 | Nstep = 4; 190 | 191 | N1_wiener = 11; 192 | Nstep_wiener = 6; 193 | 194 | lambda_thr3D = 2.8; 195 | thrToIncStep = 3; 196 | tau_match_wiener = 3500; 197 | tau_match = 25000; 198 | 199 | Ns_wiener = 39; 200 | 201 | end 202 | 203 | % The 'vn_old' profile corresponds to the original parameters for strong noise proposed in [1]. 204 | if (strcmp(profile, 'vn_old') == 1) & (sigma > 40), 205 | 206 | transform_2D_HT_name = 'dct'; 207 | 208 | N1 = 12; 209 | Nstep = 4; 210 | 211 | N1_wiener = 11; 212 | Nstep_wiener = 6; 213 | 214 | lambda_thr3D = 2.8; 215 | lambda_thr2D = 2.0; 216 | thrToIncStep = 3; 217 | tau_match_wiener = 3500; 218 | tau_match = 5000; 219 | 220 | Ns_wiener = 39; 221 | 222 | end 223 | 224 | 225 | decLevel = 0; %% dec. levels of the dyadic wavelet 2D transform for blocks (0 means full decomposition, higher values decrease the dec. number) 226 | thr_mask = ones(N1); %% N1xN1 mask of threshold scaling coeff. --- by default there is no scaling, however the use of different thresholds for different wavelet decompoistion subbands can be done with this matrix 227 | 228 | if strcmp(profile, 'high') == 1, 229 | 230 | decLevel = 1; 231 | Nstep = 2; 232 | Nstep_wiener = 2; 233 | lambda_thr3D = 2.5; 234 | vMask = ones(N1,1); vMask((end/4+1):end/2)= 1.01; vMask((end/2+1):end) = 1.07; %% this allows to have different threhsolds for the finest and next-to-the-finest subbands 235 | thr_mask = vMask * vMask'; 236 | beta = 2.5; 237 | beta_wiener = 1.5; 238 | 239 | end 240 | 241 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 242 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 243 | %%%% Note: touch below this point only if you know what you are doing! 244 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 245 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 246 | 247 | %%% Check whether to dump information to the screen or reamin silent 248 | dump_output_information = 1; 249 | if (exist('print_to_screen') == 1) & (print_to_screen == 0), 250 | dump_output_information = 0; 251 | end 252 | 253 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 254 | %%%% Create transform matrices, etc. 255 | %%%% 256 | [Tfor, Tinv] = getTransfMatrix(N1, transform_2D_HT_name, decLevel); %% get (normalized) forward and inverse transform matrices 257 | [TforW, TinvW] = getTransfMatrix(N1_wiener, transform_2D_Wiener_name); %% get (normalized) forward and inverse transform matrices 258 | 259 | if (strcmp(transform_3rd_dim_name, 'haar') == 1) | (strcmp(transform_3rd_dim_name(end-2:end), '1.1') == 1), 260 | %%% If Haar is used in the 3-rd dimension, then a fast internal transform is used, thus no need to generate transform 261 | %%% matrices. 262 | hadper_trans_single_den = {}; 263 | inverse_hadper_trans_single_den = {}; 264 | else 265 | %%% Create transform matrices. The transforms are later applied by 266 | %%% matrix-vector multiplication for the 1D case. 267 | for hpow = 0:ceil(log2(max(N2,N2_wiener))), 268 | h = 2^hpow; 269 | [Tfor3rd, Tinv3rd] = getTransfMatrix(h, transform_3rd_dim_name, 0); 270 | hadper_trans_single_den{h} = single(Tfor3rd); 271 | inverse_hadper_trans_single_den{h} = single(Tinv3rd'); 272 | end 273 | end 274 | 275 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 276 | %%%% 2D Kaiser windows used in the aggregation of block-wise estimates 277 | %%%% 278 | if beta_wiener==2 & beta==2 & N1_wiener==8 & N1==8 % hardcode the window function so that the signal processing toolbox is not needed by default 279 | Wwin2D = [ 0.1924 0.2989 0.3846 0.4325 0.4325 0.3846 0.2989 0.1924; 280 | 0.2989 0.4642 0.5974 0.6717 0.6717 0.5974 0.4642 0.2989; 281 | 0.3846 0.5974 0.7688 0.8644 0.8644 0.7688 0.5974 0.3846; 282 | 0.4325 0.6717 0.8644 0.9718 0.9718 0.8644 0.6717 0.4325; 283 | 0.4325 0.6717 0.8644 0.9718 0.9718 0.8644 0.6717 0.4325; 284 | 0.3846 0.5974 0.7688 0.8644 0.8644 0.7688 0.5974 0.3846; 285 | 0.2989 0.4642 0.5974 0.6717 0.6717 0.5974 0.4642 0.2989; 286 | 0.1924 0.2989 0.3846 0.4325 0.4325 0.3846 0.2989 0.1924]; 287 | Wwin2D_wiener = Wwin2D; 288 | else 289 | Wwin2D = kaiser(N1, beta) * kaiser(N1, beta)'; % Kaiser window used in the aggregation of the HT part 290 | Wwin2D_wiener = kaiser(N1_wiener, beta_wiener) * kaiser(N1_wiener, beta_wiener)'; % Kaiser window used in the aggregation of the Wiener filt. part 291 | end 292 | 293 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 294 | %%%% If needed, read images, generate noise, or scale the images to the 295 | %%%% [0,1] interval 296 | %%%% 297 | if (exist('yRGB') ~= 1) | (exist('zRGB') ~= 1) 298 | yRGB = im2double(imread(image_name)); %% read a noise-free image 299 | randn('seed', 0); %% generate seed 300 | zRGB = yRGB + (sigma/255)*randn(size(yRGB)); %% create a noisy image 301 | else % external images 302 | image_name = 'External image'; 303 | 304 | % convert zRGB to double precision 305 | zRGB = double(zRGB); 306 | 307 | % convert yRGB to double precision 308 | yRGB = double(yRGB); 309 | 310 | % if zRGB's range is [0, 255], then convert to [0, 1] 311 | if (max(zRGB(:)) > 10), % a naive check for intensity range 312 | zRGB = zRGB / 255; 313 | end 314 | 315 | % if yRGB's range is [0, 255], then convert to [0, 1] 316 | if (max(yRGB(:)) > 10), % a naive check for intensity range 317 | yRGB = yRGB / 255; 318 | end 319 | end 320 | 321 | 322 | if (size(zRGB,3) ~= 3) | (size(zRGB,4) ~= 1), 323 | error('CBM3D accepts only input RGB images (i.e. matrices of size M x N x 3).'); 324 | end 325 | 326 | % Check if the true image yRGB is a valid one; if not, then we cannot compute PSNR, etc. 327 | yRGB_is_invalid_image = (length(size(zRGB)) ~= length(size(yRGB))) | (size(zRGB,1) ~= size(yRGB,1)) | (size(zRGB,2) ~= size(yRGB,2)) | (size(zRGB,3) ~= size(yRGB,3)); 328 | if (yRGB_is_invalid_image), 329 | dump_output_information = 0; 330 | end 331 | 332 | 333 | [Xv, Xh, numSlices] = size(zRGB); %%% obtain image sizes 334 | 335 | if numSlices ~= 3 336 | fprintf('Error, an RGB color image is required!\n'); 337 | return; 338 | end 339 | 340 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 341 | %%%% Change colorspace, compute the l2-norms of the new color channels 342 | %%%% 343 | [zColSpace l2normLumChrom] = function_rgb2LumChrom(zRGB, colorspace); 344 | 345 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 346 | %%%% Print image information to the screen 347 | %%%% 348 | if dump_output_information == 1, 349 | fprintf(sprintf('Image: %s (%dx%dx%d), sigma: %.1f\n', image_name, Xv, Xh, numSlices, sigma)); 350 | end 351 | 352 | 353 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 354 | %%%% Step 1. Basic estimate by collaborative hard-thresholding and using 355 | %%%% the grouping constraint on the chrominances. 356 | %%%% 357 | tic; 358 | y_hat = bm3d_thr_color(zColSpace, hadper_trans_single_den, Nstep, N1, N2, lambda_thr2D,... 359 | lambda_thr3D, tau_match*N1*N1/(255*255), (Ns-1)/2, sigma/255, thrToIncStep, single(Tfor), single(Tinv)', inverse_hadper_trans_single_den, single(thr_mask), 'unused arg', 'unused arg', l2normLumChrom, Wwin2D, smallLN, stepFS ); 360 | estimate_elapsed_time = toc; 361 | 362 | 363 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 364 | %%%% Step 2. Final estimate by collaborative Wiener filtering and using 365 | %%%% the grouping constraint on the chrominances. 366 | %%%% 367 | tic; 368 | yRGB_est = bm3d_wiener_color(zColSpace, y_hat, hadper_trans_single_den, Nstep_wiener, N1_wiener, N2_wiener, ... 369 | 'unused_arg', tau_match_wiener*N1_wiener*N1_wiener/(255*255), (Ns_wiener-1)/2, sigma/255, 'unused arg', single(TforW), single(TinvW)', inverse_hadper_trans_single_den, 'unused arg', 'unused arg', l2normLumChrom, Wwin2D_wiener, smallLNW, stepFSW ); 370 | wiener_elapsed_time = toc; 371 | 372 | yRGB_est = double(yRGB_est); 373 | 374 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 375 | %%%% Convert back to RGB colorspace 376 | %%%% 377 | yRGB_est = function_LumChrom2rgb(yRGB_est, colorspace); 378 | 379 | 380 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 381 | %%%% Calculate final estimate's PSNR and ISNR, print them, and show the 382 | %%%% denoised image 383 | %%%% 384 | PSNR = 0; %% Remains 0 if the true image yRGB is not available 385 | if (~yRGB_is_invalid_image), % then we assume yRGB is a valid image 386 | PSNR = 10*log10(1/mean((yRGB(:)-yRGB_est(:)).^2)); 387 | end 388 | 389 | if dump_output_information == 1, 390 | fprintf(sprintf('FINAL ESTIMATE (total time: %.1f sec), PSNR: %.2f dB\n', ... 391 | wiener_elapsed_time + estimate_elapsed_time, PSNR)); 392 | 393 | figure, imshow(min(max(zRGB,0),1)); title(sprintf('Noisy %s, PSNR: %.3f dB (sigma: %d)', ... 394 | image_name(1:end-4), 10*log10(1/mean((yRGB(:)-zRGB(:)).^2)), sigma)); 395 | 396 | figure, imshow(min(max(yRGB_est,0),1)); title(sprintf('Denoised %s, PSNR: %.3f dB', ... 397 | image_name(1:end-4), PSNR)); 398 | end 399 | 400 | return; 401 | 402 | 403 | 404 | 405 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 406 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 407 | % Some auxiliary functions 408 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 409 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 410 | 411 | 412 | 413 | 414 | function [Tforward, Tinverse] = getTransfMatrix (N, transform_type, dec_levels) 415 | % 416 | % Create forward and inverse transform matrices, which allow for perfect 417 | % reconstruction. The forward transform matrix is normalized so that the 418 | % l2-norm of each basis element is 1. 419 | % 420 | % [Tforward, Tinverse] = getTransfMatrix (N, transform_type, dec_levels) 421 | % 422 | % INPUTS: 423 | % 424 | % N --> Size of the transform (for wavelets, must be 2^K) 425 | % 426 | % transform_type --> 'dct', 'dst', 'hadamard', or anything that is 427 | % listed by 'help wfilters' (bi-orthogonal wavelets) 428 | % 'DCrand' -- an orthonormal transform with a DC and all 429 | % the other basis elements of random nature 430 | % 431 | % dec_levels --> If a wavelet transform is generated, this is the 432 | % desired decomposition level. Must be in the 433 | % range [0, log2(N)-1], where "0" implies 434 | % full decomposition. 435 | % 436 | % OUTPUTS: 437 | % 438 | % Tforward --> (N x N) Forward transform matrix 439 | % 440 | % Tinverse --> (N x N) Inverse transform matrix 441 | % 442 | 443 | if exist('dec_levels') ~= 1, 444 | dec_levels = 0; 445 | end 446 | 447 | if N == 1, 448 | Tforward = 1; 449 | elseif strcmp(transform_type, 'hadamard') == 1, 450 | Tforward = hadamard(N); 451 | elseif (N == 8) & strcmp(transform_type, 'bior1.5')==1 % hardcoded transform so that the wavelet toolbox is not needed to generate it 452 | Tforward = [ 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274; 453 | 0.219417649252501 0.449283757993216 0.449283757993216 0.219417649252501 -0.219417649252501 -0.449283757993216 -0.449283757993216 -0.219417649252501; 454 | 0.569359398342846 0.402347308162278 -0.402347308162278 -0.569359398342846 -0.083506045090284 0.083506045090284 -0.083506045090284 0.083506045090284; 455 | -0.083506045090284 0.083506045090284 -0.083506045090284 0.083506045090284 0.569359398342846 0.402347308162278 -0.402347308162278 -0.569359398342846; 456 | 0.707106781186547 -0.707106781186547 0 0 0 0 0 0; 457 | 0 0 0.707106781186547 -0.707106781186547 0 0 0 0; 458 | 0 0 0 0 0.707106781186547 -0.707106781186547 0 0; 459 | 0 0 0 0 0 0 0.707106781186547 -0.707106781186547]; 460 | elseif (N == 8) & strcmp(transform_type, 'dct')==1 % hardcoded transform so that the signal processing toolbox is not needed to generate it 461 | Tforward = [ 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274 0.353553390593274; 462 | 0.490392640201615 0.415734806151273 0.277785116509801 0.097545161008064 -0.097545161008064 -0.277785116509801 -0.415734806151273 -0.490392640201615; 463 | 0.461939766255643 0.191341716182545 -0.191341716182545 -0.461939766255643 -0.461939766255643 -0.191341716182545 0.191341716182545 0.461939766255643; 464 | 0.415734806151273 -0.097545161008064 -0.490392640201615 -0.277785116509801 0.277785116509801 0.490392640201615 0.097545161008064 -0.415734806151273; 465 | 0.353553390593274 -0.353553390593274 -0.353553390593274 0.353553390593274 0.353553390593274 -0.353553390593274 -0.353553390593274 0.353553390593274; 466 | 0.277785116509801 -0.490392640201615 0.097545161008064 0.415734806151273 -0.415734806151273 -0.097545161008064 0.490392640201615 -0.277785116509801; 467 | 0.191341716182545 -0.461939766255643 0.461939766255643 -0.191341716182545 -0.191341716182545 0.461939766255643 -0.461939766255643 0.191341716182545; 468 | 0.097545161008064 -0.277785116509801 0.415734806151273 -0.490392640201615 0.490392640201615 -0.415734806151273 0.277785116509801 -0.097545161008064]; 469 | elseif (N == 8) & strcmp(transform_type, 'dst')==1 % hardcoded transform so that the PDE toolbox is not needed to generate it 470 | Tforward = [ 0.161229841765317 0.303012985114696 0.408248290463863 0.464242826880013 0.464242826880013 0.408248290463863 0.303012985114696 0.161229841765317; 471 | 0.303012985114696 0.464242826880013 0.408248290463863 0.161229841765317 -0.161229841765317 -0.408248290463863 -0.464242826880013 -0.303012985114696; 472 | 0.408248290463863 0.408248290463863 0 -0.408248290463863 -0.408248290463863 0 0.408248290463863 0.408248290463863; 473 | 0.464242826880013 0.161229841765317 -0.408248290463863 -0.303012985114696 0.303012985114696 0.408248290463863 -0.161229841765317 -0.464242826880013; 474 | 0.464242826880013 -0.161229841765317 -0.408248290463863 0.303012985114696 0.303012985114696 -0.408248290463863 -0.161229841765317 0.464242826880013; 475 | 0.408248290463863 -0.408248290463863 0 0.408248290463863 -0.408248290463863 0 0.408248290463863 -0.408248290463863; 476 | 0.303012985114696 -0.464242826880013 0.408248290463863 -0.161229841765317 -0.161229841765317 0.408248290463863 -0.464242826880013 0.303012985114696; 477 | 0.161229841765317 -0.303012985114696 0.408248290463863 -0.464242826880013 0.464242826880013 -0.408248290463863 0.303012985114696 -0.161229841765317]; 478 | elseif strcmp(transform_type, 'dct') == 1, 479 | Tforward = dct(eye(N)); 480 | elseif strcmp(transform_type, 'dst') == 1, 481 | Tforward = dst(eye(N)); 482 | elseif strcmp(transform_type, 'DCrand') == 1, 483 | x = randn(N); x(1:end,1) = 1; [Q,R] = qr(x); 484 | if (Q(1) < 0), 485 | Q = -Q; 486 | end; 487 | Tforward = Q'; 488 | else %% a wavelet decomposition supported by 'wavedec' 489 | %%% Set periodic boundary conditions, to preserve bi-orthogonality 490 | dwtmode('per','nodisp'); 491 | 492 | Tforward = zeros(N,N); 493 | for i = 1:N 494 | Tforward(:,i)=wavedec(circshift([1 zeros(1,N-1)],[dec_levels i-1]), log2(N), transform_type); %% construct transform matrix 495 | end 496 | end 497 | 498 | %%% Normalize the basis elements 499 | Tforward = (Tforward' * diag(sqrt(1./sum(Tforward.^2,2))))'; 500 | 501 | %%% Compute the inverse transform matrix 502 | Tinverse = inv(Tforward); 503 | 504 | return; 505 | 506 | function [y, A, l2normLumChrom]=function_rgb2LumChrom(xRGB, colormode) 507 | % Forward color-space transformation ( inverse transformation is function_LumChrom2rgb.m ) 508 | % 509 | % Alessandro Foi - Tampere University of Technology - 2005 - 2006 Public release v1.03 (March 2006) 510 | % ----------------------------------------------------------------------------------------------------------------------------------------------- 511 | % 512 | % SYNTAX: 513 | % 514 | % [y A l2normLumChrom] = function_rgb2LumChrom(xRGB, colormode); 515 | % 516 | % INPUTS: 517 | % xRGB is RGB image with range [0 1]^3 518 | % 519 | % colormode = 'opp', 'yCbCr', 'pca', or a custom 3x3 matrix 520 | % 521 | % 'opp' Opponent color space ('opp' is equirange version) 522 | % 'yCbCr' The standard yCbCr (e.g. for JPEG images) 523 | % 'pca' Principal components (note that this transformation is renormalized to be equirange) 524 | % 525 | % OUTPUTS: 526 | % y is color-transformed image (with range typically included in or equal to [0 1]^3, depending on the transformation matrix) 527 | % 528 | % l2normLumChrom (optional) l2-norm of the transformation (useful for noise std calculation) 529 | % A transformation matrix (used necessarily if colormode='pca') 530 | % 531 | % NOTES: - If only two outputs are used, then the second output is l2normLumChrom, unless colormode='pca'; 532 | % - 'opp' is used by default if no colormode is specified. 533 | % 534 | % 535 | % USAGE EXAMPLE FOR PCA TRANSFORMATION: 536 | % %%%% -- forward color transformation -- 537 | % if colormode=='pca' 538 | % [zLumChrom colormode] = function_rgb2LumChrom(zRGB,colormode); % 'colormode' is assigned a 3x3 transform matrix 539 | % else 540 | % zLumChrom = function_rgb2LumChrom(zRGB,colormode); 541 | % end 542 | % 543 | % %%%% [ ... ] Some processing [ ... ] 544 | % 545 | % %%%% -- inverse color transformation -- 546 | % zRGB=function_LumChrom2rgb(zLumChrom,colormode); 547 | % 548 | 549 | if nargin==1 550 | colormode='opp'; 551 | end 552 | change_output=0; 553 | if size(colormode)==[3 3] 554 | A=colormode; 555 | l2normLumChrom=sqrt(sum(A.^2,2)); 556 | else 557 | if strcmp(colormode,'opp') 558 | A=[1/3 1/3 1/3; 0.5 0 -0.5; 0.25 -0.5 0.25]; 559 | end 560 | if strcmp(colormode,'yCbCr') 561 | A=[0.299 0.587 0.114; -0.16873660714285 -0.33126339285715 0.5; 0.5 -0.4186875 -0.0813125]; 562 | end 563 | if strcmp(colormode,'pca') 564 | A=princomp(reshape(xRGB,[size(xRGB,1)*size(xRGB,2) 3]))'; 565 | A=A./repmat(sum(A.*(A>0),2)-sum(A.*(A<0),2),[1 3]); %% ranges are normalized to unitary length; 566 | else 567 | if nargout==2 568 | change_output=1; 569 | end 570 | end 571 | end 572 | 573 | %%%% Make sure that each channel's intensity range is [0,1] 574 | maxV = sum(A.*(A>0),2); 575 | minV = sum(A.*(A<0),2); 576 | yNormal = (reshape(xRGB,[size(xRGB,1)*size(xRGB,2) 3]) * A' - repmat(minV, [1 size(xRGB,1)*size(xRGB,2)])') * diag(1./(maxV-minV)); % put in range [0,1] 577 | y = reshape(yNormal, [size(xRGB,1) size(xRGB,2) 3]); 578 | 579 | %%%% The l2-norm of each of the 3 transform basis elements 580 | l2normLumChrom = diag(1./(maxV-minV))*sqrt(sum(A.^2,2)); 581 | 582 | if change_output 583 | A=l2normLumChrom; 584 | end 585 | 586 | return; 587 | 588 | 589 | 590 | 591 | function yRGB=function_LumChrom2rgb(x,colormode) 592 | % Inverse color-space transformation ( forward transformation is function_rgb2LumChrom.m ) 593 | % 594 | % Alessandro Foi - Tampere University of Technology - 2005 - 2006 Public release v1.03 (March 2006) 595 | % ----------------------------------------------------------------------------------------------------------------------------------------------- 596 | % 597 | % SYNTAX: 598 | % 599 | % yRGB = function_LumChrom2rgb(x,colormode); 600 | % 601 | % INPUTS: 602 | % x is color-transformed image (with range typically included in or equal to [0 1]^3, depending on the transformation matrix) 603 | % 604 | % colormode = 'opp', 'yCbCr', or a custom 3x3 matrix (e.g. provided by the forward transform when 'pca' is selected) 605 | % 606 | % 'opp' opponent color space ('opp' is equirange version) 607 | % 'yCbCr' standard yCbCr (e.g. for JPEG images) 608 | % 609 | % OUTPUTS: 610 | % x is RGB image (with range [0 1]^3) 611 | % 612 | % 613 | % NOTE: 'opp' is used by default if no colormode is specified 614 | % 615 | 616 | if nargin==1 617 | colormode='opp'; 618 | end 619 | if size(colormode)==[3 3] 620 | A=colormode; 621 | B=inv(A); 622 | else 623 | if strcmp(colormode,'opp') 624 | A =[1/3 1/3 1/3; 0.5 0 -0.5; 0.25 -0.5 0.25]; 625 | B =[1 1 2/3;1 0 -4/3;1 -1 2/3]; 626 | end 627 | if strcmp(colormode,'yCbCr') 628 | A=[0.299 0.587 0.114; -0.16873660714285 -0.33126339285715 0.5; 0.5 -0.4186875 -0.0813125]; 629 | B=inv(A); 630 | end 631 | end 632 | 633 | %%%% Make sure that each channel's intensity range is [0,1] 634 | maxV = sum(A.*(A>0),2); 635 | minV = sum(A.*(A<0),2); 636 | xNormal = reshape(x,[size(x,1)*size(x,2) 3]) * diag(maxV-minV) + repmat(minV, [1 size(x,1)*size(x,2)])'; % put in range [0,1] 637 | yRGB = reshape(xNormal * B', [ size(x,1) size(x,2) 3]); 638 | 639 | return; 640 | 641 | -------------------------------------------------------------------------------- /BM3D/CVBM3D.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/CVBM3D.m -------------------------------------------------------------------------------- /BM3D/ClipComp16b.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/ClipComp16b.p -------------------------------------------------------------------------------- /BM3D/IDDBM3D/BM3DDEB_init.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/IDDBM3D/BM3DDEB_init.m -------------------------------------------------------------------------------- /BM3D/IDDBM3D/BlockMatch.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/IDDBM3D/BlockMatch.mexw32 -------------------------------------------------------------------------------- /BM3D/IDDBM3D/BlockMatch.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/IDDBM3D/BlockMatch.mexw64 -------------------------------------------------------------------------------- /BM3D/IDDBM3D/Demo_IDDBM3D.m: -------------------------------------------------------------------------------- 1 | function [isnr, y_hat] = Demo_IDDBM3D(experiment_number, test_image_name) 2 | % ------------------------------------------------------------------------------------------ 3 | % 4 | % Demo software for BM3D-frame based image deblurring 5 | % Public release ver. 0.8 (beta) (June 03, 2011) 6 | % 7 | % ------------------------------------------------------------------------------------------ 8 | % 9 | % This function implements the IDDBM3D image deblurring algorithm proposed in: 10 | % 11 | % [1] A.Danielyan, V. Katkovnik, and K. Egiazarian, "BM3D frames and 12 | % variational image deblurring," submitted to IEEE TIP, May 2011 13 | % 14 | % ------------------------------------------------------------------------------------------ 15 | % 16 | % authors: Aram Danielyan 17 | % Vladimir Katkovnik 18 | % 19 | % web page: http://www.cs.tut.fi/~foi/GCF-BM3D/ 20 | % 21 | % contact: firstname.lastname@tut.fi 22 | % 23 | % ------------------------------------------------------------------------------------------ 24 | % Copyright (c) 2011 Tampere University of Technology. 25 | % All rights reserved. 26 | % This work should be used for nonprofit purposes only. 27 | % ------------------------------------------------------------------------------------------ 28 | % 29 | % Disclaimer 30 | % ---------- 31 | % 32 | % Any unauthorized use of these routines for industrial or profit-oriented activities is 33 | % expressively prohibited. By downloading and/or using any of these files, you implicitly 34 | % agree to all the terms of the TUT limited license (included in the file Legal_Notice.txt). 35 | % ------------------------------------------------------------------------------------------ 36 | 37 | 38 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 39 | % FUNCTION INTERFACE: 40 | % 41 | % [psnr, y_hat] = Demo_IDDBM3D(experiment_number, test_image_name) 42 | % 43 | % INPUT: 44 | % 1) experiment_number: 1 -> PSF 1, sigma^2 = 2 45 | % 2 -> PSF 1, sigma^2 = 8 46 | % 3 -> PSF 2, sigma^2 = 0.308 47 | % 4 -> PSF 3, sigma^2 = 49 48 | % 5 -> PSF 4, sigma^2 = 4 49 | % 6 -> PSF 5, sigma^2 = 64 50 | % 7-13 -> experiments 7-13 are not described in [1]. 51 | % see this file for the blur and noise parameters. 52 | % 2) test_image_name: a valid filename of a grayscale test image 53 | % 54 | % OUTPUT: 55 | % 1) isnr the output improvement in SNR, dB 56 | % 2) y_hat: the restored image 57 | % 58 | % ! The function can work without any of the input arguments, 59 | % in which case, the internal default ones are used ! 60 | % 61 | % To run this demo functions within the BM3D package should be accessible to Matlab 62 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 63 | addpath('../') 64 | 65 | if ~exist('experiment_number','var'), experiment_number=3; end 66 | if ~exist('test_image_name','var'), test_image_name='Cameraman256.png'; end 67 | 68 | filename=test_image_name; 69 | 70 | if 1 % 71 | initType = 'bm3ddeb'; %use output of the BM3DDEB to initialize the algorithm 72 | else 73 | initType = 'zeros'; %use zero image to initialize the algorithm 74 | end 75 | 76 | matchType = 'bm3ddeb'; %build groups using output of the BM3DDEB algorithm 77 | numIt = 200; 78 | 79 | fprintf('Experiment number: %d\n', experiment_number); 80 | fprintf('Image: %s\n', filename); 81 | 82 | %% ------- Generating bservation --------------------------------------------- 83 | disp('--- Generating observation ----'); 84 | y=im2double(imread(filename)); 85 | 86 | [yN,xN]=size(y); 87 | 88 | switch experiment_number 89 | case 1 90 | sigma=sqrt(2)/255; 91 | for x1=-7:7; for x2=-7:7; h(x1+8,x2+8)=1/(x1^2+x2^2+1); end, end; h=h./sum(h(:)); 92 | case 2 93 | sigma=sqrt(8)/255; 94 | s1=0; for a1=-7:7; s1=s1+1; s2=0; for a2=-7:7; s2=s2+1; h(s1,s2)=1/(a1^2+a2^2+1); end, end; h=h./sum(h(:)); 95 | case 3 96 | BSNR=40; 97 | sigma=-1; % if "sigma=-1", then the value of sigma depends on the BSNR 98 | h=ones(9); h=h./sum(h(:)); 99 | case 4 100 | sigma=7/255; 101 | h=[1 4 6 4 1]'*[1 4 6 4 1]; h=h./sum(h(:)); % PSF 102 | case 5 103 | sigma=2/255; 104 | h=fspecial('gaussian', 25, 1.6); 105 | case 6 106 | sigma=8/255; 107 | h=fspecial('gaussian', 25, .4); 108 | %extra experiments 109 | case 7 110 | BSNR=30; 111 | sigma=-1; 112 | h=ones(9); h=h./sum(h(:)); 113 | case 8 114 | BSNR=20; 115 | sigma=-1; 116 | h=ones(9); h=h./sum(h(:)); 117 | case 9 118 | BSNR=40; 119 | sigma=-1; 120 | h=fspecial('gaussian', 25, 1.6); 121 | case 10 122 | BSNR=20; 123 | sigma=-1; 124 | h=fspecial('gaussian', 25, 1.6); 125 | case 11 126 | BSNR=15; 127 | sigma=-1; 128 | h=fspecial('gaussian', 25, 1.6); 129 | case 12 130 | BSNR=40; 131 | sigma=-1; % if "sigma=-1", then the value of sigma depends on the BSNR 132 | h=ones(19); h=h./sum(h(:)); 133 | case 13 134 | BSNR=25; 135 | sigma=-1; % if "sigma=-1", then the value of sigma depends on the BSNR 136 | h=ones(19); h=h./sum(h(:)); 137 | end 138 | 139 | y_blur = imfilter(y, h, 'circular'); % performs blurring (by circular convolution) 140 | 141 | if sigma == -1; %% check whether to use BSNR in order to define value of sigma 142 | sigma=sqrt(norm(y_blur(:)-mean(y_blur(:)),2)^2 /(yN*xN*10^(BSNR/10))); 143 | % Xv% compute sigma from the desired BSNR 144 | end 145 | 146 | %%%% Create a blurred and noisy observation 147 | randn('seed',0); 148 | z = y_blur + sigma*randn(yN, xN); 149 | 150 | bsnr=10*log10(norm(y_blur(:)-mean(y_blur(:)),2)^2 /sigma^2/yN/xN); 151 | psnr_z =PSNR(y,z,1,0); 152 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 153 | 154 | fprintf('Observation BSNR: %4.2f, PSNR: %4.2f\n', bsnr, psnr_z); 155 | 156 | %% ----- Computing initial estimate --------------------- 157 | disp('--- Computing initial estimate ----'); 158 | 159 | [dummy, y_hat_RI,y_hat_RWI,zRI] = BM3DDEB_init(experiment_number, y, z, h, sigma); 160 | 161 | switch lower(initType) 162 | case 'zeros' 163 | y_hat_init=zeros(size(z)); 164 | case 'zri' 165 | y_hat_init=zRI; 166 | case 'ri' 167 | y_hat_init=y_hat_RI; 168 | case 'bm3ddeb' 169 | y_hat_init=y_hat_RWI; 170 | 171 | end 172 | 173 | switch lower(matchType) 174 | case 'z' 175 | match_im = z; 176 | case 'y' 177 | match_im = y; 178 | case 'zri' 179 | match_im = zRI; 180 | case 'ri' 181 | match_im = y_hat_RI; 182 | case 'bm3ddeb' 183 | match_im = y_hat_RWI; 184 | end 185 | 186 | psnr_init = PSNR(y, y_hat_init,1,0); 187 | 188 | fprintf('Initialization method: %s\n', initType); 189 | fprintf('Initial estimate ISNR: %4.2f, PSNR: %4.2f\n', psnr_init-psnr_z, psnr_init); 190 | 191 | %% ------- Core algorithm --------------------- 192 | %------ Description of the parameters of the IDDBM3D function ---------- 193 | %y - true image (use [] if true image is unavaliable) 194 | %z - observed 195 | %h - blurring PSF 196 | %y_hat_init - initial estimate y_0 197 | %match_im - image used to constuct groups and calculate weights g_r 198 | %sigma - standard deviation of the noise 199 | %threshType = 'h'; %use 's' for soft thresholding 200 | %numIt - number of iterations 201 | %gamma - regularization parameter see [1] 202 | %tau - regularization parameter see [1] (thresholding level) 203 | %xi - regularization parameter see [1], it is always set to 1 in this implementation 204 | %showFigure - set to True to display figure with current estimate 205 | %-------------------------------------------------------------------- 206 | 207 | threshType = 'h'; 208 | showFigure = true; 209 | 210 | switch threshType 211 | case {'s'} 212 | gamma_tau_xi_inits= [ 213 | 0.0004509 0.70 1;%1 214 | 0.0006803 0.78 1;%2 215 | 0.0003485 0.65 1;%3 216 | 0.0005259 0.72 1;%4 217 | 0.0005327 0.82 1;%5 218 | 7.632e-05 0.25 1;%6 219 | 0.0005818 0.81 1;%7 220 | 0.001149 1.18 1;%8 221 | 0.0004155 0.74 1;%9 222 | 0.0005591 0.74 1;%10 223 | 0.0007989 0.82 1;%11 224 | 0.0006702 0.75 1;%12 225 | 0.001931 1.83 1;%13 226 | ]; 227 | case {'h'} 228 | gamma_tau_xi_inits= [ 229 | 0.00051 3.13 1;%1 230 | 0.0006004 2.75 1;%2 231 | 0.0004573 2.91 1;%3 232 | 0.0005959 2.82 1;%4 233 | 0.0006018 3.63 1;%5 234 | 0.0001726 2.24 1;%6 235 | 0.00062 2.98 1;%7 236 | 0.001047 3.80 1;%8 237 | 0.0005125 3.00 1;%9 238 | 0.0005685 2.80 1;%10 239 | 0.0005716 2.75 1;%11 240 | 0.0005938 2.55 1;%12 241 | 0.001602 4.16 1;%13 242 | ]; 243 | end 244 | 245 | gamma = gamma_tau_xi_inits(experiment_number,1); 246 | tau = gamma_tau_xi_inits(experiment_number,2)/255*2.7; 247 | xi = gamma_tau_xi_inits(experiment_number,3); 248 | 249 | disp('-------- Start ----------'); 250 | fprintf('Number of iterations to perform: %d\n', numIt); 251 | fprintf('Thresholding type: %s\n', threshType); 252 | 253 | y_hat = IDDBM3D(y, h, z, y_hat_init, match_im, sigma, threshType, numIt, gamma, tau, xi, showFigure); 254 | psnr = PSNR(y,y_hat,1,0); 255 | isnr = psnr-psnr_z; 256 | 257 | disp('-------- Results --------'); 258 | fprintf('Final estimate ISNR: %4.2f, PSNR: %4.2f\n', isnr, psnr); 259 | return; 260 | 261 | end 262 | 263 | function PSNRdb = PSNR(x, y, maxval, borders) 264 | if ~exist('borders', 'var'), borders = 0; end 265 | if ~exist('maxval', 'var'), maxval = 255; end 266 | 267 | xx=borders+1:size(x,1)-borders; 268 | yy=borders+1:size(x,2)-borders; 269 | 270 | PSNRdb = zeros(1,size(x,3)); 271 | for fr=1:size(x,3) 272 | err = x(xx,yy,fr) - y(xx,yy,fr); 273 | PSNRdb(fr) = 10 * log10((maxval^2)/mean2(err.^2)); 274 | end 275 | end -------------------------------------------------------------------------------- /BM3D/IDDBM3D/GroupProcessor.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/IDDBM3D/GroupProcessor.mexw32 -------------------------------------------------------------------------------- /BM3D/IDDBM3D/GroupProcessor.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/IDDBM3D/GroupProcessor.mexw64 -------------------------------------------------------------------------------- /BM3D/IDDBM3D/IDDBM3D.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/IDDBM3D/IDDBM3D.p -------------------------------------------------------------------------------- /BM3D/LEGAL_NOTICE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/LEGAL_NOTICE.txt -------------------------------------------------------------------------------- /BM3D/README.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/README.txt -------------------------------------------------------------------------------- /BM3D/VBM3D.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/VBM3D.m -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_thr.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_thr.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_thr.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_thr.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_thr.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_thr.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_thr.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_thr.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_thr.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_thr.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_wiener.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_wiener.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_wiener.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_wiener.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_wiener.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_wiener.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_wiener.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_wiener.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_CFA_wiener.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_CFA_wiener.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_thr.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_thr.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_thr.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_color.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_color.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_color.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_color.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_thr_color.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_color.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_thr_color.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_color.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_color.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_color.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_color.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_color.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_colored_noise.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_colored_noise.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_colored_noise.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_colored_noise.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_thr_colored_noise.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_colored_noise.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_thr_colored_noise.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_colored_noise.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_colored_noise.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_colored_noise.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_colored_noise.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_colored_noise.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_sharpen_var.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_sharpen_var.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_sharpen_var.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_sharpen_var.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_thr_sharpen_var.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_sharpen_var.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_thr_sharpen_var.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_sharpen_var.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_sharpen_var.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_sharpen_var.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_sharpen_var.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_sharpen_var.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video_c.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video_c.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_thr_video_c.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_thr_video_c.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_wiener.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_wiener.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_color.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_color.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_color.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_color.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_color.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_color.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_color.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_color.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_color.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_color.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_color.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_color.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_colored_noise.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_colored_noise.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_colored_noise.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_colored_noise.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_colored_noise.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_colored_noise.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_colored_noise.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_colored_noise.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_colored_noise.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_colored_noise.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_colored_noise.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_colored_noise.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video.mexa64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video.mexglx -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video.mexmaci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video.mexmaci -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video.mexmaci64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video.mexw64 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video_c.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video_c.mexw32 -------------------------------------------------------------------------------- /BM3D/bm3d_wiener_video_c.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/BM3D/bm3d_wiener_video_c.mexw64 -------------------------------------------------------------------------------- /Bilateral Filtering advanced/3096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering advanced/3096.jpg -------------------------------------------------------------------------------- /Bilateral Filtering advanced/Main_BFad.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering advanced/Main_BFad.m -------------------------------------------------------------------------------- /Bilateral Filtering advanced/methods/bfilter2.m: -------------------------------------------------------------------------------- 1 | 2 | % BFILTER2 Two dimensional bilateral filtering. 3 | % This function implements 2-D bilateral filtering using B = bfilter2(A,W,SIGMA) performs 2-D bilateral filtering 4 | % for the grayscale A. A should be a double precision matrix of size NxMx1 or NxMx3 (i.e., grayscale images, 5 | % respectively) with normalized values in the closed interval [0,1]. The half-size of the Gaussian bilateral 6 | % filter window is defined by W. The standard deviations of the bilateral filter are given by SIGMA, 7 | % where the spatial-domain standard deviation is given by SIGMA(1) and the intensity-domain standard deviation is 8 | % given by SIGMA(2). 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | % Pre-process input and select appropriate filter. 12 | function B = bfilter2(A,w,sigma) 13 | 14 | % Verify that the input image exists and is valid. 15 | if ~exist('A','var') || isempty(A) 16 | error('Input image A is undefined or invalid.'); 17 | end 18 | if ~isfloat(A) || ~sum([1,3] == size(A,3)) || ... 19 | min(A(:)) < 0 || max(A(:)) > 1 20 | error(['Input image A must be a double precision ',... 21 | 'matrix of size NxMx1 or NxMx3 on the closed ',... 22 | 'interval [0,1].']); 23 | end 24 | 25 | % Verify bilateral filter window size. 26 | if ~exist('w','var') || isempty(w) || ... 27 | numel(w) ~= 1 || w < 1 28 | w = 5; 29 | end 30 | w = ceil(w); 31 | 32 | % Verify bilateral filter standard deviations. 33 | if ~exist('sigma','var') || isempty(sigma) || ... 34 | numel(sigma) ~= 2 || sigma(1) <= 0 || sigma(2) <= 0 35 | sigma = [3 0.1]; 36 | end 37 | 38 | % Apply either grayscale or color bilateral filtering. 39 | if size(A,3) == 1 40 | B = bfltGray(A,w,sigma(1),sigma(2)); 41 | else 42 | B = bfltColor(A,w,sigma(1),sigma(2)); 43 | end 44 | 45 | 46 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 47 | % Implements bilateral filtering for grayscale images. 48 | function B = bfltGray(A,w,sigma_d,sigma_r) 49 | 50 | % Pre-compute Gaussian distance weights. 51 | [X,Y] = meshgrid(-w:w,-w:w); 52 | G = exp(-(X.^2)/(sigma_d^2)); 53 | % G = exp(-(X.^2+Y.^2)/(2*sigma_d^2)); 54 | 55 | % Create waitbar. 56 | h = waitbar(0,'Applying bilateral filter...'); 57 | set(h,'Name','Bilateral Filter Progress'); 58 | 59 | % Apply bilateral filter. 60 | dim = size(A); 61 | B = zeros(dim); 62 | for i = 1:dim(1) 63 | for j = 1:dim(2) 64 | 65 | % Extract local region. 66 | iMin = max(i-w,1); 67 | iMax = min(i+w,dim(1)); 68 | jMin = max(j-w,1); 69 | jMax = min(j+w,dim(2)); 70 | I = A(iMin:iMax,jMin:jMax); 71 | 72 | % Compute Gaussian intensity weights. 73 | H = exp(-(I-A(i,j)).^2/(2*sigma_r^2)); 74 | 75 | % Calculate bilateral filter response. 76 | F = H.*G((iMin:iMax)-i+w+1,(jMin:jMax)-j+w+1); 77 | B(i,j) = sum(F(:).*I(:))/sum(F(:)); 78 | 79 | end 80 | waitbar(i/dim(1)); 81 | end 82 | 83 | % Close waitbar. 84 | close(h); 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /Bilateral Filtering advanced/methods/fun_Joint_bfilter2.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering advanced/methods/fun_Joint_bfilter2.p -------------------------------------------------------------------------------- /Bilateral Filtering advanced/methods/jbfilter2.m: -------------------------------------------------------------------------------- 1 | % JBFILTER2 Two dimensional Joint bilateral filtering. 2 | % This function implements 2-D bilateral filtering using 3 | % the method outlined in, however with weights calculated according 4 | % to another image. 5 | % 6 | % B = jbfilter2(D,C,W,SIGMA) performs 2-D bilateral filtering 7 | % for the grayscale or color image A. D should be a double 8 | % precision matrix of size NxMx1 (i.e., grayscale) 9 | % with normalized values in the closed interval [0,1]. 10 | % C should be similar to D, from which the weights are 11 | % calculated, with normalized values in the closed 12 | % interval [0,1]. The half-size of the Gaussian 13 | % bilateral filter window is defined by W. The standard 14 | % deviations of the bilateral filter are given by SIGMA, 15 | % where the spatial-domain standard deviation is given by 16 | % SIGMA(1) and the intensity-domain standard deviation is 17 | % given by SIGMA(2). 18 | 19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 20 | % Pre-process input and select appropriate filter. 21 | function B = jbfilter2(D,C,w,sigma) 22 | 23 | % Verify that the input image exists and is valid. 24 | if ~exist('D','var') || isempty(D) 25 | error('Input image D is undefined or invalid.'); 26 | end 27 | if ~isfloat(D) || ~sum([1,3] == size(D,3)) || ... 28 | min(D(:)) < 0 || max(D(:)) > 1 29 | error(['Input image D must be a double precision ',... 30 | 'matrix of size NxMx1 or NxMx3 on the closed ',... 31 | 'interval [0,1].']); 32 | end 33 | 34 | % Verify bilateral filter window size. 35 | if ~exist('w','var') || isempty(w) || ... 36 | numel(w) ~= 1 || w < 1 37 | w = 5; 38 | end 39 | w = ceil(w); 40 | 41 | % Verify bilateral filter standard deviations. 42 | if ~exist('sigma','var') || isempty(sigma) || ... 43 | numel(sigma) ~= 2 || sigma(1) <= 0 || sigma(2) <= 0 44 | sigma = [3 0.1]; 45 | end 46 | 47 | % Apply either grayscale or color bilateral filtering. 48 | if size(D,3) == 1 49 | B = jbfltGray(D,C,w,sigma(1),sigma(2)); 50 | else 51 | B = jbfltGray(D,C,w,sigma(1),sigma(2)); 52 | end 53 | 54 | 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | % Implements bilateral filtering for grayscale images. 57 | function B = jbfltGray(D,C,w,sigma_d,sigma_r) 58 | 59 | % Pre-compute Gaussian distance weights. 60 | [X,Y] = meshgrid(-w:w,-w:w); 61 | G = exp(-(X.^2+Y.^2)/(2*sigma_d^2)); 62 | 63 | % Create waitbar. 64 | %h = waitbar(0,'Applying bilateral filter on gray image...'); 65 | %set(h,'Name','Bilateral Filter Progress'); 66 | 67 | % Apply bilateral filter. 68 | dim = size(D); 69 | B = zeros(dim); 70 | for i = 1:dim(1) 71 | for j = 1:dim(2) 72 | 73 | % Extract local region. 74 | iMin = max(i-w,1); 75 | iMax = min(i+w,dim(1)); 76 | jMin = max(j-w,1); 77 | jMax = min(j+w,dim(2)); 78 | I = D(iMin:iMax,jMin:jMax); 79 | 80 | % To compute weights from the color image 81 | J = C(iMin:iMax,jMin:jMax); 82 | 83 | % Compute Gaussian intensity weights according to the color image 84 | H = exp(-(J-C(i,j)).^2/(2*sigma_r^2)); 85 | 86 | % Calculate bilateral filter response. 87 | F = H.*G((iMin:iMax)-i+w+1,(jMin:jMax)-j+w+1); 88 | B(i,j) = sum(F(:).*I(:))/sum(F(:)); 89 | 90 | end 91 | %waitbar(i/dim(1)); 92 | end 93 | 94 | % Close waitbar. 95 | %close(h); 96 | -------------------------------------------------------------------------------- /Bilateral Filtering advanced/result/Joint_bfilter2_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering advanced/result/Joint_bfilter2_out.png -------------------------------------------------------------------------------- /Bilateral Filtering advanced/result/bfilter2_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering advanced/result/bfilter2_out.png -------------------------------------------------------------------------------- /Bilateral Filtering advanced/result/re.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering advanced/result/re.png -------------------------------------------------------------------------------- /Bilateral Filtering/3096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering/3096.jpg -------------------------------------------------------------------------------- /Bilateral Filtering/Main_BF.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering/Main_BF.m -------------------------------------------------------------------------------- /Bilateral Filtering/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Bilateral Filtering/Thumbs.db -------------------------------------------------------------------------------- /Bilateral Filtering/bfilter2.m: -------------------------------------------------------------------------------- 1 | 2 | % BFILTER2 Two dimensional bilateral filtering. 3 | % This function implements 2-D bilateral filtering using B = bfilter2(A,W,SIGMA) performs 2-D bilateral filtering 4 | % for the grayscale A. A should be a double precision matrix of size NxMx1 or NxMx3 (i.e., grayscale images, 5 | % respectively) with normalized values in the closed interval [0,1]. The half-size of the Gaussian bilateral 6 | % filter window is defined by W. The standard deviations of the bilateral filter are given by SIGMA, 7 | % where the spatial-domain standard deviation is given by SIGMA(1) and the intensity-domain standard deviation is 8 | % given by SIGMA(2). 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | % Pre-process input and select appropriate filter. 12 | function B = bfilter2(A,w,sigma) 13 | 14 | % Verify that the input image exists and is valid. 15 | if ~exist('A','var') || isempty(A) 16 | error('Input image A is undefined or invalid.'); 17 | end 18 | if ~isfloat(A) || ~sum([1,3] == size(A,3)) || ... 19 | min(A(:)) < 0 || max(A(:)) > 1 20 | error(['Input image A must be a double precision ',... 21 | 'matrix of size NxMx1 or NxMx3 on the closed ',... 22 | 'interval [0,1].']); 23 | end 24 | 25 | % Verify bilateral filter window size. 26 | if ~exist('w','var') || isempty(w) || ... 27 | numel(w) ~= 1 || w < 1 28 | w = 5; 29 | end 30 | w = ceil(w); 31 | 32 | % Verify bilateral filter standard deviations. 33 | if ~exist('sigma','var') || isempty(sigma) || ... 34 | numel(sigma) ~= 2 || sigma(1) <= 0 || sigma(2) <= 0 35 | sigma = [3 0.1]; 36 | end 37 | 38 | % Apply either grayscale or color bilateral filtering. 39 | if size(A,3) == 1 40 | B = bfltGray(A,w,sigma(1),sigma(2)); 41 | else 42 | B = bfltColor(A,w,sigma(1),sigma(2)); 43 | end 44 | 45 | 46 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 47 | % Implements bilateral filtering for grayscale images. 48 | function B = bfltGray(A,w,sigma_d,sigma_r) 49 | 50 | % Pre-compute Gaussian distance weights. 51 | [X,Y] = meshgrid(-w:w,-w:w); 52 | G = exp(-(X.^2+Y.^2)/(2*sigma_d^2)); 53 | 54 | % Create waitbar. 55 | h = waitbar(0,'Applying bilateral filter...'); 56 | set(h,'Name','Bilateral Filter Progress'); 57 | 58 | % Apply bilateral filter. 59 | dim = size(A); 60 | B = zeros(dim); 61 | for i = 1:dim(1) 62 | for j = 1:dim(2) 63 | 64 | % Extract local region. 65 | iMin = max(i-w,1); 66 | iMax = min(i+w,dim(1)); 67 | jMin = max(j-w,1); 68 | jMax = min(j+w,dim(2)); 69 | I = A(iMin:iMax,jMin:jMax); 70 | 71 | % Compute Gaussian intensity weights. 72 | H = exp(-(I-A(i,j)).^2/(2*sigma_r^2)); 73 | 74 | % Calculate bilateral filter response. 75 | F = H.*G((iMin:iMax)-i+w+1,(jMin:jMax)-j+w+1); 76 | B(i,j) = sum(F(:).*I(:))/sum(F(:)); 77 | 78 | end 79 | waitbar(i/dim(1)); 80 | end 81 | 82 | % Close waitbar. 83 | close(h); 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Guided Filtering/3096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Guided Filtering/3096.jpg -------------------------------------------------------------------------------- /Guided Filtering/Main_filter.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Guided Filtering/Main_filter.m -------------------------------------------------------------------------------- /Guided Filtering/boxfilter.m: -------------------------------------------------------------------------------- 1 | function imDst = boxfilter(imSrc, r) 2 | 3 | % BOXFILTER O(1) time box filtering using cumulative sum 4 | % 5 | % - Definition imDst(x, y)=sum(sum(imSrc(x-r:x+r,y-r:y+r))); 6 | % - Running time independent of r; 7 | % - Equivalent to the function: colfilt(imSrc, [2*r+1, 2*r+1], 'sliding', @sum); 8 | % - But much faster. 9 | 10 | [hei, wid] = size(imSrc); 11 | imDst = zeros(size(imSrc)); 12 | 13 | %cumulative sum over Y axis 14 | imCum = cumsum(imSrc, 1); 15 | %difference over Y axis 16 | imDst(1:r+1, :) = imCum(1+r:2*r+1, :); 17 | imDst(r+2:hei-r, :) = imCum(2*r+2:hei, :) - imCum(1:hei-2*r-1, :); 18 | imDst(hei-r+1:hei, :) = repmat(imCum(hei, :), [r, 1]) - imCum(hei-2*r:hei-r-1, :); 19 | 20 | %cumulative sum over X axis 21 | imCum = cumsum(imDst, 2); 22 | %difference over Y axis 23 | imDst(:, 1:r+1) = imCum(:, 1+r:2*r+1); 24 | imDst(:, r+2:wid-r) = imCum(:, 2*r+2:wid) - imCum(:, 1:wid-2*r-1); 25 | imDst(:, wid-r+1:wid) = repmat(imCum(:, wid), [1, r]) - imCum(:, wid-2*r:wid-r-1); 26 | end 27 | 28 | -------------------------------------------------------------------------------- /Guided Filtering/guidedfilter.m: -------------------------------------------------------------------------------- 1 | function q = guidedfilter(I, p, r, eps) 2 | % GUIDEDFILTER O(1) time implementation of guided filter. 3 | % 4 | % - guidance image: I (should be a gray-scale/single channel image) 5 | % - filtering input image: p (should be a gray-scale/single channel image) 6 | % - local window radius: r 7 | % - regularization parameter: eps 8 | 9 | [hei, wid] = size(I); 10 | N = boxfilter(ones(hei, wid), r); % the size of each local patch; N=(2r+1)^2 except for boundary pixels. 11 | 12 | mean_I = boxfilter(I, r) ./ N; 13 | mean_p = boxfilter(p, r) ./ N; 14 | mean_Ip = boxfilter(I.*p, r) ./ N; 15 | cov_Ip = mean_Ip - mean_I .* mean_p; % this is the covariance of (I, p) in each local patch. 16 | 17 | mean_II = boxfilter(I.*I, r) ./ N; 18 | var_I = mean_II - mean_I .* mean_I; 19 | 20 | a = cov_Ip ./ (var_I + eps); % Eqn. (5) in the paper; 21 | b = mean_p - a .* mean_I; % Eqn. (6) in the paper; 22 | 23 | mean_a = boxfilter(a, r) ./ N; 24 | mean_b = boxfilter(b, r) ./ N; 25 | 26 | q = mean_a .* I + mean_b; % Eqn. (8) in the paper; 27 | end -------------------------------------------------------------------------------- /LMS自适应算法滤波器/LMSwanmei1.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/LMS自适应算法滤波器/LMSwanmei1.m -------------------------------------------------------------------------------- /LMS自适应算法滤波器/LMSwanmei2.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/LMS自适应算法滤波器/LMSwanmei2.m -------------------------------------------------------------------------------- /Mean && Median Filtle/3096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Mean && Median Filtle/3096.jpg -------------------------------------------------------------------------------- /Mean && Median Filtle/compute_mean_median.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Mean && Median Filtle/compute_mean_median.m -------------------------------------------------------------------------------- /Mean && Median Filtle/main.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Mean && Median Filtle/main.m -------------------------------------------------------------------------------- /NL-means-C++/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/NL-means-C++/.DS_Store -------------------------------------------------------------------------------- /NL-means-C++/A non-local algorithm for image denoising.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/NL-means-C++/A non-local algorithm for image denoising.pdf -------------------------------------------------------------------------------- /NL-means-C++/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace cv; 5 | using namespace std; 6 | 7 | // additional functions///////////////////////////////////// 8 | //add Salt-and-pepper noise 9 | void addNoiseSoltPepperMono(Mat& src, Mat& dest, double per){//per控制椒盐噪点的含量 10 | cv::RNG rng;//随机数产生器 11 | #pragma omp parallel for 12 | for (int j = 0; jper)d[i] = s[i]; 20 | else{ 21 | //产生0~1均匀分布的随机数为 a2,用于控制该噪点为椒噪点还是盐噪点 22 | double a2 = rng.uniform((double)0, (double)1); 23 | if (a2>0.5)d[i] = 0; 24 | else d[i] = 255; 25 | } 26 | } 27 | } 28 | } 29 | //添加高斯噪声 30 | void addNoiseMono(Mat& src, Mat& dest, double sigma){ 31 | Mat s; 32 | src.convertTo(s, CV_16S); 33 | Mat n(s.size(), CV_16S); 34 | //randn()将n填充为高斯分布均值为0,标准差为sigma的随机数 35 | randn(n, 0, sigma); 36 | Mat temp = s + n;//将原图与高斯噪声叠加在一起输出 37 | temp.convertTo(dest, CV_8U); 38 | /* 39 | CV_8U 8位无符号整型(0-255) 40 | CV_8S 8位有符号整型(-128-127) 41 | CV_16U 16位无符号整型(0-65535) 42 | CV_16S 16位有符号整型(-32768-32767) 43 | CV_32S 32位有符号整型(-2147483648-2147483647) 44 | CV_32F 32为浮点型 45 | CV_64F 64位浮点型 46 | */ 47 | } 48 | 49 | void addNoise(Mat&src, Mat& dest, double sigma, double sprate = 0.0){ 50 | //如果是单通道图片,调用一次增噪函数即可,否则拆分通道分别增噪然后合并 51 | if (src.channels() == 1){ 52 | addNoiseMono(src, dest, sigma);//先添加高斯噪点 53 | if (sprate != 0)addNoiseSoltPepperMono(dest, dest, sprate);//然后添加椒盐噪点 54 | return; 55 | }else{ 56 | Mat s[3]; 57 | Mat d[3]; 58 | split(src, s); 59 | for (int i = 0; isearchWindowSize){ 116 | cout << "searchWindowSize should be larger than templeteWindowSize" << endl; 117 | return; 118 | } 119 | //如果dest为空,则用与src相同大小的同型空白矩阵填充 120 | if (dest.empty())dest = Mat::zeros(src.size(), src.type()); 121 | 122 | const int tr = templeteWindowSize >> 1;//tr为邻域的中心位置 123 | const int sr = searchWindowSize >> 1;//sr为搜索域的中心位置 124 | const int bb = sr + tr;//需增加的边界宽度 125 | const int D = searchWindowSize*searchWindowSize;//搜索域中的元素个数 126 | const int H = D / 2 + 1;//搜索域中的中心点位置 127 | const double div = 1.0 / (double)D;//均匀分布时,搜索域中的每个点的权重大小 128 | const int tD = templeteWindowSize*templeteWindowSize;//邻域中的元素个数 129 | const double tdiv = 1.0 / (double)(tD);//均匀分布时,搜索域中的每个点的权重大小 130 | 131 | //create large size image for bounding box; 132 | //copyMakeBorder()的参考用法:https://blog.csdn.net/qianqing13579/article/details/42323397 133 | Mat im; 134 | copyMakeBorder(src, im, bb, bb, bb, bb, cv::BORDER_DEFAULT); 135 | 136 | //weight computation; 137 | vector weight(256 * 256 * src.channels()); 138 | double* w = &weight[0]; 139 | const double gauss_sd = (sigma == 0.0) ? h : sigma;//高斯标准差 140 | double gauss_color_coeff = -(1.0 / (double)(src.channels())) * (1.0 / (h*h));//高斯颜色系数 141 | int emax=0; 142 | //w[i]保存方差,即邻域平均欧氏距离对应的高斯加权权重,供后面计算出欧式距离后调用 143 | for (int i = 0; i < 256 * 256 * src.channels(); i++){ 144 | double v = std::exp(max(i - 2.0*gauss_sd*gauss_sd, 0.0)*gauss_color_coeff); 145 | w[i] = v; 146 | if (v<0.001){ 147 | emax = i; 148 | break; 149 | } 150 | } 151 | for (int i = emax; i < 256 * 256 * src.channels(); i++)w[i] = 0.0; 152 | 153 | if (src.channels() == 3){ 154 | //mat.step 155 | //http://blog.sina.com.cn/s/blog_15183f5750102wu94.html 156 | //https://www.cnblogs.com/wangguchangqing/p/4016179.html 157 | const int cstep = (int)im.step - templeteWindowSize * 3; 158 | const int csstep = (int)im.step - searchWindowSize * 3; 159 | #pragma omp parallel for 160 | for (int j = 0; j(r); 213 | d[1] = saturate_cast(g); 214 | d[2] = saturate_cast(b); 215 | d += 3; 216 | }//i 217 | delete[] ww; 218 | delete[] nw; 219 | }//j 220 | }else if (src.channels() == 1){ 221 | const int cstep = (int)im.step - templeteWindowSize;//在邻域比较时,从邻域的上一行末尾跳至下一行开头 222 | const int csstep = (int)im.step - searchWindowSize;//搜索域循环中,从搜索域的上一行末尾跳至下一行开头 223 | #pragma omp parallel for 224 | //下面两层嵌套循环:遍历每个图片的像素点 225 | for (int j = 0; j(v); 274 | }//i 275 | delete[] ww; 276 | delete[] nw; 277 | }//j 278 | } 279 | } 280 | 281 | int main(int argc, char** argv){ 282 | //(1) Reading image and add noise(standart deviation = 15) 283 | const double noise_sigma = 20.0; 284 | Mat src = imread("/Users/linweichen/Desktop/lena.jpg", 1); 285 | Mat snoise; 286 | Mat dest; 287 | addNoise(src, snoise, noise_sigma); 288 | //imwrite("/Users/linweichen/Desktop/lena_noise.jpg",snoise); 289 | 290 | //(2) preview conventional method with PSNR 291 | //(2-1) RAW 292 | cout << "RAW: " << calcPSNR(src, snoise) << endl << endl; 293 | //imwrite("noise.png", snoise); 294 | 295 | //(2-2) Gaussian Filter (7x7) sigma = 5 296 | int64 pre = getTickCount(); 297 | GaussianBlur(snoise, dest, Size(7, 7), 5); 298 | cout << "time: " << 1000.0*(getTickCount() - pre) / (getTickFrequency()) << " ms" << endl; 299 | cout << "gaussian: " << calcPSNR(src, dest) << endl << endl; 300 | //imwrite("gaussian.png", dest); 301 | imshow("gaussian", dest); 302 | 303 | //(2-3) median Filter (3x3) 304 | pre = getTickCount(); 305 | medianBlur(snoise, dest, 3); 306 | cout << "time: " << 1000.0*(getTickCount() - pre) / (getTickFrequency()) << " ms" << endl; 307 | cout << "median: " << calcPSNR(src, dest) << endl << endl; 308 | //imwrite("median.png", dest); 309 | imshow("median", dest); 310 | 311 | //(2-4) Bilateral Filter (7x7) color sigma = 35, space sigma = 5 312 | pre = getTickCount(); 313 | bilateralFilter(snoise, dest, 7, 35, 5); 314 | cout << "time: " << 1000.0*(getTickCount() - pre) / (getTickFrequency()) << " ms" << endl; 315 | cout << "bilateral: " << calcPSNR(src, dest) << endl << endl; 316 | //imwrite("bilateral.png", dest); 317 | imshow("bilateral", dest); 318 | 319 | //(3) analizing of performance of Nonlocal means filter 320 | pre = getTickCount(); 321 | nonlocalMeansFilter(snoise, dest, 3,7 , noise_sigma, noise_sigma); 322 | cout << "time: " << 1000.0*(getTickCount() - pre) / (getTickFrequency()) << " ms" << endl; 323 | cout << "nonlocal: " << calcPSNR(src, dest) << endl << endl; 324 | //imwrite("nonlocal.png", dest); 325 | imshow("original", src); 326 | imshow("noise", snoise); 327 | imshow("Non-local Means Filter", dest); 328 | while(waitKey(0)); 329 | return 0; 330 | } 331 | 332 | 333 | -------------------------------------------------------------------------------- /NL-means-C++/pic/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/NL-means-C++/pic/.DS_Store -------------------------------------------------------------------------------- /NL-means-C++/pic/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/NL-means-C++/pic/screenshot.png -------------------------------------------------------------------------------- /PM/denoisePM.m: -------------------------------------------------------------------------------- 1 | function [sol, resimg] = denoisePM(img, params, edgestopfct, startsol, precision) 2 | % DENOISEPM Denoise an image with Perona-Malik isotropic diffusion 3 | % [SOL, RESIMG] = denoisePM(IMG, PARAMS, EDGESTOPFCT, STARTSOL) 4 | % SOL: Solution. The diffused image. 5 | % RESIMG: Optional residual image. 6 | % IMG: 2D image matrix 7 | % PARAMS: Parameter struct: 8 | % In this function, the following parameters are used: 9 | % DENOISEPM_SIGMA: standard derivation value/list of the edge-stopping 10 | % function 11 | % DENOISEPM_TIME: Time parameter - amount of diffusion applied. 12 | % DENOISEPM_SMOOTH: standart derivation of pre-gradient-computation 13 | % smoothing (suggestion: something small, for example 0.5) 14 | % DENOISEPM_MAXITER: Maximum number of iterations. (suggestion: 1000) 15 | % EDGESTOPFCT: edge-stopping function used. Possibilities are: 'perona', 16 | % 'tukey', 'tukeylog', 'complex'. Default: tukey 17 | % STARTSOL: Initialisation for the solution, by default the input image 18 | % 19 | % Calling examples: 20 | % 21 | % First Example: 0..255 scaled intensity values 22 | % params.DENOISEPM_SIGMA = 20; 23 | % params.DENOISEPM_TIME = 3; 24 | % params.DENOISEPM_SMOOTH = 0; 25 | % params.DENOISEPM_MAXITER = 1000; 26 | % sol = denoisePM(img, params); 27 | % 28 | % Second example: 0..255 scaled intensity values 29 | % params.DENOISEPM_SIGMA = [20 pi/1000]; 30 | % params.DENOISEPM_TIME = 3; 31 | % params.DENOISEPM_SMOOTH = 1; 32 | % params.DENOISEPM_MAXITER = 200; 33 | % sol = denoisePM(img, params, 'complex'); 34 | % 35 | % A list of cites for the different edgestopfunctions: 36 | % 37 | % 'perona' 38 | % P. Perona, J. Malik: Scale-Space and Edge Detection Using Anisotropic 39 | % Diffusion, IEEE Trans. Pattern Anal. Mach. Intell., 40 | % 12(7), 1990, 629?639. 41 | % 42 | % 'tuckey' 43 | % M. J. Black, G. Sapiro, D. Marimont, D. Heeger: Robust anisotropic 44 | % diffusion, IEEE Trans. on Image Processing, 45 | % 7(3), 1998, 421?432. 46 | % 47 | % 'complex' 48 | % G. Gilboa, N. A. Sochen, Y.Y. Zeevi, ?Image Enhancement and Denoising by 49 | % Complex Diffusion Processes?, 50 | % IEEE Trans. Pattern Anal. Mach. Intell. 26(8), 1020?1036 (2004). 51 | % 52 | % The corresponding 'log' version compute their coefficients on a 53 | % logarithmic version of the image. 54 | % 55 | % The lagged diffusitivy solution of the PDE was proposed in: 56 | % C. R. Vogel, M. E. Oman: Iterative Methods for Total Variation Denoising, 57 | % SIAM Journal on Scientific Computing, 17(1), 1996, 227?238. 58 | % 59 | % Further discussion on the method can be found in: 60 | % T. Chan, P. Mulet: On the convergence of the lagged diffusivity fixed 61 | % point method in total variation image restoration, 62 | % SIAM journal on numerical analysis, 36(2), 1999, 354?367. 63 | % 64 | % Implementation by Markus Mayer, Pattern Recognition Lab, 65 | % University of Erlangen-Nuremberg, 2008 66 | % This version was revised and commented in August 2010 67 | % 68 | % You may use this code as you want. I would be grateful if you would go to 69 | % my homepage look for articles that you find worth citing in your next 70 | % publication: 71 | % http://www5.informatik.uni-erlangen.de/en/our-team/mayer-markus 72 | % Thanks, Markus 73 | 74 | if nargin < 2 75 | error('Not enough input arguments.'); 76 | end 77 | if nargin < 3 78 | edgestopfct = 'tukey'; 79 | end 80 | if nargin < 5 81 | presicion = 'single'; 82 | end 83 | 84 | sigma = params.DENOISEPM_SIGMA; 85 | t = params.DENOISEPM_TIME; 86 | 87 | % Add a 1-border to the image 88 | img = [img(:,1), img, img(:,size(img,2))]; 89 | img = vertcat(img(1,:), img, img(size(img,1),:)); 90 | 91 | iter = 0; % iteration counter 92 | 93 | if nargin < 4 94 | sol = img; % solution initialisation: original image 95 | else 96 | sol = [startsol(:,1), startsol, startsol(:,size(startsol,2))]; 97 | sol = vertcat(sol(1,:), sol, sol(size(sol,1),:)); 98 | end 99 | 100 | stencilN = zeros(size(img, 1), size(img, 2), presicion); 101 | stencilS = zeros(size(img, 1), size(img, 2), presicion); 102 | stencilE = zeros(size(img, 1), size(img, 2), presicion); 103 | stencilW = zeros(size(img, 1), size(img, 2), presicion); 104 | stencilM = zeros(size(img, 1), size(img, 2), presicion); 105 | 106 | resimg = img; 107 | resold = 1e+20; % old residual 108 | resarr = [1e+20 1e+20 1e+20]; % array of the last 3 residual changes 109 | 110 | % diffusion iteration stoping criteria 111 | % if the sum of the last 5 residuals is negative, a completion of the 112 | % calculation is assumed. 113 | % Algorithm: No explicit time marching is applied, instead the linear 114 | % equation system the diffusion process creates for one timestep is solved 115 | % with lagged diffusivity by R/B Gauss-Seidel Iteration steps 116 | if params.DENOISEPM_SMOOTH ~= 0 117 | gauss1 = fspecial('gaussian', ... 118 | round(params.DENOISEPM_SMOOTH * params.DENOISEPM_SMOOTH + 1), ... 119 | params.DENOISEPM_SMOOTH); 120 | end 121 | 122 | while (sum(resarr) > 0) && (iter < params.DENOISEPM_MAXITER); 123 | % Calculation of the edge-stoping function 124 | 125 | if params.DENOISEPM_SMOOTH ~= 0 126 | smoothsol = imfilter(sol, gauss1, 'symmetric'); 127 | 128 | if strcmp(edgestopfct, 'tukey') 129 | coeff = tukeyEdgeStop(smoothsol, sigma); 130 | elseif strcmp(edgestopfct, 'perona') 131 | coeff = peronaEdgeStop(smoothsol, sigma); 132 | elseif strcmp(edgestopfct, 'tukeylog') 133 | coeff = tukeyEdgeStopLog(smoothsol, sigma); 134 | elseif strcmp(edgestopfct, 'complex') 135 | coeff = complexEdgeStop(smoothsol, sigma); 136 | else 137 | error('Give a suitable edgestopfct argument'); 138 | end 139 | else 140 | if strcmp(edgestopfct, 'tukey') 141 | coeff = tukeyEdgeStop(sol, sigma); 142 | elseif strcmp(edgestopfct, 'perona') 143 | coeff = peronaEdgeStop(sol, sigma); 144 | elseif strcmp(edgestopfct, 'tukeylog') 145 | coeff = tukeyEdgeStopLog(sol, sigma); 146 | elseif strcmp(edgestopfct, 'complex') 147 | coeff = complexEdgeStop(sol, sigma); 148 | else 149 | error('Give a suitable edgestopfct argument'); 150 | end 151 | end 152 | 153 | coeff = coeff * t; 154 | 155 | % stencil computation 156 | stencilN(2:end-1, 2:end-1) = (coeff(2:end-1, 2:end-1) + coeff(1:end-2, 2:end-1))/2; 157 | stencilS(2:end-1, 2:end-1) = (coeff(2:end-1, 2:end-1) + coeff(3:end, 2:end-1))/2; 158 | stencilE(2:end-1, 2:end-1) = (coeff(2:end-1, 2:end-1) + coeff(2:end-1, 3:end))/2; 159 | stencilW(2:end-1, 2:end-1) = (coeff(2:end-1, 2:end-1) + coeff(2:end-1, 1:end-2))/2; 160 | 161 | stencilM = stencilN + stencilS + stencilE + stencilW + 1; 162 | 163 | % solution computation: R/B Gauss Seidel 164 | sol(2:2:end-1, 2:2:end-1) = (img(2:2:end-1, 2:2:end-1) ... 165 | + (stencilN(2:2:end-1, 2:2:end-1) .* sol(1:2:end-2, 2:2:end-1) ... 166 | + stencilS(2:2:end-1, 2:2:end-1) .* sol(3:2:end, 2:2:end-1) ... 167 | + stencilE(2:2:end-1, 2:2:end-1) .* sol(2:2:end-1, 3:2:end)... 168 | + stencilW(2:2:end-1, 2:2:end-1) .* sol(2:2:end-1, 1:2:end-2))) ... 169 | ./ stencilM(2:2:end-1, 2:2:end-1); 170 | 171 | sol(3:2:end, 3:2:end) = (img(3:2:end, 3:2:end) ... 172 | + (stencilN(3:2:end, 3:2:end) .* sol(2:2:end-1, 3:2:end) ... 173 | + stencilS(3:2:end, 3:2:end) .* sol(4:2:end, 3:2:end) ... 174 | + stencilE(3:2:end, 3:2:end) .* sol(3:2:end, 4:2:end) ... 175 | + stencilW(3:2:end, 3:2:end) .* sol(3:2:end, 2:2:end-1))) ... 176 | ./ stencilM(3:2:end, 3:2:end); 177 | 178 | sol(2:2:end-1, 3:2:end) = (img(2:2:end-1, 3:2:end) ... 179 | + (stencilN(2:2:end-1, 3:2:end) .* sol(1:2:end-2, 3:2:end) ... 180 | + stencilS(2:2:end-1, 3:2:end) .* sol(3:2:end, 3:2:end) ... 181 | + stencilE(2:2:end-1, 3:2:end) .* sol(2:2:end-1, 4:2:end) ... 182 | + stencilW(2:2:end-1, 3:2:end) .* sol(2:2:end-1, 2:2:end-1))) ... 183 | ./ stencilM(2:2:end-1, 3:2:end); 184 | 185 | sol(3:2:end, 2:2:end-1) = (img(3:2:end, 2:2:end-1) ... 186 | + (stencilN(3:2:end, 2:2:end-1) .* sol(2:2:end-1, 2:2:end-1) ... 187 | + stencilS(3:2:end, 2:2:end-1) .* sol(4:2:end, 2:2:end-1) ... 188 | + stencilE(3:2:end, 2:2:end-1) .* sol(3:2:end, 3:2:end) ... 189 | + stencilW(3:2:end, 2:2:end-1) .* sol(3:2:end, 1:2:end-2))) ... 190 | ./ stencilM(3:2:end, 2:2:end-1); 191 | 192 | % residual computation 193 | resimg(2:end-1, 2:end-1) = (-(stencilN(2:end-1, 2:end-1) .* sol(1:end-2, 2:end-1) ... 194 | + stencilS(2:end-1, 2:end-1) .* sol(3:end , 2:end-1) ... 195 | + stencilE(2:end-1, 2:end-1) .* sol(2:end-1, 3:end) ... 196 | + stencilW(2:end-1, 2:end-1) .* sol(2:end-1, 1:end-2))) ... 197 | + stencilM(2:end-1, 2:end-1) .* sol(2:end-1, 2:end-1) - img(2:end-1, 2:end-1); 198 | 199 | res = sum(sum(real(resimg) .* real(resimg))); 200 | 201 | resdiff = resold - res; 202 | resold = res; 203 | resarr = [resdiff resarr(1, 1:(size(resarr, 2)-1))]; 204 | 205 | % duplicate edges as new borders 206 | sol = [sol(:,2), sol(:, 2:end-1), sol(:,end-1)]; 207 | sol = vertcat(sol(2,:), sol(2:end-1, :), sol(end-1,:)); 208 | 209 | % disp(resarr); 210 | iter = iter + 1; 211 | end 212 | 213 | % Remove border 214 | sol = sol(2:(size(sol,1)-1), 2:(size(sol,2)-1)); 215 | if(nargout > 1) 216 | resimg = resimg(2:(size(sol,1)-1), 2:(size(sol,2)-1)); 217 | end; 218 | 219 | %-------------------------------------------------------------------------- 220 | 221 | function r = tukeyEdgeStop(img, sigma) 222 | % TUKEYEDGESTOP Tukey Edge-Stopping function on matrix 223 | % tukeyEdgeStop(img, sigma) 224 | % img: 2D image matrix 225 | % sigma: standard derivation parameter 226 | 227 | r = gradientAbsolute(img); 228 | r = 1 - r .* r / (sigma * sigma); 229 | r(r < 0) = 0; 230 | r = r .* r; 231 | 232 | %-------------------------------------------------------------------------- 233 | 234 | function r = tukeyEdgeStopLog(img, sigma) 235 | % TUKEYEDGESTOPLOG Tukey Edge-Stopping function on matrix, added log 236 | % tukeyEdgeStopLog(img, sigma) 237 | % img: 2D image matrix 238 | % sigma: standard derivation parameter 239 | 240 | r = log(img); 241 | r = gradientAbsolute(r); 242 | r = 1 - r .* r / (sigma * sigma); 243 | r(r < 0) = 0; 244 | r = r .* r; 245 | 246 | %-------------------------------------------------------------------------- 247 | 248 | function r = peronaEdgeStop(img, sigma) 249 | % PERONAEDGESTOP Perona Edge-Stopping function on matrix 250 | % peronaEdgeStop(img, sigma) 251 | % img: 2D image matrix 252 | % sigma: standard derivation parameter 253 | 254 | r = gradientAbsolute(img); 255 | r = exp(- r .* r / (2 * sigma * sigma)); 256 | 257 | %-------------------------------------------------------------------------- 258 | 259 | function r = complexEdgeStop(img, sigma) 260 | % COMPLEXEDGESTOP Complex edge-stopping function by Gilboa 261 | % complexEdgeStop(img, sigma) 262 | % img: 2D image matrix, can be complex 263 | % sigma (2)-Vector, first entry: Diffusion stopper, second: theta 264 | 265 | j = sqrt(-1); 266 | r = gradientAbsolute(img); 267 | r = exp(j * sigma(2))./(1+(imag(r) / (sigma(1) * sigma(2))) .^ 2 ); 268 | 269 | % r = exp(j .* sigma(2))./(1+(imag(r) ./ (sigma(1) .* angle(img))) .^ 2 ); 270 | % r = exp(j .* angle(img))./(1+(imag(r) ./ (sigma(1) .* angle(img))) .^ 2 ); 271 | 272 | %-------------------------------------------------------------------------- 273 | 274 | function r = gradientAbsolute(A) 275 | % GRADIENTABSOLUTE Returns the absolute value of the gradient 276 | % gradientAbsolute(A): A must be a 2D matrix 277 | 278 | [Gx, Gy] = gradient(A); 279 | r = sqrt(Gx .* Gx + Gy .* Gy); 280 | 281 | 282 | -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/Barbara500.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/TVdenoising/TV去噪模型2/Barbara500.bmp -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/In.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/TVdenoising/TV去噪模型2/In.mat -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/TV1.m: -------------------------------------------------------------------------------- 1 | function [PSNRR,ImMAE,Is]=TV1(Io,In,tau,iter,lamda) 2 | In=double(In); 3 | Is=In; 4 | t=0; 5 | for i=1:iter 6 | i 7 | tic 8 | %lamda=max(sum(sum(div(Is)*(Is-In)))./(xgm^2*255*255),0) 9 | Is=Is+tau.*div(Is)-tau.*lamda*(Is-In); 10 | figure(90) 11 | imshow(Is,[]); 12 | toc 13 | t=t+toc; 14 | PSNRR(i)=psnr(Is,Io); 15 | NowPSNR=PSNRR(i) 16 | NowSNR=snr(Is,Io) 17 | NowMAE=mae(Is,Io) 18 | ImMAE(i)=NowMAE; 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/div.m: -------------------------------------------------------------------------------- 1 | function I=div(Io) 2 | ep=0.0001; 3 | Io=double(Io); 4 | [m,n]=size(Io); 5 | T=ones(m,n); 6 | 7 | backx=Io(:,[2:end end])-Io; 8 | backy=Io([2:end end],:)-Io; 9 | 10 | forwardx=Io-Io(:,[1 1:end-1]); 11 | forwardy=Io-Io([1 1:end-1],:); 12 | 13 | term1=backx./(((backx.^2+minmod(backy,forwardy).^2)+ep).^(0.5)); 14 | term2=backy./(((backy.^2+minmod(backx,forwardx).^2)+ep).^(0.5)); 15 | 16 | I1=term1-term1(:,[1 1:end-1]); 17 | I2=term2-term2([1 1:end-1],:); 18 | 19 | I=I1+I2; 20 | end 21 | -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/mae.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % >>>> IMAGEBOX >>>> JX >>>> UCLA >>>> 3 | % 4 | % image toolbox 5 | % MATLAB file 6 | % 7 | % rmse.m 8 | % compute root-mean-square-error (RMSE) of a noisy signal/image 9 | % 10 | % function s = rmse(noisydata, original) 11 | % 12 | % input: noisydata: noisy data 13 | % original: clean data 14 | % output: s: RMSE value 15 | % example: s = rmse(f, eu); 16 | % 17 | % created: 08/23/2009 18 | % last modified: 12/03/2005 19 | % author: gzc@email.jlu.edu.cn 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | 22 | function E = mae(noisydata, original) 23 | 24 | noisydata=double(noisydata); 25 | original=double(original); 26 | 27 | [m,n] = size(noisydata); 28 | 29 | 30 | noise = abs(noisydata - original); 31 | nostotal = sum(sum(noise)); 32 | 33 | E=nostotal/(m*n); 34 | 35 | return 36 | -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/minmod.m: -------------------------------------------------------------------------------- 1 | function c=minmod(a,b) 2 | c=(sign(a)./2+sign(b)./2).*min(abs(a),abs(b)); 3 | end -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/pepper.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/TVdenoising/TV去噪模型2/pepper.bmp -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/psnr.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % >>>> IMAGEBOX >>>> JX >>>> UCLA >>>> 3 | % 4 | % image toolbox 5 | % MATLAB file 6 | % 7 | % snr.m 8 | % compute peak signal-to-noise-ratio (SNR) of a noisy signal/image 9 | % 10 | % function s = psnr(noisydata, original) 11 | % 12 | % input: noisydata: noisy data 13 | % original: clean data 14 | % output: s: PSNR value 15 | % example: s = snr(f, eu); 16 | % 17 | % created: 03/15/2008 18 | % last modified: 12/03/2005 19 | % author: lubibo@gmail.com 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | 22 | function s = psnr(noisydata, original) 23 | 24 | noisydata=double(noisydata); 25 | original=double(original); 26 | 27 | [m,n] = size(noisydata); 28 | 29 | peak=255*255*m*n; 30 | 31 | noise = noisydata - original; 32 | nostotal = sum(sum(noise.*noise)); 33 | 34 | if nostotal == 0 35 | s = 999.99; %% INF. clean image 36 | else 37 | s = 10 * log10(peak./nostotal); 38 | end 39 | 40 | return 41 | -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/snr.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % >>>> IMAGEBOX >>>> JX >>>> UCLA >>>> 3 | % 4 | % image toolbox 5 | % MATLAB file 6 | % 7 | % snr.m 8 | % compute signal-to-noise-ratio (SNR) of a noisy signal/image 9 | % 10 | % function s = snr(noisydata, original) 11 | % 12 | % input: noisydata: noisy data 13 | % original: clean data 14 | % output: s: SNR value 15 | % example: s = snr(f, eu); 16 | % 17 | % created: 11/23/2003 18 | % last modified: 12/03/2005 19 | % author: jjxu@ucla 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | 22 | function s = snr(noisydata, original) 23 | 24 | noisydata = double(noisydata); 25 | original = double(original); 26 | 27 | mean_original = mean(original(:)); 28 | tmp = original - mean_original; 29 | var_original = sum(sum(tmp.*tmp)); 30 | 31 | noise = noisydata - original; 32 | mean_noise = mean(noise(:)); 33 | tmp = noise - mean_noise; 34 | var_noise = sum(sum(tmp.*tmp)); 35 | 36 | if var_noise == 0 37 | s = 999.99; %% INF. clean image 38 | else 39 | s = 10 * log10(var_original / var_noise); 40 | end 41 | return 42 | -------------------------------------------------------------------------------- /TVdenoising/TV去噪模型2/test.m: -------------------------------------------------------------------------------- 1 | %% 程序分享 2 | % 个人博客 www.aomanhao.top 3 | % Github https://github.com/AomanHao 4 | % CSDN https://blog.csdn.net/Aoman_Hao 5 | %-------------------------------------- 6 | 7 | clear all 8 | close all 9 | I=imread('pepper.bmp'); 10 | %I=imread('Barbara500.bmp'); 11 | 12 | I=rgb2gray(I); 13 | I=double(I); 14 | figure(1),imshow(I,[]); 15 | std_n=20; 16 | var_n=std_n^2; 17 | NI=randn(size(I))*std_n; 18 | In=I+NI; 19 | % 20 | save('In'); 21 | % load('In'); 22 | figure(2);imshow(In,[]); 23 | tau=0.15; 24 | iter=130; 25 | xgm=30; 26 | lamda=0.05; 27 | [PSNRR,ImMAE,Is]=TV1(I,In,tau,iter,lamda); 28 | 29 | figure(4),imshow(Is,[]); 30 | figure(5),imshow(Is-In,[]); 31 | %��PSNRR&ImMAEͼ 32 | figure(8); 33 | x=1:iter; 34 | plot(x,PSNRR); 35 | title('PSNRR'); 36 | figure(10); 37 | x=1:iter; 38 | plot(x,ImMAE); 39 | title('ImMAE'); 40 | % figure(11) 41 | % x=1:iter; 42 | % plot(x,SNR); 43 | % title('SNR'); 44 | figure(15) 45 | mesh(Is); -------------------------------------------------------------------------------- /Wiener Filtering/3096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Wiener Filtering/3096.jpg -------------------------------------------------------------------------------- /Wiener Filtering/Main_wiener.asv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Wiener Filtering/Main_wiener.asv -------------------------------------------------------------------------------- /Wiener Filtering/Main_wiener.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/Wiener Filtering/Main_wiener.m -------------------------------------------------------------------------------- /形态学滤波/3096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/形态学滤波/3096.jpg -------------------------------------------------------------------------------- /形态学滤波/Main_filter.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AomanHao/Matlab-Image-Denoise/dce742a7ee41fe93ab34ff917e78d0b0442bcd0f/形态学滤波/Main_filter.m -------------------------------------------------------------------------------- /形态学滤波/w_ColorRecons_CO.m: -------------------------------------------------------------------------------- 1 | function output_f=w_ColorRecons_CO(f,radius) 2 | se=strel('disk',radius); 3 | if length(size(f))<3 4 | disp('Please input a color image!'); 5 | else 6 | %% 7 | f=double(f);f_r=f(:,:,1);f_g=f(:,:,2);f_b=f(:,:,3); 8 | f_pca=double(PCA_color(f));f1=f_pca(:,:,1);f2=f_pca(:,:,2); 9 | %% step2 data transformation 10 | data1=f1*10^3+f2+f_r*10^-3+f_g*10^-6+f_b*10^-9;Max1=max(max(data1)); 11 | data2=f1*10^3+f2+f_g*10^-3+f_r*10^-6+f_b*10^-9;Max2=max(max(data2)); 12 | data3=f1*10^3+f2+f_b*10^-3+f_r*10^-6+f_g*10^-9;Max3=max(max(data3)); 13 | %% step 3 data processing 14 | imput_data1=imerode(data1,se); 15 | imput_data2=imerode(data2,se); 16 | imput_data3=imerode(data3,se); 17 | f_rec1=imreconstruct(imput_data1,data1); 18 | f_rec2=imreconstruct(imput_data2,data2); 19 | f_rec3=imreconstruct(imput_data3,data3); 20 | imput2_data1=imerode(Max1-f_rec1,se); 21 | imput2_data2=imerode(Max2-f_rec2,se); 22 | imput2_data3=imerode(Max3-f_rec3,se); 23 | f_g1=Max1-imreconstruct(imput2_data1,Max1-f_rec1); 24 | f_g2=Max2-imreconstruct(imput2_data2,Max2-f_rec2); 25 | f_g3=Max3-imreconstruct(imput2_data3,Max3-f_rec3); 26 | end 27 | %% return to RGB format 28 | tt1=f_g1-floor(f_g1); 29 | tt2=f_g2-floor(f_g2); 30 | tt3=f_g3-floor(f_g3); 31 | g1_r=floor(tt1*10^3); 32 | g1_g=floor(tt2*10^3); 33 | g1_b=floor(tt3*10^3); 34 | output_f=cat(3,uint8(g1_r),uint8(g1_g),uint8(g1_b)); 35 | -------------------------------------------------------------------------------- /形态学滤波/w_recons_CO.m: -------------------------------------------------------------------------------- 1 | % morphological closing reconstruction 2 | function fobrcbr=w_recons_CO(f,se) 3 | fe=imerode(f,se); 4 | fobr=imreconstruct(fe,f); 5 | fobrc=imcomplement(fobr); 6 | fobrce=imerode(fobrc,se); 7 | fobrcbr=imcomplement(imreconstruct(fobrce,fobrc)); 8 | 9 | --------------------------------------------------------------------------------