├── CG.m ├── Dx.m ├── Dxt.m ├── Dy.m ├── Dyt.m ├── README.md ├── README.pdf ├── XCAT512.mat ├── demo_CG_for_lowdose_ct.m └── img ├── low_dose_image.png └── reconstructed_image.png /CG.m: -------------------------------------------------------------------------------- 1 | %% REFERENCE 2 | % https://en.wikipedia.org/wiki/Conjugate_gradient_method 3 | 4 | %% 5 | function [x, obj] = CG(A,b,x,n,COST,bfig) 6 | 7 | if (nargin < 6) 8 | bfig = false; 9 | end 10 | 11 | if (nargin < 5 || isempty(COST)) 12 | COST.function = @(x) (0); 13 | COST.equation = []; 14 | end 15 | 16 | if (nargin < 4) 17 | n = 1e2; 18 | end 19 | 20 | 21 | % r = b - A*x; 22 | r = b - A(x); 23 | p = r; 24 | 25 | rsold = r(:)'*r(:); 26 | obj = zeros(n, 1); 27 | 28 | for i = 1:n 29 | % Ap = A*p; 30 | Ap = A(p); 31 | a = rsold/(p(:)'*Ap(:)); 32 | 33 | x = x + a*p; 34 | r = r - a*Ap; 35 | 36 | rsnew= r(:)'*r(:); 37 | 38 | if (sqrt(rsnew) < eps) 39 | break; 40 | end 41 | 42 | p = r + (rsnew/rsold)*p; 43 | rsold= rsnew; 44 | 45 | obj(i) = COST.function(x); 46 | 47 | if bfig 48 | figure(1); colormap gray; 49 | subplot(121); imagesc(abs(x)); title([num2str(i) ' / ' num2str(n)]); 50 | subplot(122); semilogy(obj, '*-'); title(COST.equation); xlabel('# of iteration'); ylabel('Objective'); 51 | xlim([1, n]); grid on; grid minor; 52 | drawnow(); 53 | end 54 | end 55 | 56 | x = gather(x); 57 | obj = gather(obj); 58 | 59 | end -------------------------------------------------------------------------------- /Dx.m: -------------------------------------------------------------------------------- 1 | % % function d = Dx(u) 2 | % % d = u; 3 | % % d(:,1:end-1) = u(:,2:end); 4 | % % d(:,end) = u(:,1); 5 | % % d = d - u; 6 | % % return 7 | 8 | function d = Dx(u) 9 | [rows,cols] = size(u); 10 | d = zeros(rows,cols, 'like', u); 11 | d(:,2:cols) = u(:,2:cols)-u(:,1:cols-1); 12 | d(:,1) = u(:,1)-u(:,cols); 13 | return -------------------------------------------------------------------------------- /Dxt.m: -------------------------------------------------------------------------------- 1 | % function d = Dxt(u) 2 | % d = u; 3 | % d(:,1:end-1) = u(:,2:end); 4 | % d(:,end) = u(:,1); 5 | % d(:,2:end) = -(d(:,1:end-1) - u(:,1:end-1)); 6 | % d(:,1) = u(:,end) - u(:,1); 7 | % return 8 | 9 | function d = Dxt(u) 10 | [rows,cols] = size(u); 11 | d = zeros(rows,cols, 'like', u); 12 | d(:,1:cols-1) = u(:,1:cols-1)-u(:,2:cols); 13 | d(:,cols) = u(:,cols)-u(:,1); 14 | return -------------------------------------------------------------------------------- /Dy.m: -------------------------------------------------------------------------------- 1 | % function d = Dy(u) 2 | % d = u; 3 | % d(1:end-1,:) = u(2:end,:); 4 | % d(end,:) = u(1,:); 5 | % d = d - u; 6 | % return 7 | 8 | function d = Dy(u) 9 | [rows,cols] = size(u); 10 | d = zeros(rows,cols, 'like', u); 11 | d(2:rows,:) = u(2:rows,:)-u(1:rows-1,:); 12 | d(1,:) = u(1,:)-u(rows,:); 13 | return -------------------------------------------------------------------------------- /Dyt.m: -------------------------------------------------------------------------------- 1 | % function d = Dyt(u) 2 | % d = u; 3 | % d(1:end-1,:) = u(2:end,:); 4 | % d(end,:) = u(1,:); 5 | % d(2:end,:) = -(d(1:end-1,:) - u(1:end-1,:)); 6 | % d(1,:) = u(end,:) - u(1,:); 7 | % return 8 | 9 | function d = Dyt(u) 10 | [rows,cols] = size(u); 11 | d = zeros(rows,cols, 'like', u); 12 | d(1:rows-1,:) = u(1:rows-1,:)-u(2:rows,:); 13 | d(rows,:) = u(rows,:)-u(1,:); 14 | return -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CG method 2 | 3 | ## Reference 4 | Conjugate Gradient Method `(ENG)` 5 | - https://en.wikipedia.org/wiki/Conjugate_gradient_method 6 | 7 | 켤레기울기법 `(KOR)` 8 | - https://ko.wikipedia.org/wiki/%EC%BC%A4%EB%A0%88%EA%B8%B0%EC%9A%B8%EA%B8%B0%EB%B2%95 9 | 10 | ## Conjugate Gradient Method (CG) 11 | The conjugate gradient method is an algorithm for the numerical solution of particular systems of linear equations, namely those whose matrix is [symmetric](https://en.wikipedia.org/wiki/Symmetric_matrix) and [positive-definite](https://en.wikipedia.org/wiki/Positive-definite_matrix). The conjugate gradient method is often implemented as an [iterative algorithm](https://en.wikipedia.org/wiki/Iterative_method), applicable to sparse systems that are too large to be handled by a direct implementation or other direct methods such as the Cholesky decomposition. 12 | 13 | ## Description of the problem 14 | Suppose we want to solve the [system of linear equations](https://en.wikipedia.org/wiki/System_of_linear_equations) 15 | 16 | (P1) A * x = b : matrix ver. 17 | 18 | or, 19 | 20 | (P2) A( x ) = b : function ver. 21 | 22 | for the vector `x`, where the known n x n matrix `A` is symmetric (i.e., A^T = A), positive-definite (i.e., x^T A x > 0 for all non-zero vectors x in R^n), and real, and `b` is known as well. We denote the unique solution of this system by `x^*`. 23 | 24 | ## The basic iteration CG for solving problem (matrix ver.) 25 | ```matlab 26 | function [x] = conjgrad(A, b, x) 27 | r = b - A * x; 28 | p = r; 29 | rsold = r' * r; 30 | 31 | for i = 1:length(b) 32 | Ap = A * p; 33 | alpha = rsold / (p' * Ap); 34 | x = x + alpha * p; 35 | r = r - alpha * Ap; 36 | rsnew = r' * r; 37 | if sqrt(rsnew) < 1e-10 38 | break; 39 | end 40 | p = r + (rsnew / rsold) * p; 41 | rsold = rsnew; 42 | end 43 | end 44 | ``` 45 | 46 | ## The basic iteration CG for solving problem (function ver.) 47 | 48 | ```matlab 49 | function [x] = conjgrad(A, b, x, N) 50 | r = b - A ( x ); 51 | p = r; 52 | rsold = r(:)' * r(:); 53 | 54 | for i = 1:N 55 | Ap = A ( p ); 56 | alpha = rsold / (p(:)' * Ap(:)); 57 | x = x + alpha * p; 58 | r = r - alpha * Ap; 59 | rsnew = r(:)' * r(:); 60 | if sqrt(rsnew) < 1e-10 61 | break; 62 | end 63 | p = r + (rsnew / rsold) * p; 64 | rsold = rsnew; 65 | end 66 | end 67 | ``` 68 | 69 | 70 | --- 71 | 72 | ## Example 73 | ### Problem definition 74 | In X-ray computed tomography (CT) system, radiation exposure is critical limitation. To reduce the radiation exposure, X-ray CT system uses a low-dose X-ray source. The low-dose X-ray source generate severe poison noise when X-ray photon are measured at X-ray detector, then a reconstruction image using low-dose measurement is too noisy to diagnosis diseases by doctor. Below image shows (a) full-dose image and (b) low-dose image, respectively. 75 | 76 | ![alt text](./img/low_dose_image.png "low dose image") 77 | 78 | To reduce the noise, objective function with total variation (TV) regularization can be formulated as follows: 79 | 80 | $$L(\textrm{x}) = \frac{1}{2} || \textrm{y} - A\textrm{x} ||_2^2 + \frac{\lambda}{2} ( ||D_x(\textrm{x})||_2^2 + ||D_y(\textrm{x})||_2^2 ),$$ 81 | 82 | where $\textrm{y}$ is measurement and $\textrm{x}$ defines reconstruction image (denoised image). $A$ is system operator (in this case, it is defined as CT system operator, called by **radon transform**). $D_x$ and $D_y$ are differential operators along x-axis and y-axis, respectively. 83 | 84 | In above equation, since each terms is quadratic function, an optimal point of $\textrm{x}$ is $\frac{d}{d\textrm{x}}L(x)=0$: 85 | 86 | $$-A^T (\textrm{y} - A\textrm{x})+ \lambda( D_x^T D_x(\textrm{x}) + D_y^T D_y(\textrm{x})) = 0,$$ 87 | 88 | $$A^TA(\textrm{x}) + \lambda( D_x^T D_x(\textrm{x}) + D_y^T D_y(\textrm{x})) = A^T\textrm{y},$$ 89 | 90 | $$[A^TA + \lambda( D_x^T D_x + D_y^T D_y)](\textrm{x}) = A^T\textrm{y}.$$ 91 | 92 | To match the CG formula, $[A^TA + \lambda( D_x^T D_x + D_y^T D_y)]$ is defined as $A_{cg}$ and $A^T\textrm{y} = b$, then 93 | 94 | $$\therefore A_{cg}(\textrm{x}) = b.$$ 95 | 96 | Now, above equation form $A_{cg}(\textrm{x}) = b$ is exactly matched with CG equation form $A(x)=b$. Using above reordered formula, optimal point $\textrm{x}^*$ of $L(\textrm{x})$ can be found. 97 | 98 | ### Results 99 | ![alt text](./img/reconstructed_image.png "Reconstructed by CG method") 100 | -------------------------------------------------------------------------------- /README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanyoseob/matlab-CG/1572b0a6b80edd0418a4f0327e0f3aaad7282fa8/README.pdf -------------------------------------------------------------------------------- /XCAT512.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanyoseob/matlab-CG/1572b0a6b80edd0418a4f0327e0f3aaad7282fa8/XCAT512.mat -------------------------------------------------------------------------------- /demo_CG_for_lowdose_ct.m: -------------------------------------------------------------------------------- 1 | %% REFERENCE 2 | % https://en.wikipedia.org/wiki/Conjugate_gradient_method 3 | 4 | %% COST FUNCTION 5 | % x^* = argmin_x { 1/2 * || A(X) - Y ||_2^2 + lambda/2 * ( || D_x(X) ||_2^2 + || D_y(X) ||_2^2 ) } 6 | 7 | %% 8 | clear ; 9 | close all; 10 | home; 11 | 12 | %% GPU Processing 13 | % If there is GPU device on your board, 14 | % then isgpu is true. Otherwise, it is false. 15 | isgpu = true; 16 | isfig = true; 17 | 18 | %% SYSTEM SETTING 19 | N = 512; 20 | ANG = 180; 21 | VIEW = 360; 22 | THETA = linspace(0, ANG, VIEW + 1); THETA(end) = []; 23 | 24 | A = @(x) radon(x, THETA); 25 | AT = @(y) iradon(y, THETA, 'none', N)/(pi/(2*length(THETA))); 26 | AINV = @(y) iradon(y, THETA, N); 27 | 28 | %% DATA GENERATION 29 | load('XCAT512.mat'); 30 | x = imresize(double(XCAT512), [N, N]); 31 | p = A(x); 32 | x_full = AINV(p); 33 | 34 | %% LOW-DOSE SINOGRAM GENERATION 35 | i0 = 5e4; 36 | pn = exp(-p); 37 | pn = i0.*pn; 38 | pn = poissrnd(pn); 39 | pn = max(-log(max(pn,1)./i0),0); 40 | 41 | y = pn; 42 | 43 | %% CONJUGATE GRADIENT METHOD (CG) INITIALIZATION 44 | x_low = AINV(y); 45 | LAMBDA = 3e2; 46 | Acg = @(x) (AT(A(x)) + LAMBDA*(Dxt(Dx(x)) + Dyt(Dy(x)))); 47 | 48 | b0 = AT(y); 49 | x0 = zeros(N); 50 | 51 | niter = 5e1; 52 | 53 | L2 = @(x) power(norm(x, 'fro'), 2); 54 | COST.equation = '1/2 * || A(X) - Y ||_2^2 + lambda/2 * ( || D_x(X) ||_2^2 + || D_y(X) ||_2^2 )'; 55 | COST.function = @(x) 1/2 * L2(A(x) - y) + LAMBDA/2 * (L2(Dx(x)) + L2(Dy(x))); 56 | 57 | %% RUN CONJUGATE GRADIENT METHOD (CG) 58 | if isgpu 59 | b0 = gpuArray(b0); 60 | x0 = gpuArray(x0); 61 | end 62 | 63 | [x_cg, obj] = CG(Acg, b0, x0, niter, COST, isfig); 64 | 65 | %% CALCUATE QUANTIFICATION FACTOR 66 | x_low = max(x_low, 0); 67 | x_cg = max(x_cg, 0); 68 | nor = max(x(:)); 69 | 70 | mse_x_low = immse(x_low./nor, x./nor); 71 | mse_x_cg = immse(x_cg./nor, x./nor); 72 | 73 | psnr_x_low = psnr(x_low./nor, x./nor); 74 | psnr_x_cg = psnr(x_cg./nor, x./nor); 75 | 76 | ssim_x_low = ssim(x_low./nor, x./nor); 77 | ssim_x_cg = ssim(x_cg./nor, x./nor); 78 | 79 | %% DISPLAY 80 | wndImg = [0, 0.03]; 81 | 82 | figure('name', 'Conjugate Gradient (CG) Method'); 83 | colormap(gray(256)); 84 | 85 | suptitle('Conjugate Gradient (CG) Method'); 86 | subplot(231); imagesc(x, wndImg); axis image off; title('(a) ground truth'); 87 | subplot(232); imagesc(x_full, wndImg); axis image off; title(['(b) full-dose_{FBP, view : ', num2str(VIEW) '}']); 88 | subplot(234); imagesc(x_low, wndImg); axis image off; title({['(c) low-dose_{FBP, view : ', num2str(VIEW) '}'], ['MSE : ' num2str(mse_x_low, '%.4e')], ['PSNR : ' num2str(psnr_x_low, '%.4f')], ['SSIM : ' num2str(ssim_x_low, '%.4f')]}); 89 | subplot(235); imagesc(x_cg, wndImg); axis image off; title({['(d) recon_{CG}'], ['MSE : ' num2str(mse_x_cg, '%.4e')], ['PSNR : ' num2str(psnr_x_cg, '%.4f')], ['SSIM : ' num2str(ssim_x_cg, '%.4f')]}); 90 | 91 | subplot(2,3,[3,6]); semilogy(obj, '*-'); title(COST.equation); xlabel('# of iteration'); ylabel('Objective'); 92 | xlim([1, niter]); grid on; grid minor; 93 | 94 | -------------------------------------------------------------------------------- /img/low_dose_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanyoseob/matlab-CG/1572b0a6b80edd0418a4f0327e0f3aaad7282fa8/img/low_dose_image.png -------------------------------------------------------------------------------- /img/reconstructed_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanyoseob/matlab-CG/1572b0a6b80edd0418a4f0327e0f3aaad7282fa8/img/reconstructed_image.png --------------------------------------------------------------------------------