Deblurring Images in Matlab using the Contragradient Method

An image can be thought of as an array filled with numbers. Grayscale images can be stored as \( m \times n \) matrices whose entries determine the shade of gray. Color images can be stored as \( m \times n \times 3 \) tensors (think 3 matrices stacked on top of each other). Each level keeps track of the shade of Red, Green, or Blue (RGB values).

To apply methods from linear algebra it is helpful to think of images as vectors (\(m \times 1\) arrays). To convert from a rectangular array to a matrix we simply rip out all of the columns and then stack them end to end.

\( \begin{vmatrix} 1 & 2 & 3 \\ 1 & 0 & 2 \end{vmatrix} \quad \Longrightarrow \quad \begin{array}{c} \begin{vmatrix} 1 \\ 1 \end{vmatrix} \\ \; \\ \begin{vmatrix} 2 \\ 0 \end{vmatrix} \\ \; \\ \begin{vmatrix} 3 \\ 2 \end{vmatrix} \end{array} \quad \Longrightarrow \quad \begin{vmatrix} 1 \\ 1 \\ 2 \\ 0 \\ 3 \\ 2 \end{vmatrix} \)

An image is blurring when the pixels making up the image are "smeared" and spread around. We spread out pixels using a point spread function (PSF). In particular we used a Gaussian PSF (sort of like a 3D bell curve).


[> GuassianPSF(0.1,0);

[> A = cityScape(0);

[> applyGaussianPSF(0.1, A, 0);

The PSF is applied to each pixel then these smears are added together. Since this is a "linear" process it amounts to multiplying our image vector by a matrix. So if \( x \) is our unblurred image and \( A \) is the matrix corresponding to the PSF blurring process, then the blurred image is \( Ax = b \).

Now given a blurred image \( b \) we "simply" need to solve the system \( Ax=b \) for \( x \). In linear algebra we learn to solve linear systems using "row reduction". It turns out that this won't work for us for sveral reasons.

Another difficulty standing in the way of recovering the orginal picture is When a picture is blurred some information from outside the picture frame will get smeared into the picture and some of the information from inside the picture will get smeared outside. There are several ways to deal with this using different "boundary conditions". While our group discussed several of these techniques, in the end we adopted "zero" boundary conditions (assuming everything is black outside our picture) for simplicity. This is the reason our blurring matrix has BTTB structure (Block Toeplitz - Toeplitz Block).

Our way around the first two difficulties (round-off error & large coefficient matrix) is to use an "iterative" method to solve the system. This type of method takes in a "guess" solution and then (hopefully) improves the guess. This improved guess is then fed back into the method to improve it yet again, etc. Iterative methods have the avantage that then don't require us to manipulate the coefficient matrix (\( A \)). In fact, in our code we don't ever construct the matrix \( A \) itself -- we instead have a function "applyGaussianPSF" which mimics the effect of multiplying by \( A \). This saves us from having to store the potentially millions or billions of entries of \( A \).

The particular interative method we chose is called the "Conjugate Gradient Method" (CG method). The CG method is based on a process of "sliding down hill". Consider the following complicated looking function:

\( f(x) = \frac{1}{2}x^T A x - x^T b \)

The graph of \( f \) is some sort of "hyper-surface". In Calculus III one learns about gradient vectors. The gradient of a function, \( \nabla f \), is a vector which points in the direction of maximal increase. The negative of the gradient then points in the direction of maximal decrease. It turns out that the gradient of \( f \) is

\( \nabla f = Ax-b \)

Therefore, \( \qquad \nabla f = 0 \qquad \Longleftrightarrow \qquad Ax-b = 0 \qquad \Longleftrightarrow \qquad Ax=b \)

Points where the gradient vector are zero are critical points. If we want to solve our system, we need to find a "minimum" for \( f \). We can do this by picking some point on our surface and then heading down hill. To get to the minimum as fast as possible we should head down hill along \( - \nabla f \) since that is the direction of maximal decrease. That is basically what the CG method does.





Our Matlab Code:

Applying the Blur:
psf.m
applyGaussianPSF.m

Restoring the Image:
inner_product.m
CGmethod.m

Functions for Demos:
blur.m
deblur.m
loadImage.m
cityScape.m
GaussianPSF.m