├── TVD_Img.m ├── GSTVD_Img.m ├── ADMM 1D Denoising ├── testSig3.mat ├── ADMM_1D_Demo.m ├── ADMM_1D.m ├── ADMM_1D_HOTV.m ├── AMA_1D.m └── ADMM_1D_HOTV_lp.m ├── .gitattributes ├── .gitignore ├── ALMTV_Demo.m ├── README.md ├── L1_OGS Denoising ├── gstvdm.m ├── demoOGS_impulse.m └── gstv2d_imp.m ├── Denoise_Img.m ├── Split Bregman Deblurring ├── splitBreg_Demo.m └── splitBreg.m ├── Second Order TV ├── HOTV_demo.m └── HOTV.m ├── l0_TV Denoising ├── DemoL0_ADMM.m └── L0_ADMM.m ├── ADMM Matrix Completion ├── lrmcADMM_Demo.m └── lrmcADMM.m ├── NonConvex_Lp ADMM ├── lpALM_Demo.m ├── lpALM.m └── lpALM_rhoUpdate.m ├── ADMM Image Denoising ├── ADMM_DemoDenoise.m └── ADMM.m ├── getConvMtx.m ├── RPCA Image Inpainting ├── RPCA_Demo.m └── RPCA_ADMM.m ├── ADMM Color Image Denoising ├── ADMM_DemoDenoiseColor.m └── ADMM.m └── ALMTV.m /TVD_Img.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarmiziAdam2005/Image-Signal-Processing/HEAD/TVD_Img.m -------------------------------------------------------------------------------- /GSTVD_Img.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarmiziAdam2005/Image-Signal-Processing/HEAD/GSTVD_Img.m -------------------------------------------------------------------------------- /ADMM 1D Denoising/testSig3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarmiziAdam2005/Image-Signal-Processing/HEAD/ADMM 1D Denoising/testSig3.mat -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /ALMTV_Demo.m: -------------------------------------------------------------------------------- 1 | % ================ Demo for grayscale image deblurring================== 2 | % This code demostrates the use of the ALMTV (Augmented Lagrangian Method 3 | % Total Variation) code. 4 | 5 | clc 6 | clear all; 7 | close all; 8 | 9 | Img = im2double(imread('Lighthouse256.bmp')); %Your Image goes here 10 | %I = double(Img); 11 | 12 | %H = ones(9,9)/81; 13 | H = fspecial('gaussian', [7 7], 5); 14 | %H = fspecial('motion',20,45); %Try a motion blur 15 | g = imfilter(Img,H,'circular'); 16 | 17 | %[g,I] = BlurCrop(Img,H); 18 | %g = imnoise(g, 'gaussian', 0, 0.00001); % A little bit of noise 19 | 20 | lam = 10000; %Regularization parameter 21 | rho = 2; 22 | Nit = 20; 23 | tol = 1e-5; 24 | 25 | %=============Deblurr algorithm========== 26 | tg = tic; 27 | [f, relchg] = ALMTV(g,H,lam,rho,Nit,tol); 28 | tg = toc(tg); 29 | %======================================== 30 | 31 | figure; 32 | imshow(f); 33 | title('Deblurred'); 34 | 35 | figure; 36 | imshow(g); 37 | title('Blurred'); 38 | 39 | figure; 40 | imshow(Img); 41 | title('Original'); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | This folder contains implementations and re-implementations of some image restoration algorithms using mainly the 3 | popular Alternating Direction Methods of Multipliers (ADMM). 4 | 5 | Some of the codes included are: 6 | 7 | 1. Split Bregman Total Variation Denoising/Deblurring of Image 8 | 2. ALM/ADMM Total Variation Denoising/Deblurring of Image 9 | 3. Non-convex Lp-norm (0 < p <1) Total Variation Deblurring using ADMM/ALM and IRL1 (Iterative Reweighted L1). 10 | 4. Second Order ALM/ADMM Total Variation Denoising/Deblurring (TV image restoration using the 2nd Order Derivative operator). 11 | 5. Robust Principal Componant Analysis (RPCA) for sparse noise restoration (impulse noise). Solved using ADMM. 12 | 6. Low rank matrix completion (LRMC) using ADMM. Example code is applied for missing pixel image restoration (Inpainting). 13 | 7. The state-of-the-art L0-TV by Yuan and Ghanem for impulse noise restoration (using pure ADMM). 14 | 15 | If you find any mistakes or bugs, Please DO NOT HESITATE to contact me ! at tarmizi_adam2005@yahoo.com. 16 | -------------------------------------------------------------------------------- /L1_OGS Denoising/gstvdm.m: -------------------------------------------------------------------------------- 1 | function x = gstvdm(y, K, lam, Nit) 2 | % [x, cost] = gstvdm(y, K, lam, Nit) 3 | % Group-Sparse Total Variation modification Denoising. 4 | % 5 | % INPUT 6 | % y - noisy signal 7 | % K - group size (small positive integer) 8 | % lam - regularization parameter (lam > 0) 9 | % Nit - number of iterations 10 | % 11 | % OUTPUT 12 | % x - denoised signal 13 | 14 | 15 | % Ivan Selesnick, selesi@poly.edu, 2012 16 | % Modified by LJ, UESTC, 2013 17 | % history 18 | h = ones(K,K); % For convolution 19 | x = y; % Initialization 20 | 21 | if K ~=1 22 | for k = 1:Nit 23 | r = sqrt(conv2(abs(x).^2, h,'same')); % zero outside the bounds of x 24 | % r = sqrt(imfilter(abs(x).^2,h)); % slower than conv2 25 | v = conv2(1./r, h, 'same'); 26 | % F = 1./(lam*v) + 1; 27 | % x = y - y./F; 28 | x = y./(1+lam*v); 29 | end 30 | else 31 | for k = 1:Nit 32 | r = sqrt(abs(x).^2); % zero outside the bounds of x 33 | % r = sqrt(imfilter(abs(x).^2,h)); % slower than conv2 34 | v = 1./r; 35 | % F = 1./(lam*v) + 1; 36 | % x = y - y./F; 37 | x = y./(1+lam*v); 38 | end 39 | end 40 | 41 | -------------------------------------------------------------------------------- /ADMM 1D Denoising/ADMM_1D_Demo.m: -------------------------------------------------------------------------------- 1 | 2 | % Created on 5/3/2017 by Tarmizi Adam. 3 | % Small demo for 1D-signal Total Variation (TV) denoising using the 4 | % Alternating Direction Methods of Multiplier (ADMM). 5 | % This demo file calls the function " ADMM_1D() " solver. 6 | 7 | clc; 8 | clear all; 9 | close all; 10 | 11 | 12 | %Generate sine wave; 13 | %{ 14 | x = -10*pi:.1:10*pi; 15 | y = sin(x); 16 | plot(x,y) 17 | %} 18 | 19 | %Load a piecewice defined function instead of a sine wave 20 | % You can use any signal that you have 21 | load testSig3.mat; 22 | y = testSig3; 23 | 24 | %add some noise to it 25 | sigma = 10; 26 | noisy_y = y + sigma * randn(1, length(y)); 27 | 28 | %figure; 29 | %plot(x,noisy_y) %To plot sine wave; 30 | 31 | lam = 0.0078; 32 | rho = 1.0; 33 | Nit = 200; 34 | 35 | %% ********** Run the TV-solver *************** 36 | 37 | out = ADMM_1D(noisy_y, lam, rho, Nit); %Run the Algorithm !!! 38 | 39 | %% ******************************************** 40 | 41 | %% 42 | figure; 43 | subplot(3,1,1) 44 | plot(y); 45 | axis tight; 46 | title('Original Signal'); 47 | 48 | subplot(3,1,2); 49 | plot(noisy_y) 50 | axis tight; 51 | title('Noisy Signal'); 52 | 53 | subplot(3,1,3); 54 | plot(out.sol); 55 | axis tight; 56 | title('TV Denoised'); 57 | 58 | figure; 59 | plot(out.funVal); 60 | title('Function Value'); 61 | %% -------------------------------------------------------------------------------- /Denoise_Img.m: -------------------------------------------------------------------------------- 1 | %Created by Tarmizi Adam 1/9/2015. TVD and GSTVD denoising for random Noise 2 | %Run this script with functions: 3 | 4 | %[x1,err1] = TVD_Img(y,lam,Nit); 5 | % or 6 | %[x1,err1] = GSTVD_Img(y,K,lam,Nit); 7 | 8 | %Which must be in the same folder as this script. 9 | 10 | 11 | 12 | 13 | clc; clear all; 14 | close all; 15 | 16 | s = double(imread('lenaN','bmp')); 17 | 18 | Nit = 20; %Number of iterations to run the algorithm 19 | sigma = 30; %Noise level added to the image 20 | lam = 10 %sqrt(3*sigma); %Regularization parameter lambda 21 | K = 6; 22 | 23 | %% Add noise to image 24 | noise = sigma * randn(size(s)); 25 | y = s + noise; 26 | 27 | [x1,err1] = TVD_Img(y,lam,Nit); 28 | %[x1,err1] = GSTVD_Img(y,K,lam,Nit); 29 | 30 | score = psnr(s,x1); %PSNR score of the denoised Image 31 | rmse = sqrt(sum((s(:)-x1(:)).^2)/numel(s)); %RMSE score of the denoise image 32 | x1 = uint8(x1); 33 | 34 | 35 | %% Start Plotting Results 36 | figure; 37 | 38 | subplot 431 39 | imshow(uint8(s)); 40 | title('Original'); 41 | 42 | subplot 432 43 | imshow(uint8(y)); 44 | title(['Noisy, \sigma = ' int2str(sigma)]); 45 | 46 | subplot 433 47 | imshow(x1); 48 | title(['Denoised with \lambda = ',int2str(lam),', PSNR = ',num2str(score)]) 49 | 50 | subplot 434 51 | plot(err1) 52 | title('Error') 53 | 54 | 55 | -------------------------------------------------------------------------------- /Split Bregman Deblurring/splitBreg_Demo.m: -------------------------------------------------------------------------------- 1 | % ================ Demo for grayscale image deblurring================== 2 | % This code demostrates the use of the Split Bregman method Total 3 | % Variation (SBMTV) for image deblurring. 4 | % Make sure the main SBMTV file is in the same folder, "splitBreg.m" 5 | 6 | clc 7 | clear all; 8 | close all; 9 | 10 | Img = double(imread('peppers.bmp')); %Your Image goes here 11 | %I = double(Img); 12 | 13 | %H = ones(9,9)/81; 14 | H = fspecial('gaussian', [7 7], 5); 15 | %H = fspecial('motion',20,45); %Try a motion blur 16 | g = imfilter(Img,H,'circular'); 17 | 18 | BSNR = 40; 19 | sigma = BSNR2WGNsigma(g, BSNR); 20 | g = g + sigma * randn(size(Img)); %Add a little noise 21 | 22 | 23 | lam = 10; %regularization parameter associated with the constraint 24 | mu = 10000; %Regularization parameter 25 | res = cell([1 size(lam,2)]); 26 | Nit = 10; 27 | tol = 1e-5; 28 | pm.mu = 30; 29 | %=============Deblurr algorithm========== 30 | %for k=1:length(lam) 31 | tg = tic; 32 | % 33 | out = splitBreg(g,Img,H,lam,mu,Nit,tol); 34 | %[uTV,outputTV] = deblurTV(g,H,pm); 35 | tg = toc(tg); 36 | %end 37 | %======================================== 38 | 39 | figure; 40 | imshow(uint8(out.sol)); 41 | title('Deblurred'); 42 | 43 | figure; 44 | imshow(uint8(g)); 45 | title('Blurred'); 46 | 47 | figure; 48 | imshow(uint8(Img)); 49 | title('Original'); 50 | 51 | 52 | -------------------------------------------------------------------------------- /Second Order TV/HOTV_demo.m: -------------------------------------------------------------------------------- 1 | clc 2 | clear all; 3 | close all; 4 | 5 | Img = double(imread('boat.bmp')); %Your Image goes here 6 | 7 | N = numel(Img); 8 | %H = ones(9,9)/81; 9 | %K = fspecial('gaussian', [9 9], 5); % Deblurring. Try other kernels as 10 | % well 11 | K = fspecial('average',1); % For denoising 12 | f = imfilter(Img,K,'circular'); 13 | 14 | BSNR =15; 15 | %sigma = BSNR2WGNsigma(f, BSNR); 16 | sigma = BSNR; 17 | % If you dont have the BSNR2WGNsigma() function, use the below instead. 18 | 19 | %sigma = sqrt(5); 20 | %BSNR=20*log10(norm(f(:)-mean(f(:)),'fro')/sqrt(N)/sigma); 21 | 22 | f = f + sigma * randn(size(Img)); %Add a little noise 23 | 24 | 25 | 26 | %opts.lam = 3500; % for deblurring, try large values. 27 | %opts.omega = 50; % reg param for 2nd order TV 28 | 29 | opts.lam = 0.1; % for denoising try starting with these 30 | opts.omega = 1; 31 | 32 | opts.Nit = 400; 33 | opts.tol = 1.0e-5; 34 | opts.beta = 0.1; 35 | 36 | % ****** The main solver ****** 37 | out = HOTV(f,Img,K, opts); 38 | %****************************** 39 | 40 | figure; 41 | imshow(uint8(out.sol)); 42 | title(sprintf('2nd Order TV Deblurred (PSNR = %3.3f dB, cputime %.3f s) ',... 43 | psnr_fun(out.sol,Img), out.cpuTime)); 44 | 45 | figure; 46 | imshow(uint8(f)); 47 | title(sprintf('Blurred + Noisy (PSNR = %3.3f dB)',psnr_fun(f,Img))); 48 | 49 | figure; 50 | imshow(uint8(Img)); 51 | title('Original'); 52 | -------------------------------------------------------------------------------- /l0_TV Denoising/DemoL0_ADMM.m: -------------------------------------------------------------------------------- 1 | 2 | % Created by Tarmizi Adam,27/8/2019 3 | 4 | % This demo runs the L0-TV impulse noise restoration. Works for pure 5 | % denoising and deblurring under influence of impulse noise. 6 | % For further information on L0-TV please refer to the function "L0_ADMM.m" 7 | % function called within this script. 8 | 9 | clc; 10 | clear all; 11 | close all; 12 | 13 | imageName = 'peppers.bmp'; 14 | 15 | Img = imread(imageName); 16 | 17 | if size(Img,3) > 1 18 | Img = rgb2gray(Img); 19 | end 20 | 21 | [row, col] = size(Img); 22 | 23 | row = int2str(row); 24 | col = int2str(col); 25 | 26 | imageSize = [row 'x' col]; 27 | 28 | K = fspecial('gaussian', [7 7], 5); % Gaussian Blur 29 | %K = fspecial('average',1); % For denoising 30 | f = imfilter(Img,K,'circular'); 31 | 32 | 33 | f = impulsenoise(f,0.5,0); 34 | f = double(f); 35 | 36 | O = ones(size(Img)); 37 | O(f == 255) = 0; 38 | O(f == 0) = 0; 39 | 40 | Img = double(Img)/255; 41 | f = f/255; 42 | 43 | 44 | opts.lam = 2.0; % Regularization parameter, play with this ! 45 | opts.tol = 1e-4; 46 | opts.Nit = 300; 47 | opts.O = O; 48 | 49 | %******** Main denoising function call******** 50 | 51 | out = L0_ADMM(f,Img,K,opts); 52 | 53 | 54 | figure; 55 | imshow(Img,[]); 56 | 57 | figure; 58 | imshow(f,[]); 59 | 60 | figure; 61 | imshow(out.sol,[]); 62 | title(sprintf('l0-TV_ADMM Denoising (PSNR = %3.3f dB,SSIM = %3.3f) ',... 63 | psnr_fun(out.sol*255,Img*255),ssim_index(out.sol*255,Img*255))); 64 | 65 | -------------------------------------------------------------------------------- /ADMM Matrix Completion/lrmcADMM_Demo.m: -------------------------------------------------------------------------------- 1 | % This demo files solve the low rank matrix completion problem applied to 2 | % image inpainting. In this demo, we apply the Alternating Direction Method 3 | % of Multipliers (ADMM) to do so. 4 | 5 | % Created by Tarmizi Adam on 31/12/2019. For furter assistance on the ADMM 6 | % algorithm used for the matrix completion problem, refer to the file 7 | % "lrmcADMM.m" file. 8 | % 9 | 10 | clc; 11 | clear all; 12 | close all; 13 | 14 | %% For image inpainting %% 15 | 16 | X = imread('peppers.bmp'); 17 | X = double(X); 18 | 19 | [n1,n2] =size(X); 20 | 21 | %% Create projection matrix %% 22 | MisLvl = 0.2; % percentage of missing pixels/entries, change here. 23 | 24 | J = randperm(n1*n2); 25 | J = J(1:round(MisLvl*n1*n2)); 26 | P = ones(n1*n2,1); 27 | P(J) = 0; 28 | P = reshape(P,[n1,n2]); % our projection matrix 29 | 30 | %% Simulate our corrupted original matrix %% 31 | Y = X(:); 32 | sigma = 30; %noise level 33 | noise = sigma*randn(n1*n2,1); 34 | 35 | Y = Y + noise; 36 | Y = reshape(Y,[n1,n2]); 37 | Y = P.*Y; % Our final noisy + missing entry matrix (Observation) 38 | 39 | opts.lam = 800; % Regularization parameter. Play with this and see effects. 40 | opts.Nit = 500; % Number of iteration for algorithm termination 41 | opts.tol = 1e-3; 42 | 43 | out = lrmcADMM(Y,X,P,opts); % Call ADMM solver for matrix completion. 44 | 45 | figure; 46 | imshow(out.sol,[]); 47 | 48 | figure; 49 | imshow(X,[]); 50 | 51 | figure; 52 | imshow(Y,[]); 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /NonConvex_Lp ADMM/lpALM_Demo.m: -------------------------------------------------------------------------------- 1 | % ================ Demo for grayscale image deblurring================== 2 | 3 | %Created by Tarmizi Adam. Use this code at your own risk 4 | %Demo code that is used for the lp-norm ALM deblurring code. 5 | % Feel free to email me at tarmizi_adam2005@yahoo.com if you find any 6 | % bugs or just drop by and inform me that you used the code somewhere in 7 | % your research. 8 | 9 | clc 10 | clear all; 11 | close all; 12 | 13 | Img = double(imread('cameraman.bmp')); %Your Image goes here 14 | 15 | %H = fspecial('gaussian', [7 7], 5); 16 | H = ones(9,9)/81; 17 | g = imfilter(Img,H,'circular'); 18 | 19 | BSNR = 30; 20 | sigma = BSNR2WGNsigma(g, BSNR); 21 | g = g + sigma * randn(size(Img)); %Add a little noise 22 | 23 | mu = 0.45; 24 | 25 | %res = cell([1 size(l,2)]); 26 | rho = 0.1; %default 2 27 | Nit = 400; 28 | tol = 1e-5; 29 | p = 0.3; 30 | 31 | %=============Deblurr algorithm========== 32 | %for k=1:length(lam) 33 | tg = tic; 34 | % out = lpALM_rhoUpdate(g,Img,H,mu,rho,Nit,p,tol); %with rho %update 35 | out = lpALM(g,Img,H,mu,rho,Nit,p,tol); % lp-Norm TV function 36 | tg = toc(tg); 37 | %res{1,k} = out; 38 | %end 39 | %======================================== 40 | 41 | 42 | figure; 43 | imshow(uint8(out.sol)); 44 | %title('Deblurred'); 45 | title(sprintf('TV_p (IRL1) Deblurred (PSNR = %3.3f dB, cputime %.3f s) ',... 46 | out.psnrf, tg)); 47 | 48 | figure; 49 | imshow(uint8(g)); 50 | title(sprintf('Blurred (PSNR = %3.3f dB', psnr_fun(g, Img))); 51 | 52 | figure; 53 | imshow(uint8(Img)); 54 | title('Original'); 55 | 56 | -------------------------------------------------------------------------------- /ADMM Image Denoising/ADMM_DemoDenoise.m: -------------------------------------------------------------------------------- 1 | % ================ Demo for grayscale image denoising================== 2 | % This code demostrates the use of the ADMM Image denoising. ADMM is a 3 | % splitting version of the more classical ALM (Augmented Lagrangian Method) 4 | % This code solves the problem of 5 | % min_x 1/2*||y - x||^2_2 + lamda||Dx||_1 6 | 7 | clc 8 | clear all; 9 | close all; 10 | 11 | Img = double(imread('Lighthouse256.bmp')); %Your Image goes here 12 | 13 | sigma = 25; % standard variation 14 | 15 | g = Img + sigma * randn(size(Img)); %Add a little noise 16 | 17 | lam = 29.7; 18 | 19 | 20 | res = cell([1 size(lam,2)]); 21 | resSSIM = cell([1 size(lam,2)]); %Store SSIM result of each iteration 22 | resPSNR = cell([1 size(lam,2)]); %Store PSNR result of each iteration 23 | 24 | rho = 2; %regularization param related to the lagrange constraints 25 | 26 | Nit = 400; 27 | tol = 1e-5; 28 | 29 | %Regularization function. Isotropic TV ('iso') or Anisotropic TV ('ani') 30 | regType = 'iso'; 31 | 32 | %=============Denoising algorithm========== 33 | 34 | out = ADMM(g,Img,lam,rho,Nit,tol,regType); 35 | 36 | %======================================== 37 | 38 | 39 | figure; 40 | imshow(uint8(out.sol)); 41 | title(sprintf('ADMM Denoised (PSNR = %3.3f dB,SSIM = %3.3f, cputime %.3f s) ',... 42 | out.psnrf, out.ssimf, out.cpuTime)); 43 | 44 | figure; 45 | imshow(uint8(g)); 46 | title(sprintf('Noisy (PSNR = %3.3f dB, SSIM = %3.3f)', psnr_fun(g, Img),ssim_index(g,Img))); 47 | 48 | figure; 49 | imshow(uint8(Img)); 50 | title(sprintf('Original (PSNR = %3.3f dB)', psnr(Img,Img))); 51 | 52 | -------------------------------------------------------------------------------- /L1_OGS Denoising/demoOGS_impulse.m: -------------------------------------------------------------------------------- 1 | 2 | % 28/8/2019 3 | % This is the demo file to run image denoising and deblurring with impulse 4 | % noise. The algorithm is the L1-OGSTV (re-implementation from the original paper). 5 | 6 | % L1 --> Data fidelity term (for impulse noise) 7 | % OGSTV --> Regularization term (supress staircase artifacts) 8 | 9 | % See the function "gstv2d_imp.m" for further details on L1-OGSTV 10 | 11 | clc; 12 | clear all; 13 | close all; 14 | 15 | imageName = 'boat256.bmp'; 16 | 17 | Img = imread(imageName); 18 | 19 | if size(Img,3) > 1 20 | Img = rgb2gray(Img); 21 | end 22 | 23 | [row, col] = size(Img); 24 | 25 | row = int2str(row); 26 | col = int2str(col); 27 | 28 | imageSize = [row 'x' col]; 29 | 30 | K = fspecial('gaussian', [7 7], 5); % Gaussian Blur 31 | %K = fspecial('average',1); % For denoising 32 | f1 = imfilter(Img,K,'circular'); 33 | f1 = double(f1); 34 | 35 | 36 | f = impulsenoise(f1,0.7,0); 37 | f = double(f); 38 | Img = double(Img); 39 | 40 | 41 | opts.lam = 18; % for denoising try starting with these 42 | opts.grpSz = 3; % OGS group size 43 | opts.Nit = 300; 44 | opts.Nit_inner = 5; 45 | opts.tol = 1e-4; 46 | 47 | % main function 48 | 49 | out = gstv2d_imp(f,Img,K,opts); 50 | 51 | 52 | 53 | figure; 54 | imshow(out.sol,[]), 55 | title(sprintf('ogs2d\\_tv (PSNR = %3.2f dB,SSIM = %3.3f, cputime %.2f s) ',... 56 | psnr_fun(out.sol,Img),ssim_index(out.sol,Img))) 57 | 58 | figure; 59 | imshow(uint8(Img)) 60 | title('Original Image'); 61 | 62 | figure; 63 | imshow(uint8(f)) 64 | title('Blur + Noisy'); 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /getConvMtx.m: -------------------------------------------------------------------------------- 1 | function T = getConvMtx(H,m,n) 2 | 3 | %This program was posted by stackoverflow user Stav and can be found 4 | % here: 5 | % http://stackoverflow.com/questions/26151265/matlab-2d-convolution- 6 | % matrix-with-replication 7 | % Copyright thus goes to the user Stav 8 | 9 | % Input: 10 | % H: blur kernel e.g: 5 x 5 gaussian kernel etc. 11 | % m: row of resulting convolution matrix T. 12 | % n: columns of the resulting convolution matrix T 13 | 14 | % Output 15 | % T: the convlution matrix 16 | 17 | %This code is used to create the convolution matrix T like the predefined 18 | %MATLAB function convmtx2. However, this code replicates the convolution 19 | %matrix to get an M x M size matrix. 20 | 21 | %This code may be used for linear inverse problems i.e. lnear models like 22 | % y = Tx + w 23 | % where y is the observed blury image T is the convolution matrix (this 24 | % code), x the original clean signal (Image) to be estimated and w the 25 | % noise. 26 | 27 | vHalfKerSz = floor(size(H) / 2); 28 | 29 | mInds = reshape(1:m*n, m, n); 30 | mInds = padarray(mInds, vHalfKerSz, 'replicate'); 31 | 32 | Tcols = zeros(m*n*numel(H), 1); 33 | Trows = zeros(m*n*numel(H), 1); 34 | Tvals = zeros(m*n*numel(H), 1); 35 | 36 | i = 0; p = 0; 37 | for c = 1:n 38 | for r = 1:m 39 | p = p + 1; 40 | 41 | mKerInds = mInds(r:r+size(H,1)-1, c:c+size(H,2)-1); 42 | 43 | [U, ~, ic] = unique(mKerInds(:)); 44 | 45 | for k = 1:length(U) 46 | i = i + 1; 47 | Tcols(i) = U(k); 48 | Trows(i) = p; 49 | Tvals(i) = sum(H(mKerInds == U(k))); 50 | end 51 | end 52 | end 53 | 54 | T = sparse(Trows(1:i), Tcols(1:i), Tvals(1:i), m*n, m*n); 55 | 56 | end -------------------------------------------------------------------------------- /RPCA Image Inpainting/RPCA_Demo.m: -------------------------------------------------------------------------------- 1 | clc; 2 | clear all; 3 | close all; 4 | 5 | % First Created on 3/07/2017 by Tarmizi Adam 6 | % Update History : 8/6/2019, 7 | % Demo for robust principal component analysis (RPCA) using ADMM 8 | % Uses the ADMM/ADM algorithm to solve the the pricipal component pursuit: 9 | % 10 | % min_L&M ||L||_* + lambda*||S||_1 11 | % s.t L + S = M 12 | % 13 | % This code demostrates the RPCA for image inpainting (Filling missing pixel values). 14 | % The main solver is "RPCA_ADMM()". For furter information, check file 15 | % "RPCA_ADMM.m" 16 | 17 | 18 | Img = imread('peppers.bmp'); 19 | 20 | sigma = 0.2; %density of the noise 21 | Img_n = imnoise(Img,'salt & pepper',sigma); 22 | Img_n = double(Img_n); 23 | 24 | %% ==================== Parameter options ===================== 25 | 26 | opts.lam = 0.053; % Regularization parameter 27 | opts.Nit = 1000; % Algorithm iteration 28 | opts.tol = 1.0e-5; %Stopping criterion value 29 | opts.rho = 0.05; % Regularization param of ADMM constraint 30 | 31 | %% ==================== Run our ADMM algorithm for RPCA ! ================== 32 | out = RPCA_ADMM(Img_n, opts); 33 | 34 | 35 | %% ===================== Show some results ===================== 36 | figure; 37 | imshow(uint8(Img_n)); 38 | title(sprintf('Corrupted (Missing pixels).(PSNR = %3.3f dB)', psnr_fun(Img_n, double(Img)))); 39 | 40 | figure; 41 | imshow(Img); 42 | title('Original'); 43 | 44 | figure; 45 | imshow(uint8(out.solL)); 46 | title(sprintf('Low rank restored (PSNR = %3.3f dB,SSIM = %3.3f) ',... 47 | psnr_fun(out.solL,double(Img)),ssim_index(out.solL,double(Img)))); 48 | 49 | figure; 50 | imshow(uint8(out.solS)); 51 | title(sprintf('Sparse component')); 52 | 53 | figure; 54 | plot(out.relativeError); 55 | title('Relative Error'); 56 | 57 | -------------------------------------------------------------------------------- /ADMM Color Image Denoising/ADMM_DemoDenoiseColor.m: -------------------------------------------------------------------------------- 1 | clc; 2 | clear all; 3 | close all; 4 | 5 | Img = double(imread('butterfly.png')); %Your Image goes here 6 | 7 | [M,N,O] = size(Img); 8 | 9 | sigma = 30; % standard variation of noise 10 | 11 | %% Adding noise to each chanel %% 12 | g1 = Img(:,:,1) + sigma * randn(size(Img(:,:,1))); 13 | g2 = Img(:,:,2) + sigma * randn(size(Img(:,:,2))); 14 | g3 = Img(:,:,3) + sigma * randn(size(Img(:,:,3))); 15 | %% 16 | 17 | imgNoise = cat(3,g1,g2,g3); %The noisy image 18 | 19 | %% Some initializations %% 20 | 21 | cleanImg = zeros(M,N,O); % pre-allocate space for our denoised image 22 | 23 | lam = 25; % Regularization parameter. Play around with this ! 24 | % Larger values smoothens the image from noise. 25 | 26 | rho = 2; %initial regularization param related to the lagrange constraints 27 | % You can try to play around with this. However, in this code 28 | % this value will be updated in each iteration of the 29 | % algorithm to speed up the convergence. 30 | 31 | Nit = 400; % Total iteration of the algorithm 32 | tol = 1e-5; % Error tolerance before the algorithms stops. (Stopping criteria) 33 | 34 | %Regularization function. Isotropic TV ('iso') or Anisotropic TV ('ani') 35 | regType = 'ani'; 36 | %% 37 | 38 | %=============Denoising algorithm========== 39 | overallTime = tic; 40 | for i = 1:3 41 | 42 | % Here, we denoise each rgb chanel separately. 43 | out = ADMM(imgNoise(:,:,i),Img,lam,rho,Nit,tol,regType); 44 | cleanImg(:,:,i) = out.sol; 45 | 46 | end 47 | %======================================== 48 | overallTime = toc(overallTime); 49 | 50 | figure; 51 | imshow(uint8(Img)); 52 | title(sprintf('Original Clean Image')); 53 | 54 | 55 | figure; 56 | imshow(uint8(imgNoise)); 57 | title(sprintf('Noisy Image (Additive Gaussian)')); 58 | 59 | figure; 60 | imshow(uint8(cleanImg)); 61 | title(sprintf('ADMM Denoised Image (CPU time = %3.3f)',overallTime)); 62 | -------------------------------------------------------------------------------- /RPCA Image Inpainting/RPCA_ADMM.m: -------------------------------------------------------------------------------- 1 | function out = RPCA_ADMM(M,opts) 2 | 3 | % Created by Tarmizi Adam on 2/06/2017 4 | % Update: 8/6/2019 5 | %This is a simple program for Robust Principal Component Analysis (RPCA) 6 | %for Image inpainting (restoring missing pixels values). The iterative algorithm used in this program is the 7 | % Alternating Direction Methods of Multiplier (ADMM) which is a splitting 8 | % version of the classical Augmented Lagrangian Method (ALM). 9 | 10 | % This solver solves the following minimization problem: 11 | 12 | % min_L&M ||L||_* + lambda*||S||_1 13 | % s.t L + S = M 14 | 15 | % Input: 16 | % M = Noisy observation 17 | % opts = related parameters for ADMM algorithm etc. 18 | % 19 | % Output: 20 | % out.solL = Low rank matrix (in our context, inpainted image) 21 | % out.solS = Sparse matrix ( in our context, separated missing pixels) 22 | 23 | % Any suggestion,comments, errors regarding this code, do not hesitate to email me at: 24 | % 25 | % tarmizi_adam2005@yahoo.com 26 | % 27 | %% 28 | 29 | L = zeros(size(M)); % Low rank matrix 30 | S = zeros(size(M)); % Sparse matrix 31 | Mu = zeros(size(M)); % Lagrange multipliers 32 | 33 | rho = opts.rho; % contraint regularization parameter 34 | lam = opts.lam; %Regularization parameter, > 0 35 | 36 | relError = zeros(opts.Nit,1); 37 | 38 | %====================== Main ADMM algorithm loop ========================= 39 | for i = 1:opts.Nit 40 | 41 | % L subproblem 42 | X = M + Mu./rho; 43 | L = svt(X-S , 1/rho); %Solve for L, by singular value thresholding 44 | 45 | % S subproblem 46 | S = shrink(X-L, lam/rho); %Solve for S by soft thresholding 47 | 48 | Mu = Mu - rho*(L+S-M); %Update our Lagrange multipliers 49 | 50 | E_r = L+S-M; 51 | 52 | relError(i) = norm(E_r,'fro')/norm(M, 'fro'); 53 | 54 | if relError(i) < opts.tol 55 | break; 56 | end 57 | 58 | end 59 | 60 | out.solL = L; 61 | out.solS = S; 62 | out.relativeError = relError(1:i); 63 | 64 | end 65 | 66 | function Z = shrink(X,r) %Shrinkage operator 67 | Z = sign(X).*max(abs(X)- r,0); 68 | end 69 | 70 | function Z = svt(X, r) %Singular value thresholding 71 | 72 | [U, S, V] = svd(X,'econ'); 73 | Z = U*shrink(S,r)*V'; 74 | end 75 | -------------------------------------------------------------------------------- /ADMM 1D Denoising/ADMM_1D.m: -------------------------------------------------------------------------------- 1 | function out = ADMM_1D(f,lam,rho, Nit) 2 | % Created by Tarmizi Adam on 5/3/2017 3 | %This is a simple program for 1D Signal denoising using total variation 4 | % denoising. The iterative algorithm used in this program is the 5 | % Alternating Direction Methods of Multiplier (ADMM) which is a splitting 6 | % version of the classical Augmented Lagrangian Method (ALM). 7 | 8 | % This solver solves the following minimization problem: 9 | 10 | % min_x lambda/2*||u - f||^2_2 + ||Du||_1 11 | 12 | % Input: 13 | % f = The noisy observed signal (1D-signal) 14 | % lam = Regularization parameter. Controls the smoothness of the 15 | % denoised signal. 16 | % rho = Regularization parameter related to the constraint (ADMM) 17 | % Nit = Number of iterations to run the ADMM iterative method. 18 | % 19 | % Output: 20 | % out.sol = The denoised signal 21 | % out.funVal = Plot of the convergence of our objective 22 | % function 23 | %% 24 | 25 | f = f(:); 26 | u = f; %Initialize 27 | N = length(f); 28 | mu = zeros(N,1); % Lagrange multiplier 29 | v = mu; %Initialize the v sub-problem 30 | funcVal = zeros(Nit,1); 31 | 32 | [D,DT,DTD] = defDDt(N); 33 | 34 | for k = 1:Nit 35 | u_old = u; 36 | 37 | %% u sub-problem %% 38 | % Solves a linear system using the conjugate gradient method. 39 | [u,~] = cgs(rho*DTD + lam*speye(N),lam*f+rho*DT*(v - mu/rho),1e-5,100); 40 | 41 | %% v sub-problem %% 42 | x = D*u + mu/rho; 43 | v = shrink(x, 1/rho); 44 | 45 | %% Update Lagrange multiplier 46 | mu = mu + (D*u - v); 47 | 48 | r1 = u - f; 49 | funcVal(k) = (lam/2)*norm(r1,'fro')^2 + sum(v(:)); 50 | 51 | end 52 | 53 | out.sol = u; 54 | out.funVal = funcVal(1:k); 55 | 56 | end 57 | 58 | function [D,DT,DTD] = defDDt(N) 59 | %Create a first order difference matrix D 60 | e = ones(N,1); 61 | B = spdiags([e -e], [1 0], N, N); 62 | B(N,1) = 1; 63 | 64 | D = B; 65 | clear B; 66 | % Create the transpose of D 67 | DT = D'; %Remember that DT = -D, also called the backward difference. 68 | DTD = D'*D; 69 | end 70 | 71 | function z = shrink(x,r) 72 | z = sign(x).*max(abs(x)- r,0); 73 | end 74 | 75 | -------------------------------------------------------------------------------- /ADMM Matrix Completion/lrmcADMM.m: -------------------------------------------------------------------------------- 1 | function out = lrmcADMM(Y,I,P,opts) 2 | 3 | 4 | %Created on 31/12/2019 by Tarmizi Adam (Email: tarmizi_adam2005@yahoo.com). 5 | % This code solves the noisy matrix completion problem with ADMM. The original 6 | % problem is the following: 7 | % 8 | % minimize_X F(X) = 0.5*||Y_omega - X_omega||^2_2 + lambda||X||_* 9 | % 10 | % We re-write the problem as the follows(used in this code) 11 | % 12 | % minimize_X F(X) = 0.5*||M_omega||^2_2 + lambda||X||_* 13 | % subject to, M_omega + X_omega = Y_omega, 14 | % 15 | % and solve using ADMM. 16 | % 17 | % Input: Y: The noisy and corrupted matrix (observation) 18 | % I: Original matrix 19 | % P: The mask, location of zero pixels/entries. 20 | % opts: Options, see "lrmcADMM_Demo" file. 21 | % 22 | % Output: Xk: Estimated low rank matrix. 23 | 24 | 25 | lam = opts.lam; % Regularization parameter 26 | Nit = opts.Nit; % Number of iteration for algorithm termination 27 | tol = opts.tol; % Tolerance for algorithm stopping criteria. 28 | 29 | relError = zeros(Nit,1); 30 | 31 | Xk = zeros(size(I)); % Initialize Xk 32 | mu = zeros(size(I)); % Lagrange multiplier 33 | M = Xk; % Initialize M (see objective function being solved) 34 | 35 | beta = 0.5; %Parameter related to the augmented Lagrange term. 36 | 37 | 38 | %% ***** Main Loop ***** 39 | 40 | for k =1:Nit 41 | 42 | X_old = Xk; 43 | 44 | %***** X Subproblem **** 45 | 46 | V = Xk - (P.*M + P.*Xk - Y - mu/beta); 47 | 48 | Xk = svt(V,lam/beta); 49 | 50 | %***** M subproblem ***** 51 | RHS = beta*Y - beta*(P.*Xk) + mu; 52 | 53 | M = RHS./(beta + 1); 54 | 55 | %***** Update Lagrange multipliers ***** 56 | 57 | mu = mu - beta*(P.*M - Y + P.*Xk); 58 | 59 | Err = Xk - X_old; 60 | relError(k) = norm(Err,'fro')/norm(Xk,'fro'); 61 | 62 | if relError(k) < tol 63 | break; 64 | end 65 | 66 | end 67 | 68 | %% ***** End Main Loop ***** 69 | 70 | out.sol = Xk; 71 | out.err = relError(1:k); 72 | 73 | 74 | end 75 | 76 | function Z = shrink(X,r) %Shrinkage operator 77 | Z = sign(X).*max(abs(X)- r,0); 78 | end 79 | 80 | function Z = svt(X, r) %Singular value thresholding 81 | 82 | [U, S, V] = svd(X); 83 | s = shrink(S,r); 84 | 85 | Z = U*s*V'; 86 | end -------------------------------------------------------------------------------- /ADMM 1D Denoising/ADMM_1D_HOTV.m: -------------------------------------------------------------------------------- 1 | function out = ADMM_1D_HOTV(f,lam,rho, Nit) 2 | % Created by Tarmizi Adam on 7/3/2017 3 | %This is a simple program for 1D Signal denoising using total variation 4 | % denoising using second 2nd order difference operator (Higher Order TV). 5 | 6 | % The iterative algorithm used in this program is the 7 | % Alternating Direction Methods of Multiplier (ADMM) which is a splitting 8 | % version of the classical Augmented Lagrangian Method (ALM). 9 | 10 | % This solver solves the following minimization problem: 11 | 12 | % min_x lambda/2*||u - f||^2_2 + ||DDu||_1 13 | 14 | % Input: 15 | % f = The noisy observed signal (1D-signal) 16 | % lam = Regularization parameter. Controls the smoothness of the 17 | % denoised signal. 18 | % rho = Regularization parameter related to the constraint (ADMM) 19 | % Nit = Number of iterations to run the ADMM iterative method. 20 | % 21 | % Output: 22 | % out.sol = The denoised signal 23 | % out.funVal = Plot of the convergence of our objective 24 | % function 25 | %% 26 | 27 | f = f(:); 28 | u = f; %Initialize 29 | N = length(f); 30 | mu = zeros(N,1); % Lagrange multiplier 31 | v = mu; %Initialize the v sub-problem 32 | funcVal = zeros(Nit,1); 33 | 34 | [DD,DDT,DDTDD] = defDDt(N); % 2d Order difference operators. 35 | 36 | for k = 1:Nit 37 | u_old = u; 38 | 39 | %% u sub-problem %% 40 | % Solves a linear system using the conjugate gradient method. 41 | [u,~] = cgs(rho*DDTDD + lam*speye(N),lam*f+rho*DDT*(v - mu/rho),1e-5,100); 42 | 43 | %% v sub-problem %% 44 | x = DD*u + mu/rho; 45 | v = shrink(x, 1/rho); 46 | 47 | %% Update Lagrange multiplier 48 | mu = mu + (DD*u - v); 49 | 50 | r1 = u - f; 51 | funcVal(k) = (lam/2)*norm(r1,'fro')^2 + sum(v(:)); 52 | 53 | end 54 | 55 | out.sol = u; 56 | out.funVal = funcVal(1:k); 57 | 58 | end 59 | 60 | function [DD,DDT,DDTDD] = defDDt(N) 61 | %Create a first order difference matrix D 62 | e = ones(N,1); 63 | B = spdiags([e -e], [1 0], N, N); 64 | B(N,1) = 1; 65 | 66 | D = B; 67 | clear B; 68 | DD = D*D; 69 | clear D; 70 | % Create the transpose of D 71 | DDT = DD'; %Remember that DT = -D, also called the backward difference. 72 | DDTDD = DD'*DD; 73 | end 74 | 75 | function z = shrink(x,r) 76 | z = sign(x).*max(abs(x)- r,0); 77 | end 78 | 79 | -------------------------------------------------------------------------------- /ADMM 1D Denoising/AMA_1D.m: -------------------------------------------------------------------------------- 1 | function out = AMA_1D(f,lam,rho, Nit) 2 | % Created by Tarmizi Adam on 24/5/2017 3 | %This is a simple program for 1D Signal denoising using total variation 4 | % denoising. The iterative algorithm used in this program is the 5 | % Alternating Minimization Algorithm (AMA) proposed by Paul Tseng in the 6 | % paper titled: 7 | % "Application of a Splitting Algorithm to Decomposition in 8 | % Convex Programming and Variational Inequalities" 9 | 10 | % This solver solves the following minimization problem: 11 | 12 | % min_x lambda/2*||u - f||^2_2 + ||Du||_1 13 | 14 | % Input: 15 | % f = The noisy observed signal (1D-signal) 16 | % lam = Regularization parameter. Controls the smoothness of the 17 | % denoised signal. 18 | % rho = Regularization parameter related to the constraint (ADMM) 19 | % Nit = Number of iterations to run the ADMM iterative method. 20 | % 21 | % Output: 22 | % out.sol = The denoised signal 23 | % out.funVal = Plot of the convergence of our objective 24 | % function 25 | % 26 | % Remarks: This code is based on the derivation in the authors ADMM notes 27 | % in the subsection AMA TV denoising. 28 | %% 29 | 30 | f = f(:); 31 | u = f; %Initialize 32 | N = length(f); 33 | mu = zeros(N,1); % Lagrange multiplier 34 | v = mu; %Initialize the v sub-problem 35 | funcVal = zeros(Nit,1); 36 | 37 | [D,DT,DTD] = defDDt(N); 38 | 39 | for k = 1:Nit 40 | u_old = u; 41 | 42 | %% u sub-problem %% 43 | 44 | u = f + (1/lam)*DT*mu; %Main difference with ADMM. No need to solve linear system. 45 | 46 | %% v sub-problem %% 47 | x = D*u - mu/rho; 48 | v = shrink(x, 1/rho); 49 | 50 | %% Update Lagrange multiplier 51 | mu = mu + (v - D*u); 52 | 53 | r1 = u - f; 54 | funcVal(k) = (lam/2)*norm(r1,'fro')^2 + sum(v(:)); 55 | 56 | end 57 | 58 | out.sol = u; 59 | out.funVal = funcVal(1:k); 60 | 61 | end 62 | 63 | function [D,DT,DTD] = defDDt(N) 64 | %Create a first order difference matrix D 65 | e = ones(N,1); 66 | B = spdiags([e -e], [1 0], N, N); 67 | B(N,1) = 1; 68 | 69 | D = B; 70 | clear B; 71 | % Create the transpose of D 72 | DT = D'; %Remember that DT = -D, also called the backward difference. 73 | DTD = D'*D; 74 | end 75 | 76 | function z = shrink(x,r) 77 | z = sign(x).*max(abs(x)- r,0); 78 | end 79 | 80 | -------------------------------------------------------------------------------- /ADMM 1D Denoising/ADMM_1D_HOTV_lp.m: -------------------------------------------------------------------------------- 1 | function out = ADMM_1D_HOTV_lp(f,lam,rho,omega,p, Nit) 2 | % Created by Tarmizi Adam on 7/3/2017 3 | %This is a simple program for 1D Signal denoising using total variation 4 | % denoising using second 2nd order difference operator (Higher Order TV). 5 | 6 | % The iterative algorithm used in this program is the 7 | % Alternating Direction Methods of Multiplier (ADMM) which is a splitting 8 | % version of the classical Augmented Lagrangian Method (ALM). 9 | 10 | % This solver solves the following minimization problem: 11 | 12 | % min_x lambda/2*||u - f||^2_2 + omega*||DDu||_p^p 13 | 14 | % Input: 15 | % f = The noisy observed signal (1D-signal) 16 | % lam = Regularization parameter. Controls the smoothness of the 17 | % denoised signal. 18 | % rho = Regularization parameter related to the constraint (ADMM) 19 | % Nit = Number of iterations to run the ADMM iterative method. 20 | % 21 | % Output: 22 | % out.sol = The denoised signal 23 | % out.funVal = Plot of the convergence of our objective 24 | % function 25 | %% 26 | 27 | f = f(:); 28 | u = f; %Initialize 29 | N = length(f); 30 | mu = zeros(N,1); % Lagrange multiplier 31 | v = mu; %Initialize the v sub-problem 32 | funcVal = zeros(Nit,1); 33 | 34 | [DD,DDT,DDTDD] = defDDt(N); % 2d Order difference operators. 35 | 36 | for k = 1:Nit 37 | u_old = u; 38 | 39 | %% u sub-problem %% 40 | % Solves a linear system using the conjugate gradient method. 41 | [u,~] = cgs(rho*DDTDD + lam*speye(N),lam*f+rho*DDT*(v - mu/rho),1e-5,100); 42 | 43 | %% v sub-problem %% 44 | x = DD*u + mu/rho; 45 | wgt = omega*p./(abs(DD*u)+ 0.00001).^(1-(p)); 46 | v = shrink(x, wgt.*omega/rho); 47 | 48 | %% Update Lagrange multiplier 49 | mu = mu + (DD*u - v); 50 | 51 | r1 = u - f; 52 | funcVal(k) = (lam/2)*norm(r1,'fro')^2 + sum(v(:)); 53 | 54 | end 55 | 56 | out.sol = u; 57 | out.funVal = funcVal(1:k); 58 | 59 | end 60 | 61 | function [DD,DDT,DDTDD] = defDDt(N) 62 | %Create a first order difference matrix D 63 | e = ones(N,1); 64 | B = spdiags([e -e], [1 0], N, N); 65 | B(N,1) = 1; 66 | 67 | D = B; 68 | clear B; 69 | DD = D*D; 70 | clear D; 71 | % Create the transpose of D 72 | DDT = DD'; %Remember that DT = -D, also called the backward difference. 73 | DDTDD = DD'*DD; 74 | end 75 | 76 | function z = shrink(x,r) 77 | z = sign(x).*max(abs(x)- r,0); 78 | end 79 | 80 | -------------------------------------------------------------------------------- /Split Bregman Deblurring/splitBreg.m: -------------------------------------------------------------------------------- 1 | function out = splitBreg(g,Img,H,lam,mu,Nit,tol) 2 | %% 3 | % The program solves the following core objective function 4 | % using Split Bregman method 5 | % 6 | % min_f mu/2*||Hf - g||^2 + ||Df||_1 7 | % 8 | % where ||DF||_1 is |D_h*f| + |D_v*f| 9 | % References: 10 | % [1] Goldstein, Tom, and Stanley Osher. "The split Bregman method for L1-regularized problems." 11 | % SIAM Journal on Imaging Sciences 2.2 (2009): 323-343. 12 | %% 13 | 14 | [row,col] = size(g); 15 | f = g; 16 | x = zeros(row,col); 17 | y = zeros(row,col); 18 | bx = zeros(row,col); 19 | by = zeros(row,col); 20 | 21 | 22 | relError = zeros(Nit,1); % Compute error relative to the previous iteration. 23 | relErrorImg = relError; %Compute error relative to the original image 24 | psnrGain = relError; % PSNR improvement every iteration 25 | funcVal = relError; %Function value at each iteration 26 | 27 | 28 | eigHtH = psf2otf(H,[row,col]); 29 | Htg = imfilter(g, H, 'circular'); 30 | 31 | [D,Dt] = defDDt(); %Declare forward finite difference operators 32 | 33 | %=================== Main algorithm starts here ====================== 34 | nabla = fspecial('laplacian',0); 35 | lhs = mu*conj(eigHtH).*eigHtH - lam*psf2otf(nabla, [row col]); 36 | 37 | for k=1:Nit 38 | 39 | f_old = f; 40 | 41 | rhs = mu*Htg + lam*Dt(x - bx, y - by); 42 | 43 | f = fft2(rhs)./lhs; 44 | f = real(ifft2(f)); 45 | 46 | [Dfx, Dfy] = D(f); 47 | %Dfx = Dx(f); 48 | %Dfy = Dy(f); 49 | 50 | x = shrink(Dfx + bx,1/lam); 51 | y = shrink(Dfy + by,1/lam); 52 | 53 | % update bregman parameters 54 | bx = bx + Dfx - x; 55 | by = by + Dfy - y; 56 | 57 | relError(k) = norm(f - f_old,'fro')/norm(f, 'fro'); 58 | relErrorImg(k) = norm(Img - f,'fro')/norm(Img,'fro'); 59 | psnrGain(k) = psnr_fun(f,Img); 60 | 61 | r1 = imfilter(f, H, 'circular')-g; 62 | funcVal(k) = (lam/2)*norm(r1,'fro')^2 + sum(Dfx(:)+Dfy(:)); 63 | 64 | % if relError(k) < tol 65 | %break 66 | %end 67 | end 68 | 69 | %======================= Results ============================== 70 | out.psnrf = psnr_fun(f, Img); 71 | out.ssimf = ssim_index(f,Img); 72 | out.sol = f; %Deblurred image 73 | out.relativeError = relError(1:k); 74 | out.relativeErrorImg = relErrorImg(1:k); 75 | out.psnrGain = psnrGain(1:k) 76 | out.functionValue = funcVal(1:k); 77 | end 78 | 79 | function [D,Dt] = defDDt() 80 | D = @(U) ForwardDiff(U); 81 | Dt = @(X,Y) Dive(X,Y); 82 | end 83 | 84 | function [Dux,Duy] = ForwardDiff(U) 85 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 86 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 87 | end 88 | 89 | function DxyT = Dive(X,Y) 90 | 91 | [rows, cols] = size(X); 92 | dxt = zeros(rows, cols); 93 | dxt(:,1:cols-1) = X(:,1:cols-1)-X(:,2:cols); 94 | dxt(:,cols) = X(:,cols)-X(:,1); 95 | 96 | dyt = zeros(rows, cols); 97 | dyt(1:rows-1,:) = Y(1:rows-1,:)-Y(2:rows,:); 98 | dyt(rows,:) = Y(rows,:)-Y(1,:); 99 | 100 | DxyT = dxt + dyt; 101 | 102 | end 103 | 104 | function z = shrink(x,r) 105 | z = sign(x).*max(abs(x)-r,0); 106 | end 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /NonConvex_Lp ADMM/lpALM.m: -------------------------------------------------------------------------------- 1 | function out = lpALM(y, Img, H, mu, rho, Nit,p, tol) 2 | 3 | %Created by Tarmizi on 11/02/ 2016 4 | % Non-convex lp total variation deblurring.... 5 | % the total variation deblurring in this code uses non-convex penalty 6 | % function which is the lp norm where 0 < p < 1. 7 | % This code minimizes the objective function: 8 | % 9 | % 1/2 ||y - Hx||_2^2 + mu*||Dx||_p^p 10 | % 11 | % In this code, we apply the Augmented Lagrangian Method (ALM) with 12 | % ADMM to handel the subproblems and use the 13 | % IRL1 algorithm to approximately solve the lp penalty. 14 | 15 | % If you happen to use this code for any research work, feel free to email 16 | % me just to let me know, at tarmizi_adam2005@yahoo.com 17 | % OR if you find any bugs also feel free to email me. 18 | 19 | %If you use this code, use it at your own risk. No guarantees are provided 20 | %for its usage. 21 | 22 | [row,col] = size(y); 23 | x = y; 24 | 25 | v1 = zeros(row,col); %Initialize intermediate variables for v subproblem 26 | v2 = zeros(row,col); % " " " for v subproblem 27 | 28 | y1 = zeros(row,col); %Initialize Lagrange Multipliers 29 | y2 = zeros(row,col); % " Lagrange Multipliers 30 | 31 | relError = zeros(Nit,1); % Compute error relative to the previous iteration. 32 | relErrorImg = relError; %Compute error relative to the original image 33 | psnrGain = relError; % PSNR improvement every iteration 34 | funcVal = relError; %Function value at each iteration 35 | 36 | eigHtH = abs(fft2(H,row,col)).^2; %eigen value for HtH 37 | eigDtD = abs(fft2([1 -1], row, col)).^2 + abs(fft2([1 -1]', row, col)).^2; 38 | 39 | Hty = imfilter(y, H, 'circular'); 40 | 41 | [D,Dt] = defDDt(); %Declare forward finite difference operators 42 | [Dx1, Dx2] = D(x); 43 | 44 | for k=1:Nit 45 | 46 | x_old = x; 47 | rhs = Hty + rho*Dt(v1 - (1/rho)*y1, v2 - (1/rho)*y2); 48 | eigA = eigHtH + rho*eigDtD; 49 | x = fft2(rhs)./eigA; 50 | x = real(ifft2(x)); 51 | 52 | [Dx1, Dx2] = D(x); 53 | 54 | w1 = mu*p./(abs(Dx1)+ 0.0001).^(1-(p)); %IRL1 Weight update 55 | w2 = mu*p./(abs(Dx2) + 0.0001).^(1-(p));% IRL1 Weight update 56 | 57 | u1 = Dx1 + y1; 58 | u2 = Dx2 + y2; 59 | 60 | v1 = shrink(u1,0.5*w1.*mu/rho)- y1; 61 | v2 = shrink(u2,0.5*w2.*mu/rho) - y2; 62 | 63 | 64 | y1 = Dx1 - v1; 65 | y2 = Dx2 -v2; 66 | 67 | relError(k) = norm(x - x_old,'fro')/norm(x, 'fro'); 68 | r1 = imfilter(x, H, 'circular')-y; 69 | funcVal(k) = (1/2)*norm(r1,'fro')^2 + mu*sum(Dx1(:)+Dx2(:)); 70 | 71 | if relError(k) < tol 72 | break 73 | end 74 | 75 | end 76 | 77 | out.psnrf = psnr_fun(x, Img); 78 | out.ssimf = ssim_index(x,Img); 79 | out.sol = x; %Deblurred image 80 | out.functionValue = funcVal(1:k); 81 | out.relativeError = relError(1:k); 82 | end 83 | 84 | function [D,Dt] = defDDt() 85 | D = @(U) ForwardDiff(U); 86 | Dt = @(X,Y) Dive(X,Y); 87 | end 88 | 89 | function [Dux,Duy] = ForwardDiff(U) 90 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 91 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 92 | end 93 | 94 | function DtXY = Dive(X,Y) 95 | % Transpose of the forward finite difference operator 96 | % is the divergence fo the forward finite difference operator 97 | DtXY = [X(:,end) - X(:, 1), -diff(X,1,2)]; 98 | DtXY = DtXY + [Y(end,:) - Y(1, :); -diff(Y,1,1)]; 99 | end 100 | 101 | function z = shrink(x,r) 102 | z = sign(x).*max(abs(x)-r,0); 103 | end -------------------------------------------------------------------------------- /l0_TV Denoising/L0_ADMM.m: -------------------------------------------------------------------------------- 1 | 2 | % Created by Tarmizi adam and Yin Mingming on 27/8/19 3 | % Re-implementation of Yuan and Ghanem L0-TV from the following paper: 4 | 5 | % [1] Yuan, G., & Ghanem, B. (2017). $\ell _0 $ TV: A Sparse Optimization Method for 6 | % Impulse Noise Image Restoration. IEEE transactions on pattern analysis 7 | % and machine intelligence, 41(2), 352-364. 8 | 9 | % code is currently working fine. 10 | 11 | %Notes: 12 | % In the original paper [1] The authors used proximal-ADMM (PADMM) to 13 | % minimized the L0-TV problem. However, in this re-implementation of 14 | % ours, we use standard ADMM. Therefore in return, we will solve a 15 | % linear system of equation for the u-subproblem using FFTs. 16 | 17 | 18 | function out = L0_ADMM(f,Img,K,opts) 19 | 20 | lam = opts.lam; 21 | o = opts.O; % mask 22 | Nit = opts.Nit; 23 | tol = opts.tol; 24 | 25 | beta_1 = 300; 26 | beta_2 = 300; 27 | beta_3 = 100; 28 | 29 | [row, col] = size(f); 30 | u = f; 31 | 32 | v = ones(size(u)); 33 | 34 | relError = zeros(Nit,1); 35 | 36 | epsi_1 = 1e-3*randn(size(f)); 37 | epsi_2 = epsi_1; 38 | delta = epsi_1; 39 | pio = epsi_1; 40 | 41 | 42 | eigK = psf2otf(K,[row col]); %In the fourier domain 43 | eigKtK = abs(eigK).^2; 44 | eigDtD = abs(fft2([1 -1], row, col)).^2 + abs(fft2([1 -1]', row, col)).^2; 45 | 46 | [D,Dt] = defDDt(); %Declare forward finite difference operators 47 | [Dux, Duy] = D(u); 48 | 49 | 50 | lhs = beta_2*eigKtK + beta_1*eigDtD; % From normal eqns. 51 | Ku__f = imfilter (u,K,'circular') -f; % Ku-f 52 | 53 | 54 | for k = 1:Nit 55 | 56 | u_old = u; 57 | 58 | %*** solve y - subproblem *** 59 | w = v.*o; 60 | 61 | A = beta_3*v.*w + beta_2; 62 | B = -delta - beta_2*Ku__f; 63 | C = pio.*w; 64 | 65 | y = threshold_1(B./A,C./A); 66 | 67 | %*** solve x - subproblem *** 68 | xn1 = Dux + epsi_1/beta_1; % The "noisy" x from previous 69 | xn2 = Duy + epsi_2/beta_1; % iterates... 70 | 71 | x1 = shrink(xn1,lam/beta_1); 72 | x2 = shrink(xn2,lam/beta_1); 73 | 74 | 75 | %*** solve u - subproblem *** 76 | ftemp = beta_2*y + beta_2*f - delta; 77 | rhs = imfilter(ftemp,K,'circular') + Dt(beta_1*x1 - epsi_1 ,beta_1*x2 - epsi_2); 78 | u = fft2(rhs)./lhs; 79 | u = real(ifft2(u)); 80 | 81 | 82 | [Dux, Duy] = D(u); 83 | Ku__f = imfilter (u,K,'circular') -f; 84 | 85 | %*** solve v - subproblem *** 86 | s = beta_3*y.*y.*o ; 87 | 88 | c = pio.*abs(y.*o) - 1 ; 89 | v = max(-c./s,0); 90 | v = min(v,1); 91 | 92 | %*** Update the Lagrange multipliers *** 93 | epsi_1 = epsi_1 + beta_1*(Dux - x1); 94 | epsi_2 = epsi_2 + beta_1*(Duy - x2); 95 | 96 | delta = delta + beta_2*(Ku__f - y); 97 | pio = pio + beta_3*(v.*abs(y.*o)); 98 | 99 | 100 | relError(k) = norm(u - u_old,'fro')/norm(u, 'fro'); 101 | 102 | if relError(k) < tol 103 | break; 104 | end 105 | 106 | end 107 | 108 | out.sol = u; 109 | out.relativeError = relError(1:k); 110 | 111 | end 112 | 113 | function [D,Dt] = defDDt() 114 | D = @(U) ForwardDiff(U); 115 | Dt = @(X,Y) Dive(X,Y); 116 | end 117 | 118 | function [Dux,Duy] = ForwardDiff(U) 119 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 120 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 121 | end 122 | 123 | function DtXY = Dive(X,Y) 124 | % Transpose of the forward finite difference operator 125 | % is the divergence fo the forward finite difference operator 126 | DtXY = [X(:,end) - X(:, 1), -diff(X,1,2)]; 127 | DtXY = DtXY + [Y(end,:) - Y(1, :); -diff(Y,1,1)]; 128 | end 129 | 130 | function z = shrink(x,r) 131 | z = sign(x).*max(abs(x)-r,0); 132 | end 133 | 134 | function x = threshold_1(a,b) 135 | x = -sign(a).*max(0,abs(a) - b); 136 | end 137 | 138 | -------------------------------------------------------------------------------- /ALMTV.m: -------------------------------------------------------------------------------- 1 | function [f, relchg] = ALMTV(g,H,lam,rho,Nit,tol) 2 | %% 3 | %==========Anisotropic Total variation using Augmented Lagrangian==== 4 | % ALMTV: Augmented Lagrangian Method Total Variation 5 | % The original paper [1] Takes into account image and video restorations. 6 | % This code is a little modification for just gray scale image restoration. 7 | % This code does not support video restoration like [1]. Only the 8 | % mathematical theory used in [1] to code this program. 9 | 10 | %inputs: 11 | % g : Observed blurred(and possibly noisy) image 12 | % H : Point spread function/Blurring kernel (A linear operator) 13 | % lam : regularization parameter 14 | % rho : regularization parameter of the Augmented Lagrangian form 15 | % of the main problem. 16 | % Nit : Number of iterations 17 | % tol : Error tolerance for stopping criteria 18 | 19 | %============== References==================== 20 | % See the following papers 21 | 22 | % [1] Chan, Stanley H., Ramsin Khoshabeh, Kristofor B. Gibson, Philip E. Gill, 23 | % and Truong Q. Nguyen. "An augmented Lagrangian method for total variation 24 | % video restoration." Image Processing, IEEE Transactions on 20, no. 11 25 | % (2011): 3097-3111. 26 | 27 | % [2] Chan, Stanley H., Ramsin Khoshabeh, Kristofor B. Gibson, Philip E. Gill, and 28 | % Truong Q. Nguyen. "An augmented Lagrangian method for video restoration." In 29 | % Acoustics, Speech and Signal Processing (ICASSP), 2011 IEEE International 30 | % Conference on, pp. 941-944. IEEE, 2011. 31 | 32 | % The program solves the following core objective function 33 | 34 | % min_f lam/2*||Hf - g||^2 + ||Df||_1 35 | 36 | %% 37 | 38 | [row,col] = size(g); 39 | f = g; 40 | 41 | u1 = zeros(row,col); %Initialize intermediat variables for u subproblem 42 | u2 = zeros(row,col); % " " " for u subproblem 43 | 44 | y1 = zeros(row,col); %Initialize Lagrange Multipliers 45 | y2 = zeros(row,col); % " Lagrange Multipliers 46 | 47 | eigHtH = abs(fft2(H,row,col)).^2; %eigen value for HtH 48 | eigDtD = abs(fft2([1 -1], row, col)).^2 + abs(fft2([1 -1]', row, col)).^2 % eigen value ofDtD 49 | Htg = imfilter(g, H, 'circular'); 50 | 51 | [D,Dt] = defDDt(); %Declare forward finite difference operators 52 | [Df1, Df2] = D(f); 53 | 54 | rnorm = sqrt(norm(Df1(:))^2 + norm(Df2(:))^2); 55 | 56 | for k=1:Nit 57 | 58 | %Solving the f subproblem 59 | f_old = f; 60 | rhs = lam*Htg + Dt(u1 - (1/rho)*y1, u2 - (1/rho)*y2); 61 | eigA = lam*eigHtH + rho*eigDtD; 62 | f = fft2(rhs)./eigA; 63 | f = real(ifft2(f)); 64 | 65 | 66 | %Solving the u subproblem 67 | [Df1, Df2] = D(f); 68 | v1 = Df1 + (1/rho)*y1; 69 | v2 = Df2 + (1/rho)*y2; 70 | 71 | u1 = shrink(v1,1/lam); 72 | u2 = shrink(v2,1/lam); 73 | 74 | %Update y, the Lagrange multipliers 75 | y1 = y1 - rho*(u1 - Df1); 76 | y2 = y2 - rho*(u2 - Df2); 77 | 78 | rnorm_old = rnorm; 79 | rnorm = sqrt(norm(Df1(:)-u1(:), 'fro')^2 + norm(Df2(:)-u2(:), 'fro')^2); 80 | 81 | relchg = norm(f(:)-f_old(:))/norm(f_old(:)); 82 | relchg(Nit) = relchg; 83 | 84 | if relchg < tol 85 | break 86 | end 87 | 88 | end 89 | end 90 | 91 | 92 | function [D,Dt] = defDDt() 93 | D = @(U) ForwardDiff(U); 94 | Dt = @(X,Y) Dive(X,Y); 95 | end 96 | 97 | function [Dux,Duy] = ForwardDiff(U) 98 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 99 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 100 | end 101 | 102 | function DtXY = Dive(X,Y) 103 | % Transpose of the forward finite difference operator 104 | % Divergence 105 | DtXY = [X(:,end) - X(:, 1), -diff(X,1,2)]; 106 | DtXY = DtXY + [Y(end,:) - Y(1, :); -diff(Y,1,1)]; 107 | end 108 | 109 | function z = shrink(x,r) 110 | z = sign(x).*max(abs(x)-r,0); 111 | end -------------------------------------------------------------------------------- /NonConvex_Lp ADMM/lpALM_rhoUpdate.m: -------------------------------------------------------------------------------- 1 | function out = lpALM(y, Img, H, mu, rho, Nit,p, tol) 2 | 3 | %Created by Tarmizi on 11/02/ 2016 4 | %Update: 17/6/2016. Added rho updating in each iteration. 5 | % to speed up the convergence rate 6 | 7 | % Non-convex lp total variation deblurring.... 8 | % the total variation deblurring in this code uses non-convex penalty 9 | % function which is the lp norm where 0 < p < 1. 10 | % This code minimizes the objective function: 11 | % 12 | % 1/2 ||y - Hx||_2^2 + mu*||Dx||_p^p 13 | % 14 | % In this code, we apply the Augmented Lagrangian Method (ALM) with 15 | % ADMM to handel the subproblems and use the 16 | % IRL1 algorithm to approximately solve the lp penalty. 17 | 18 | % If you happen to use this code for any research work, feel free to email 19 | % me just to let me know, at tarmizi_adam2005@yahoo.com 20 | % OR if you find any bugs also feel free to email me. 21 | 22 | %If you use this code, use it at your own risk. No guarantees are provided 23 | %for its usage. 24 | 25 | [row,col] = size(y); 26 | x = y; 27 | 28 | alpha = 0.7; 29 | v1 = zeros(row,col); %Initialize intermediate variables for v subproblem 30 | v2 = zeros(row,col); % " " " for v subproblem 31 | 32 | y1 = zeros(row,col); %Initialize Lagrange Multipliers 33 | y2 = zeros(row,col); % " Lagrange Multipliers 34 | 35 | relError = zeros(Nit,1); % Compute error relative to the previous iteration. 36 | relErrorImg = relError; %Compute error relative to the original image 37 | psnrGain = relError; % PSNR improvement every iteration 38 | funcVal = relError; %Function value at each iteration 39 | 40 | eigHtH = abs(fft2(H,row,col)).^2; %eigen value for HtH 41 | eigDtD = abs(fft2([1 -1], row, col)).^2 + abs(fft2([1 -1]', row, col)).^2; 42 | 43 | Hty = imfilter(y, H, 'circular'); 44 | 45 | [D,Dt] = defDDt(); %Declare forward finite difference operators 46 | [Dx1, Dx2] = D(x); 47 | 48 | curNorm = sqrt(norm(Dx1(:) - v1(:),'fro'))^2 + sqrt(norm(Dx2(:) - v2(:),'fro'))^2; 49 | 50 | for k=1:Nit 51 | 52 | x_old = x; 53 | rhs = Hty + rho*Dt(v1 - (1/rho)*y1, v2 - (1/rho)*y2); 54 | eigA = eigHtH + rho*eigDtD; 55 | x = fft2(rhs)./eigA; 56 | x = real(ifft2(x)); 57 | 58 | [Dx1, Dx2] = D(x); 59 | 60 | w1 = mu*p./(abs(Dx1)+ 0.0001).^(1-(p)); %IRL1 Weight update 61 | w2 = mu*p./(abs(Dx2) + 0.0001).^(1-(p));% IRL1 Weight update 62 | 63 | u1 = Dx1 + y1; 64 | u2 = Dx2 + y2; 65 | 66 | v1 = shrink(u1,0.5*w1.*mu/rho)- y1; 67 | v2 = shrink(u2,0.5*w2.*mu/rho) - y2; 68 | 69 | 70 | y1 = Dx1 - v1; 71 | y2 = Dx2 -v2; 72 | 73 | relError(k) = norm(x - x_old,'fro')/norm(x, 'fro'); 74 | r1 = imfilter(x, H, 'circular')-y; 75 | funcVal(k) = (1/2)*norm(r1,'fro')^2 + mu*sum(Dx1(:)+Dx2(:)); 76 | 77 | % ****Update the rho at each iteration to accelerate the convergence*** 78 | % Compare the acceleration with and without the rho updating. 79 | normOld = curNorm; 80 | curNorm = sqrt(norm(Dx1(:) - v1(:),'fro'))^2 + sqrt(norm(Dx2(:) - v2(:),'fro'))^2; 81 | % **********Update rho condition starts here ***************** 82 | if curNorm > alpha*normOld 83 | rho = 2*rho; 84 | end 85 | %************************************************************* 86 | 87 | if relError(k) < tol 88 | break 89 | end 90 | 91 | end 92 | 93 | out.psnrf = psnr_fun(x, Img); 94 | out.ssimf = ssim_index(x,Img); 95 | out.sol = x; %Deblurred image 96 | out.functionValue = funcVal(1:k); 97 | out.relativeError = relError(1:k); 98 | end 99 | 100 | function [D,Dt] = defDDt() 101 | D = @(U) ForwardDiff(U); 102 | Dt = @(X,Y) Dive(X,Y); 103 | end 104 | 105 | function [Dux,Duy] = ForwardDiff(U) 106 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 107 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 108 | end 109 | 110 | function DtXY = Dive(X,Y) 111 | % Transpose of the forward finite difference operator 112 | % is the divergence fo the forward finite difference operator 113 | DtXY = [X(:,end) - X(:, 1), -diff(X,1,2)]; 114 | DtXY = DtXY + [Y(end,:) - Y(1, :); -diff(Y,1,1)]; 115 | end 116 | 117 | function z = shrink(x,r) 118 | z = sign(x).*max(abs(x)-r,0); 119 | end -------------------------------------------------------------------------------- /ADMM Color Image Denoising/ADMM.m: -------------------------------------------------------------------------------- 1 | function out = ADMM(y,Img,lam,rho,Nit,tol,regType) 2 | % created by Tarmizi Adam 16/5/2016 3 | %Update: 26/5/2016 4 | %Update: 15/6/2016 added rho updating for accelerating convergence. 5 | % rho updating reference: 6 | % - Chan, Stanley H., Ramsin Khoshabeh, Kristofor B. Gibson, Philip E. Gill, and 7 | % Truong Q. Nguyen. "An augmented Lagrangian method for video restoration." In 8 | % Acoustics, Speech and Signal Processing (ICASSP), 2011 IEEE International 9 | % Conference on, pp. 941-944. IEEE, 2011. 10 | 11 | %Update: 29/6/2016, added Isotropic TV regularization (function 12 | % isoShrink()) 13 | 14 | % ADMM image denoising. This script solve the optimization problem 15 | % 16 | % min_x 1/2*||y - x||^2_2 + lamda||Dx||_1 17 | 18 | %Dependencies: this code depends on the function 19 | % psnr_fun(x, Img) and ssim_index(x,Img) for computing the PSNR and SSIM 20 | % of the resulting denoised image. This function can be replaced by other 21 | % PSNR or SSIM function that you have. 22 | 23 | [row,col] = size(y); 24 | x = y; 25 | alpha = 0.7; 26 | v1 = zeros(row,col); %Initialize intermediate variables for v subproblem 27 | v2 = zeros(row,col); % " " " for v subproblem 28 | 29 | y1 = zeros(row,col); %Initialize Lagrange Multipliers 30 | y2 = zeros(row,col); % " Lagrange Multipliers 31 | 32 | relError = zeros(Nit,1); % Compute error relative to the previous iteration. 33 | relErrorImg = relError; %Compute error relative to the original image 34 | psnrGain = relError; % PSNR improvement every iteration 35 | funcVal = relError; %Function value at each iteration 36 | 37 | eigDtD = abs(fft2([1 -1], row, col)).^2 + abs(fft2([1 -1]', row, col)).^2; 38 | 39 | [D,Dt] = defDDt(); %Declare forward finite difference operators 40 | [Dx1, Dx2] = D(x); 41 | 42 | curNorm = sqrt(norm(Dx1(:) - v1(:),'fro'))^2 + sqrt(norm(Dx2(:) - v2(:),'fro'))^2; 43 | 44 | tg = tic; 45 | 46 | for k=1:Nit 47 | 48 | x_old = x; 49 | rhs = y - rho*Dt(y1/rho + v1, y2/rho + v2); 50 | lhs = 1 + rho*(eigDtD); 51 | 52 | x = fft2(rhs)./lhs; 53 | x = real(ifft2(x)); 54 | 55 | [Dx1, Dx2] = D(x); 56 | 57 | u1 = Dx1 + y1/rho; 58 | u2 = Dx2 + y2/rho; 59 | 60 | switch regType 61 | case 'ani' 62 | %If using anisotropic TV 63 | v1 = shrink(u1, lam/rho); %lam/rho 64 | v2 = shrink(u2, lam/rho); 65 | case 'iso' 66 | %If using isotropic TV 67 | [v1,v2] = isoShrink(u1,u2,lam/rho); 68 | 69 | otherwise 70 | warning('No such regularization !, Denoising failed !') 71 | break; 72 | end 73 | y1 = y1 - rho*(v1 - Dx1); 74 | y2 = y2 - rho*(v2 - Dx2); 75 | 76 | relError(k) = norm(x - x_old,'fro')/norm(x, 'fro'); 77 | r1 = x-y; 78 | funcVal(k) = (1/2)*norm(r1,'fro')^2 + lam*sum(Dx1(:) + Dx2(:)); 79 | 80 | % ****Update the rho at each iteration to accelerate the convergence*** 81 | % Compare the acceleration with and without the rho updating. 82 | normOld = curNorm; 83 | curNorm = sqrt(norm(Dx1(:) - v1(:),'fro'))^2 + sqrt(norm(Dx2(:) - v2(:),'fro'))^2; 84 | % **********Update rho condition starts here ***************** 85 | if curNorm > alpha*normOld 86 | rho = 0.5*rho; 87 | end 88 | %************************************************************* 89 | 90 | if relError(k) < tol 91 | break 92 | end 93 | 94 | end 95 | 96 | tg = toc(tg); 97 | 98 | out.sol = x; %Deblurred image 99 | out.functionValue = funcVal(1:k); 100 | out.relativeError = relError(1:k); 101 | out.cpuTime = tg; 102 | out.finalRho = rho; 103 | 104 | end 105 | 106 | function [D,Dt] = defDDt() 107 | D = @(U) ForwardDiff(U); 108 | Dt = @(X,Y) Dive(X,Y); 109 | end 110 | 111 | function [Dux,Duy] = ForwardDiff(U) 112 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 113 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 114 | end 115 | 116 | function DtXY = Dive(X,Y) 117 | % Transpose of the forward finite difference operator 118 | % is the divergence fo the forward finite difference operator 119 | DtXY = [X(:,end) - X(:, 1), -diff(X,1,2)]; 120 | DtXY = DtXY + [Y(end,:) - Y(1, :); -diff(Y,1,1)]; 121 | end 122 | 123 | function z = shrink(x,r) 124 | z = sign(x).*max(abs(x)- r,0); 125 | end 126 | 127 | function [v1, v2] = isoShrink(u1,u2,r) 128 | u = sqrt(u1.^2 + u2.^2); 129 | u(u==0) = 1; 130 | u = max(u - r,0)./u; 131 | 132 | v1 = u1.*u; 133 | v2 = u2.*u; 134 | end 135 | 136 | -------------------------------------------------------------------------------- /ADMM Image Denoising/ADMM.m: -------------------------------------------------------------------------------- 1 | function out = ADMM(y,Img,lam,rho,Nit,tol,regType) 2 | % created by Tarmizi Adam 16/5/2016 3 | %Update: 26/5/2016 4 | %Update: 15/6/2016 added rho updating for accelerating convergence. 5 | % rho updating reference: 6 | % - Chan, Stanley H., Ramsin Khoshabeh, Kristofor B. Gibson, Philip E. Gill, and 7 | % Truong Q. Nguyen. "An augmented Lagrangian method for video restoration." In 8 | % Acoustics, Speech and Signal Processing (ICASSP), 2011 IEEE International 9 | % Conference on, pp. 941-944. IEEE, 2011. 10 | 11 | %Update: 29/6/2016, added Isotropic TV regularization (function 12 | % isoShrink()) 13 | 14 | % ADMM image denoising. This script solve the optimization problem 15 | % 16 | % min_x 1/2*||y - x||^2_2 + lamda||Dx||_1 17 | 18 | %Dependencies: this code depends on the function 19 | % psnr_fun(x, Img) and ssim_index(x,Img) for computing the PSNR and SSIM 20 | % of the resulting denoised image. This function can be replaced by other 21 | % PSNR or SSIM function that you have. 22 | 23 | [row,col] = size(y); 24 | x = y; 25 | alpha = 0.7; 26 | v1 = zeros(row,col); %Initialize intermediate variables for v subproblem 27 | v2 = zeros(row,col); % " " " for v subproblem 28 | 29 | y1 = zeros(row,col); %Initialize Lagrange Multipliers 30 | y2 = zeros(row,col); % " Lagrange Multipliers 31 | 32 | relError = zeros(Nit,1); % Compute error relative to the previous iteration. 33 | relErrorImg = relError; %Compute error relative to the original image 34 | psnrGain = relError; % PSNR improvement every iteration 35 | funcVal = relError; %Function value at each iteration 36 | 37 | eigDtD = abs(fft2([1 -1], row, col)).^2 + abs(fft2([1 -1]', row, col)).^2; 38 | 39 | [D,Dt] = defDDt(); %Declare forward finite difference operators 40 | [Dx1, Dx2] = D(x); 41 | 42 | curNorm = sqrt(norm(Dx1(:) - v1(:),'fro'))^2 + sqrt(norm(Dx2(:) - v2(:),'fro'))^2; 43 | 44 | tg = tic; 45 | 46 | for k=1:Nit 47 | 48 | x_old = x; 49 | rhs = y - rho*Dt(y1/rho + v1, y2/rho + v2); 50 | lhs = 1 + rho*(eigDtD); 51 | 52 | x = fft2(rhs)./lhs; 53 | x = real(ifft2(x)); 54 | 55 | [Dx1, Dx2] = D(x); 56 | 57 | u1 = Dx1 + y1/rho; 58 | u2 = Dx2 + y2/rho; 59 | 60 | switch regType 61 | case 'ani' 62 | %If using anisotropic TV 63 | v1 = shrink(u1, lam/rho); %lam/rho 64 | v2 = shrink(u2, lam/rho); 65 | case 'iso' 66 | %If using isotropic TV 67 | [v1,v2] = isoShrink(u1,u2,lam/rho); 68 | 69 | otherwise 70 | warning('No such regularization !, Denoising failed !') 71 | break; 72 | end 73 | y1 = y1 - rho*(v1 - Dx1); 74 | y2 = y2 - rho*(v2 - Dx2); 75 | 76 | relError(k) = norm(x - x_old,'fro')/norm(x, 'fro'); 77 | r1 = x-y; 78 | funcVal(k) = (1/2)*norm(r1,'fro')^2 + lam*sum(Dx1(:) + Dx2(:)); 79 | 80 | % ****Update the rho at each iteration to accelerate the convergence*** 81 | % Compare the acceleration with and without the rho updating. 82 | normOld = curNorm; 83 | curNorm = sqrt(norm(Dx1(:) - v1(:),'fro'))^2 + sqrt(norm(Dx2(:) - v2(:),'fro'))^2; 84 | % **********Update rho condition starts here ***************** 85 | if curNorm > alpha*normOld 86 | rho = 0.5*rho; 87 | end 88 | %************************************************************* 89 | 90 | if relError(k) < tol 91 | break 92 | end 93 | 94 | end 95 | 96 | tg = toc(tg); 97 | 98 | out.psnrf = psnr_fun(x, Img); 99 | out.ssimf = ssim_index(x,Img); 100 | out.sol = x; %Deblurred image 101 | out.functionValue = funcVal(1:k); 102 | out.relativeError = relError(1:k); 103 | out.cpuTime = tg; 104 | out.finalRho = rho; 105 | 106 | end 107 | 108 | function [D,Dt] = defDDt() 109 | D = @(U) ForwardDiff(U); 110 | Dt = @(X,Y) Dive(X,Y); 111 | end 112 | 113 | function [Dux,Duy] = ForwardDiff(U) 114 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 115 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 116 | end 117 | 118 | function DtXY = Dive(X,Y) 119 | % Transpose of the forward finite difference operator 120 | % is the divergence fo the forward finite difference operator 121 | DtXY = [X(:,end) - X(:, 1), -diff(X,1,2)]; 122 | DtXY = DtXY + [Y(end,:) - Y(1, :); -diff(Y,1,1)]; 123 | end 124 | 125 | function z = shrink(x,r) 126 | z = sign(x).*max(abs(x)- r,0); 127 | end 128 | 129 | function [v1, v2] = isoShrink(u1,u2,r) 130 | u = sqrt(u1.^2 + u2.^2); 131 | u(u==0) = 1; 132 | u = max(u - r,0)./u; 133 | 134 | v1 = u1.*u; 135 | v2 = u2.*u; 136 | end 137 | 138 | -------------------------------------------------------------------------------- /L1_OGS Denoising/gstv2d_imp.m: -------------------------------------------------------------------------------- 1 | function out = gstv2d_imp(f,Img,K,opts) 2 | % Created on 31/8/2019 by Tarmizi Adam 3 | % Version 1.1 4 | % Overlapping Group Sparse TV + ADMM for removing blur with salt and pepper noise 5 | % implementation of the paper: 6 | % "Total Variation with Overlapping GroupSparsity for 7 | % "Image Deblurring under Impulse Noise, 2015, Gang Liu et.al., Plos One 8 | 9 | %The following code solves the following optimization problem 10 | % 11 | % minimize_u lam*||Ku - f ||_1 + OGS(Du) + I(u) 12 | % 13 | % where I(u) is the indicator function. 14 | %% 15 | % Input: 16 | % f : Noisy image (corrupted by salt and pepper noise) 17 | % Img : Original Image 18 | % K : Point spread function (Convolution kernel) 19 | % opts : Options i.e., rho, regularization parameter, No of iterations etc. 20 | % 21 | % Output 22 | % out.sol : Denoised image 23 | % out.relError : relative error 24 | %% 25 | 26 | lam = opts.lam; 27 | tol = opts.tol; 28 | Nit = opts.Nit; 29 | grpSz = opts.grpSz; %Group size 30 | Nit_inner = opts.Nit_inner; 31 | 32 | %******** Regularization parameter related to constraints ****** 33 | %{ 34 | rho_v = 2.5; 35 | rho_z = 2.5; 36 | rho_r = 2.5; 37 | %} 38 | % 39 | rho_v = 0.01; 40 | rho_z = 0.1; 41 | rho_r = 5; 42 | % 43 | relError = zeros(Nit,1); 44 | psnrGain = relError; % PSNR improvement every iteration 45 | ssimGain = relError; 46 | 47 | [row, col] = size(f); 48 | u = f; 49 | 50 | %*** Variables for v subproblems *** 51 | v1 = zeros(row,col); 52 | %v2 = v1; 53 | 54 | %*** Variables for z and r subproblem *** 55 | z = v1; 56 | %r = v1; 57 | 58 | %**** Lagrange multipliers *** 59 | mu_v1 = zeros(row,col); 60 | mu_v2 = mu_v1; 61 | mu_z = mu_v1; 62 | mu_r = mu_v1; 63 | 64 | eigK = psf2otf(K,[row col]); %In the fourier domain 65 | eigKtK = abs(eigK).^2; 66 | eigDtD = abs(fft2([1 -1], row, col)).^2 + abs(fft2([1 -1]', row, col)).^2; 67 | 68 | [D,Dt] = defDDt(); %Declare forward finite difference operators 69 | [Dux, Duy] = D(u); 70 | 71 | lhs = eigKtK + rho_v/rho_r*eigDtD + rho_z/rho_r; % From normal eqns. 72 | q = imfilter (u,K,'circular') -f; 73 | 74 | tg = tic; 75 | for k = 1:Nit 76 | 77 | u_old = u; 78 | 79 | %*** solve v - subproblem (OGS-TV problem) *** 80 | v1 = gstvdm(Dux + mu_v1/rho_v , grpSz , 1/rho_v, Nit_inner); 81 | v2 = gstvdm(Duy + mu_v2/rho_v , grpSz , 1/rho_v, Nit_inner); 82 | 83 | %*** solve r - subproblem *** 84 | r = shrink(q + mu_r/rho_r, lam/rho_r); 85 | 86 | %*** solve u - subproblem *** 87 | ftemp = r + f -mu_r/rho_r; 88 | rhs = imfilter(ftemp,K,'circular') + 1/rho_r*Dt(rho_v*v1 - mu_v1,rho_v*v2 - mu_v2) + rho_z/rho_r*z - mu_z/rho_r; 89 | u = fft2(rhs)./lhs; 90 | u = real(ifft2(u)); 91 | 92 | %*** solve z - subproblem *** 93 | z = min(255,max(u + mu_z/rho_z,0)); 94 | 95 | [Dux, Duy] = D(u); 96 | 97 | q = imfilter(u,K,'circular') - f; 98 | 99 | %*** Update the Lagrange multipliers *** 100 | mu_v1 = mu_v1 -1.618*rho_v*(v1- Dux); 101 | mu_v2 = mu_v2 -1.618*rho_v*(v2 - Duy); 102 | 103 | mu_z = mu_z - 1.618*rho_z*(z - u); 104 | mu_r = mu_r - 1.618*rho_r*(r - q); 105 | 106 | %*** Some statistics, this might slow the cpu time of the algo. *** 107 | relError(k) = norm(u - u_old,'fro')/norm(u, 'fro'); 108 | psnrGain(k) = psnr_fun(u,Img); 109 | ssimGain(k) = ssim_index(u,Img); 110 | 111 | if relError(k) < tol 112 | break; 113 | end 114 | 115 | end 116 | 117 | tg = toc(tg); 118 | 119 | out.sol = u; 120 | out.relativeError = relError(1:k); 121 | out.psnrGain = psnrGain(1:k); 122 | out.ssimGain = ssimGain(1:k); 123 | out.cpuTime = tg; 124 | out.psnrRes = psnr_fun(u, Img); 125 | out.ssimRes = ssim_index(u, Img); 126 | out.snrRes = snr_fun(u, Img); 127 | out.OverallItration = size(out.relativeError,1); 128 | 129 | end 130 | 131 | 132 | function [D,Dt] = defDDt() 133 | D = @(U) ForwardDiff(U); 134 | Dt = @(X,Y) Dive(X,Y); 135 | end 136 | 137 | function [Dux,Duy] = ForwardDiff(U) 138 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 139 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 140 | end 141 | 142 | function DtXY = Dive(X,Y) 143 | % Transpose of the forward finite difference operator 144 | % is the divergence fo the forward finite difference operator 145 | DtXY = [X(:,end) - X(:, 1), -diff(X,1,2)]; 146 | DtXY = DtXY + [Y(end,:) - Y(1, :); -diff(Y,1,1)]; 147 | end 148 | 149 | function z = shrink(x,r) 150 | z = sign(x).*max(abs(x)-r,0); 151 | end 152 | -------------------------------------------------------------------------------- /Second Order TV/HOTV.m: -------------------------------------------------------------------------------- 1 | function out = HOTV(f, Img ,K ,opts) 2 | %Copyright, created by Tarmizi Adam on 31/07/2016 3 | %This codes solves the second order (2nd) Total variation model problem 4 | % 5 | % min_u lam/2*||Ku - f||_2^2 + omega*TV(DDu)_iso, 6 | % 7 | %using ADMM where, DDu is the 2nd order difference operator and TV(.)_iso is the 8 | %isotropic total variation functional. This model is reffered as the Lysaker–Lundervold–Tai (LLT) model for image 9 | %restoration. Please refer to the paper: 10 | 11 | % M. Lysaker, A. Lundervold, and X.-C. Tai, Noise removal using fourth-order partial differential 12 | % equations with applications to medical magnetic resonance images in space and time, IEEE Trans. 13 | % Image Process., 12 (2003), pp. 1579–1590. 14 | 15 | % To follow exactly the LLT model, set 'lam = 1' and play around with 'omega'. 16 | %Run this code through the demo .m 17 | %code HOTV_demo.m 18 | 19 | % Any suggestions, errors or bugs feel free to contact me at: 20 | % tarmizi_adam2005@yahoo.com 21 | 22 | [row, col] = size(f); 23 | u = f; 24 | 25 | Nit = opts.Nit; 26 | tol = opts.tol; 27 | lam = opts.lam; % The regularization parameter. 28 | beta = opts.beta; 29 | omega = opts.omega; 30 | alpha = 0.07; 31 | 32 | %v1 = zeros(row,col); %Initialize intermediate variables for v subproblem 33 | %v2 = zeros(row,col); % " " " for v subproblem 34 | 35 | mu1 = zeros(row,col); %Initialize Lagrange Multipliers 36 | mu2 = zeros(row,col); % " Lagrange Multipliers 37 | mu3 = zeros(row,col); 38 | mu4 = zeros(row,col); 39 | 40 | relError = zeros(Nit,1); % Compute error relative to the previous iteration. 41 | funcVal = relError; 42 | psnrGain = relError; 43 | v1 = zeros(row, col); 44 | v2 = v1; 45 | v3 = v1; 46 | v4 = v1; 47 | 48 | 49 | eigK = psf2otf(K,[row col]); %In the fourier domain 50 | eigKtK = abs(eigK).^2; 51 | eigDDtDD = abs(psf2otf([1 -2 1],[row col])).^2 + abs(psf2otf([1 -1;-1 1],[row col])).^2 ... 52 | + abs(psf2otf([1 -1;-1 1],[row col])).^2 + abs(psf2otf([1;-2;1],[row col])).^2; 53 | 54 | 55 | [DD,DDt] = defDDt2; 56 | 57 | [Duxx,Duxy,Duyx,Duyy] = DD(u); 58 | 59 | curNorm = sqrt(norm(Duxx(:) - v1(:),'fro'))^2 + sqrt(norm(Duxy(:) - v2(:),'fro'))^2 + sqrt(norm(Duyx(:) - v3(:),'fro'))^2 + sqrt(norm(Duyy(:) - v4(:),'fro'))^2; 60 | 61 | Ktf = imfilter(f,K,'circular'); 62 | 63 | tg = tic; 64 | 65 | for k = 1:Nit 66 | 67 | x1 = Duxx + mu1/beta; 68 | x2 = Duxy + mu2/beta; 69 | x3 = Duyx + mu3/beta; 70 | x4 = Duyy + mu4/beta; 71 | 72 | [v1, v2, v3, v4] = isoShrink(x1,x2,x3,x4,omega/beta); 73 | 74 | u_old = u; 75 | rhs = lam*Ktf + beta*DDt(v1 - mu1/beta, v2 - mu2/beta, v3 - mu3/beta, v4 - mu4/beta); 76 | lhs = lam*eigKtK + beta*eigDDtDD; 77 | 78 | u = fft2(rhs)./lhs; 79 | u = real(ifft2(u)); 80 | 81 | [Duxx,Duxy,Duyx,Duyy] = DD(u); 82 | 83 | mu1 = mu1 - beta*(v1 - Duxx); 84 | mu2 = mu2 - beta*(v2 - Duxy); 85 | mu3 = mu3 - beta*(v3 - Duyx); 86 | mu4 = mu4 - beta*(v4 - Duyy); 87 | 88 | relError(k) = norm(u - u_old,'fro')/norm(u, 'fro'); 89 | psnrGain(k) = psnr_fun(u,Img); 90 | r1 = imfilter(u, K, 'circular')-f; 91 | funcVal(k) = (lam/2)*norm(r1,'fro')^2 + omega*sqrt(sum(Duxx(:).^2 + Duxy(:).^2 + Duyx(:).^2 + Duyy(:).^2)); 92 | 93 | if relError(k) < tol 94 | break; 95 | end 96 | 97 | normOld = curNorm; 98 | curNorm = sqrt(norm(Duxx(:) - v1(:),'fro'))^2 + sqrt(norm(Duxy(:) - v2(:),'fro'))^2 + sqrt(norm(Duyx(:) - v3(:),'fro'))^2 + sqrt(norm(Duyy(:) - v4(:),'fro'))^2; 99 | 100 | if curNorm > alpha*normOld 101 | beta = 0.95*beta; 102 | end 103 | end 104 | 105 | tg = toc(tg); 106 | 107 | out.sol = u; 108 | out.relativeError = relError(1:k); 109 | out.functionValue = funcVal(1:k); 110 | out.cpuTime = tg; 111 | out.psnrGain = psnrGain(1:k); 112 | out.psnrRes = psnr_fun(u, Img); 113 | out.ssimRes = ssim_index(u, Img); 114 | out.OverallItration = size(out.functionValue,1); %No of itr to converge 115 | 116 | end 117 | 118 | 119 | function [DD,DDt] = defDDt2 120 | % defines finite difference operator D 121 | % and its transpose operator 122 | DD = @(U) ForwardD2(U); 123 | DDt = @(Duxx,Duxy,Duyx,Duyy) Dive2(Duxx,Duxy,Duyx,Duyy); 124 | end 125 | 126 | function [Duxx Duxy Duyx Duyy] = ForwardD2(U) 127 | % 128 | Duxx = [U(:,end) - 2*U(:,1) + U(:,2), diff(U,2,2), U(:,end-1) - 2*U(:,end) + U(:,1)]; 129 | Duyy = [U(end,:) - 2*U(1,:) + U(2,:); diff(U,2,1); U(end-1,:) - 2*U(end,:) + U(1,:)]; 130 | % 131 | Aforward = U(1:end-1, 1:end-1) - U( 2:end,1:end-1) - U(1:end-1,2:end) + U(2:end,2:end); 132 | Bforward = U( end, 1:end-1) - U( 1,1:end-1) - U( end,2:end) + U( 1,2:end); 133 | Cforward = U(1:end-1, end) - U(1:end-1, 1) - U( 2:end, end) + U(2:end, 1); 134 | Dforward = U( end, end) - U( 1, end) - U( end, 1) + U( 1, 1); 135 | % 136 | Eforward = [Aforward ; Bforward]; Fforward = [Cforward ; Dforward]; 137 | Duxy = [Eforward, Fforward]; Duyx = Duxy; 138 | % 139 | end 140 | 141 | function Dt2XY = Dive2(Duxx,Duxy,Duyx,Duyy) 142 | % 143 | Dt2XY = [Duxx(:,end) - 2*Duxx(:,1) + Duxx(:,2), diff(Duxx,2,2), Duxx(:,end-1) - 2*Duxx(:,end) + Duxx(:,1)]; % xx 144 | Dt2XY = Dt2XY + [Duyy(end,:) - 2*Duyy(1,:) + Duyy(2,:); diff(Duyy,2,1); Duyy(end-1,:) - 2*Duyy(end,:) + Duyy(1,:)]; % yy 145 | % 146 | Axy = Duxy(1 , 1) - Duxy( 1, end) - Duxy( end, 1) + Duxy( end, end); 147 | Bxy = Duxy(1 ,2:end) - Duxy( 1,1:end-1) - Duxy( end,2:end) + Duxy( end,1:end-1); 148 | Cxy = Duxy(2:end, 1) - Duxy(1:end-1, 1) - Duxy( 2:end, end) + Duxy(1:end-1, end); 149 | Dxy = Duxy(2:end,2:end) - Duxy( 2:end,1:end-1) - Duxy(1:end-1,2:end) + Duxy(1:end-1,1:end-1); 150 | Exy = [Axy, Bxy]; Fxy = [Cxy, Dxy]; 151 | % 152 | Dt2XY = Dt2XY + [Exy; Fxy]; 153 | Dt2XY = Dt2XY + [Exy; Fxy]; 154 | end 155 | 156 | function [v1, v2, v3, v4] = isoShrink(u1,u2,u3,u4,r) 157 | u = sqrt(u1.^2 + u2.^2 + u3.^2 + u4.^2); 158 | u(u==0) = 1; 159 | u = max(u - r,0)./u; 160 | 161 | v1 = u1.*u; 162 | v2 = u2.*u; 163 | v3 = u3.*u; 164 | v4 = u4.*u; 165 | end 166 | 167 | 168 | --------------------------------------------------------------------------------