Matlab Code

Applying the Blur:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function v = psf(sigma,x,y)
% returns the value of the point spread function
% We're using a Gaussian PSF (truncated far away from
% its center -- the origin).

if x >= -8 & x <= 8 & y >= -8 & y <= 8
   v = exp(-sigma*(x.^2+y.^2));
else
   v = 0;
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function g = applyGaussianPSF(sigma, f, x)
% Returns the blurred graph of f
% if x = 0 the mesh plot is generated,
% otherwise it is not graphed.
% sigma determines how much the light is spread
% (How bad the blur is.)

% Get size
[m n] = size(f);

% create Toeplitz blocks
for i = -8:8
   for k = 1:n
      c(k) = psf(sigma, i, k-1);
      r(k) = psf(sigma, i, 1-k);
   end;
   
   block(i+9,1:n,1:n) = toeplitz(c,r);
end;

% apply the convolution product row by row
for i = 1:m
   g(i,1:n) = zeros(1,n);

   % apply convolution product
   % to the graph on row i
   for j = -8:8
      if i-j >= 1 & i-j <= m
         b(:,:) = block(j+9,:,:);
         g(i,1:n) = g(i,1:n) + f(i-j,1:n) * b;
      end;
   end;
end;

if x == 0, mesh(g); end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Solving for the Image:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function n = inner_product(x,y)
% turn x and y into columns by transposing each row
% into a column and concatenating together.
% then find regular inner product
% (x and y are sz x ?? matrices)

sz = size(x,1);

n = 0;
for i = 1:sz
   n = n + x(i,:) * y(i,:)' ;
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [g, error, niter, flag] = CGmethod(sigma, g, f, maxit, tol)
% Conjugate Gradient method for solving linear systems.
%
% sigma is a parameter for the Gaussian psf
%
% We are solving "Ag = f":
% g as input is the initial guess at a solution and then
% g as output is the solution to the system.
% f is the blurred image.
%
% maxit is the maximum number of iterations to attempt
% niter is the number of iterations actually preformed
% error is the difference between the exact answer and our answer
% tol is the allowable error
% flag is set to 1 if the function returns before error <= tol

flag = 0;
niter = 0;

% r is the residual (error).
r = f - applyGaussianPSF(sigma,g,1);

% Initial search direction.
d = r;

% norm of f (as a vector: turn rows into cols and concatenate)
norm_f = sqrt(inner_product(f,f));

if(norm_f == 0.0), norm_f = 1.0; end;

error = sqrt(inner_product(r,r)) / norm_f;

for niter = 1:maxit
   if(error < tol), return, end; % bail out if the error is small enough.
   
   % multiply our search direction by the blur matrix.
   Ad = applyGaussianPSF(sigma,d,1);
   
   % the square of the blur matrix norm of d. 
   inp_Ad_d = inner_product(Ad,d);
   
   % Step size (how far to move along the gradient direction).
   alpha = inner_product(r,d) / inp_Ad_d;
   
   % Improve the 
   g = g + alpha * d;
   
   % update the residual (error).
   r = f - applyGaussianPSF(sigma,g,1);
   
   % the conjugate factor to force our search directions
   % to be orthogonal (in some sense).
   beta = -inner_product(r,Ad) / inp_Ad_d;
   
   % New search direction.
   d = r + beta * d;
   
   % measure the relative error.
   error = sqrt(inner_product(r,r)) / norm_f;
   
end;

if(error > tol) flag = 1; end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Wrapper Functions for Demos:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function B = blur(pic, gry, flag)
% Blurs "pic" (a jpeg) and returns the blurred image.
% The image is converted to grayscale if gry = 1 and 
% the image is displayed if flag = 1.

% Load up the picture. A is a m by n matrix if grayscale
% and an m by n by 3 tensor if in color (think 3 matrices
% stacked on top of each other -- one each for RGB values.
A = loadImage(pic, gry, 0);

if gry == 0  % Color
    % Blur Red, Greens, and then Blues.
    B(:,:,1) = applyGaussianPSF(0.1, A(:,:,1), 1);
    B(:,:,2) = applyGaussianPSF(0.1, A(:,:,2), 1);
    B(:,:,3) = applyGaussianPSF(0.1, A(:,:,3), 1);
else % Grayscale
    B = applyGaussianPSF(0.1, A, 1);
end;

if flag == 1  % Display the image
    figure; 
    if gry == 1
        colormap(gray(256)); 
        
        % rescale to make image show up.
        x = max([max(max(B)),0.000001]);
        scaleB = (1/x)*B;
    else 
        % rescale to make image show up.
        x = max([max(max(max(B))),0.000001]);
        scaleB = (1/x)*B;
    end;
    %image(myImg);
    imshow(scaleB);
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function A = deblur(B, n, gry, flag)
% Deblurs the image stored in the matrix/tensor B 
% and returns the "unblurred" image.
% The image is considered to be grayscale if gry = 1 
% and the image is displayed if flag = 1.


% Our initial "guess" to feed into the CG method is the zero image.
A = zeros(size(B));

if gry == 0 % Color

    % Run the CG method on RGB values. 
    % Each call to the CG method is iterated n times.
    [A(:,:,1), error, niter, flag] = CGmethod(0.1, A(:,:,1), B(:,:,1), n, 0);
    [A(:,:,2), error, niter, flag] = CGmethod(0.1, A(:,:,2), B(:,:,2), n, 0);
    [A(:,:,3), error, niter, flag] = CGmethod(0.1, A(:,:,3), B(:,:,3), n, 0);
    
else % Grayscale

    % Each call to the CG method is iterated n times.
    [A, error, niter, flag] = CGmethod(0.1, A, B, n, 0);

end;


% Display image when flag is 1.
if flag == 1
    figure; 
    if gry == 1
        colormap(gray(256)); 
        
        % rescale to make image show up.
        x = max([max(max(A)),0.000001]);
        scaleA = (1/x)*A;
    else 
        % rescale to make image show up.
        x = max([max(max(max(A))),0.000001]);
        scaleA = (1/x)*A;
    end;
    %image(myImg);
    imshow(scaleA);
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function myImg = loadImage(pic, gry, flag)
% This function loads the file "pic" (should be a jpeg).
% If gry = 0, it's loaded as a color picture.
% If gry = 1, it's turned into a grayscale image.
% flag determines whether the image is displayed.
% flag = 0 not shown / flag = 1 shown

myImg = imread(pic);

if gry == 1 
    tmp = .2989*myImg(:,:,1) + .5870*myImg(:,:,2) + .1140*myImg(:,:,3);
    myImg = tmp;
end;

if flag == 1
    figure; 
    if gry == 1
            colormap(gray(256)); 
    end;
    %image(myImg);
    imshow(myImg);
end;

% convert to double so the image can be manipulated.
myImg = double(myImg);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function f = cityScape(x)
% Returns the graph of the skyline
% if x = 0 then mesh plot is generated,
% otherwise it is not graphed.

f = zeros(160,100);
%f = zeros(64);
f(21:44,20:30) = 1;
f(16:49,40:45) = 2;
f(11:55,50:55) = 3;
f(30:40,50:55) = 2.2;

if x == 0
    mesh(f); 
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function Z = GaussianPSF(sigma,x)
% Returns the n by n graph of the point spread function
% if x = 0 the mesh plot is generated, 
% otherwise, it is not graphed.
% sigma determines how much the light is spread.

[X,Y] = meshgrid(-8:8,-8:8);
Z = exp(-sigma*(X.^2+Y.^2));

if x == 0, mesh(-8:8,-8:8,Z); end;