Sei sulla pagina 1di 12

Image Processing Using SPECT Analysis

Abstract
This paper investigates the reconstruction of Single-Photon Electron Computed Tomography (SPECT) data from nuclear medicine.
We used a technique known as Filtered Back Projection, and achieved excellent results reconstructing a number of phantom images as
well as actual data obtained from M.D. Anderson in Houston. We have concluded that Filtered Back Projection is an extremely
effective technique for reconstruction. Future investigation in this field should include further study of filter optimizations as well as
other reconstruction techniques.
Introduction to SPECT Image Processing

Our project is based on data collected using Single-Photon Emission Computed Tomography or what the medical world refers to as
SPECT. This technology is used in nuclear medicine where the patient is injected with a radio pharmaceutical (a harmless tracer
chemical of some sort) which will emit gamma rays. The radioactivity is collected by an instrument called a gamma camera.

The gamma camera is made up two massive cameras opposite each other which rotate around a center axis 180 degrees. Each one is
lead-encased and weighs about 500 pounds. The camera has three basic layers - the collimator (which only allows the gamma rays
which are perpendicular to the plane of the camera to enter), the crystal, and the detectors. The collimation of the rays facilitates the
reconstruction since we will be dealing with data that comes in only perpendicularly. At each angle of projection, the data will be back
projected only in one direction.

When the Gamma Camera rotates around the supine body, it stops at interval angles to collect data. Since it has two heads, it needs to
only rotate 180 degrees to collect data around the entire body. The collected data is planar. Each of the cameras collects a matrix of
values which correspond to the number of gamma COUNTS detected in that one direction at the one angle.

There are some errors due to the characteristics of the camera and the procedure of data acquisition such as Center of Rotation and
Attenuation. To simplify our research, we have saved these corrections for further developments.

Corrections for the Gamma Camera


Center of Rotation

Ideally as the camera rotates around 360 degrees, we would like the center of rotation to always project into the same hole in the
collimator. We would expect also that the opposite cameras would be getting mirror images of each other. Unfortunately, due to the
weight of the cameras, the mechanics of the rotating gears, and every day wear and tear on the equipment, it is hard to get perfect
results. Misalignments cause blurry reconstructed images.

Attenuation

Photons exponentially attenuate making acquisition of accurate tracer data difficult. Since the radiation from the parts of the body
farthest away from the camera degrades before it reaches the detectors, this also distorts the data.

There are many other errors which come into play in using a gamma camera. However, for our purposes, correcting for these errors in
the few real data samples we acquired was unnecessary. We are primarily concerned with understanding the reconstruction of images.

Applications in the Real World

SPECT is used to treat cancer patients because using the slicing methods, we can remove any interference from the surrounding area
and detect disfunctionality of organs pretty easily. The radioactive chemicals will distribute through the body. This distribution can be
traced and compared to that of a normal healthy body. Because this method is so precise, doctors can detect abnormalities in the early
stages of disease development when it is more curable.

File Decode

For our reconstruction, actual tomographic data from a gamma camera was obtained. The images were of a standard phantom, which
in our case, was of a cylinder filled with hot and cold rods. This data was obtained courtesy of Dr. Bud Wendt, from the M.D.
Anderson Center in Houston, TX.
The data came in Interfile 3.3 format, which is a standard data format for used in Nuclear Medicine. It consists of two files: a
descriptive ASCII header file, and a purely binary data file. The header gives important details about the images in the data file; for
example, who the patient was, what imaging machinery was used, and the sizes and number of images. The data file consists of raster
images, scanning from left to right and top to bottom. For more information, the details of the Interfile standard can be found here.

The data file consisted of 180 128x128 pixel images, each being a projection of the phantom dummy at a different angle. The
projections went completely around the dummy, as one was taken for every two degrees of rotation.

The above image is one of the projections of the phantom, this one being from directly over the top. The axis of the gamma camera
runs from left to right, while the camera spins from top to bottom. Note that the camera takes a two-dimensional image at every angle;
with this information, we want to reconstruct a two-dimensional slice through the dummy, perpendicular to the projection planes.

For us to calculate the tomographic slices, we needed to take a column from each projection and group them all together. The
following sinogram is a collection of all the 64th columns from all of the projections; the columns are then rotated to be horizontal.

Each one of the rows is a vector from one of the projections; this vector runs perpendicular to the axis of the phantom body.

To create the sinogram, represented in MATLAB as a 128x180 element matrix, some MATLAB code was written. The function can
be found here.

% decodefile.m
% Decodes the Interfile format into a [128, 180] matrix. Each of the 180 columns is a different projection vector.
% y = decodefile(file, n)
%
%where n is the row of the image you want and file is the string of the file name.
%
% by Stephen K. Gee
%
function y = decodefile(file, n)
fid = fopen(file); % Opens File
r = 128*2*n;

for i = 0:179
fseek(fid, r+i*128*128*2, -1); % Sets to proper row of image
x = fread(fid, 128, 'uint16'); % reads image data
y(i+1,:) = x';
end

Image Projections and the Radon Transform


Image Projections and the Radon Transform

The basic problem of tomography is given a set of 1-D projections and the angles at which these projections were taken, how do we
reconstruct the 2-D image from which these projections were taken? The first thing we did was to look at the nature of the
projections.

Fig(1) -

Define g(phi,s) as a 1-D projection at an angle . g(phi,s) is the line integral of the image intensity, f(x,y), along a line l that is
distance s from the origin and at angle phi off the x-axis.

Eqn(1)

All points on this line satisfy the equation:

x*sin(phi) - y*cos(phi) = s

Therefore, the projection function g(phi,s) can be rewritten as

Eqn(2)
The collection of these g(phi,s) at all phi is called the Radon Transform of image f(x,y).

To be able to study different reconstruction techniques, we first needed to write a (MATLAB) program that took projections of a
known image. Having the original image along with the projections gives us some idea of how well our algorithm performs. The
projection code is pretty simple. Basically, we take the image (which is just a matrix of intensities in MATLAB), rotate it, and sum
up the intensities. In MATLAB this is easily accomplished with the 'imrotate' and 'sum' commands. First, we zero pad the image so
we don't lose anything when we rotate (the images are rectangular so the distance across the diagonal is longer than the distance on a
side). Then we rotate the image 90-phi degrees (so that the projection is lined up in the columns) using the 'imrotate' command, and
finally summed up the columns using the 'sum' command.
The performance of this program was marginal. We did not bother optimizing the code for MATLAB because our main focus was
reconstructing the images, not taking projections of them.
The Projection Code
% projections.m

%% This MATLAB function takes an image matrix and vector of angles and then finds the 1D projection (Radon transform) at each
% of the angles. It returns a matrix whose columns are the projections at each angle.
%%
%% Written by : Justin K. Romberg

function PR = projections(IMG, THETA)

% pad the image with zeros so we don't lose anything when we rotate.
[iLength, iWidth] = size(IMG);
iDiag = sqrt(iLength^2 + iWidth^2);
LengthPad = ceil(iDiag - iLength) + 2;
WidthPad = ceil(iDiag - iWidth) + 2;
padIMG = zeros(iLength+LengthPad, iWidth+WidthPad);
padIMG(ceil(LengthPad/2):(ceil(LengthPad/2)+iLength-1), ...
ceil(WidthPad/2):(ceil(WidthPad/2)+iWidth-1)) = IMG;

% loop over the number of angles, rotate 90-theta (because we can easily sum if we look at stuff from the top), and then add up. Don't
% perform any interpolation on the rotation.
n = length(THETA);
PR = zeros(size(padIMG,2), n);
for i = 1:n
tic
tmpimg = imrotate(padIMG, 90-THETA(i), 'bilinear', 'crop');
PR(:,i) = (sum(tmpimg))';
THETA(i)
toc
end

Filtered Backprojection and the Fourier Slice Theorem

In order to reconstruct the images, we used what is known as the Fourier Slice Theorem. The Slice Theorem tells us that the 1D
Fourier Transform of the projection function g(phi,s) is equal to the 2D Fourier Transform of the image evaluated on the line that the
projection was taken on (the line that g(phi,0) was calculated from). So now that we know what the 2D Fourier Transform of the
image looks like (or at least what it looks like on certain lines and then interpolate), we can simply take the 2D inverse Fourier
Transform and have our original image.

Fig. 2 -

We can show the Fourier Slice Theorem in the following way:


The 1D Fourier Transform of g is given by:

Eqn(3)

Now, we subsitute our expression for g(phi,s) (Eqn. 2) into the expression above to get

Eqn(4)

We can use the sifting property of the Dirac delta function to simplify to

Eqn(5)

Now, if we recall the definition of the 2D Fourier Transform of f

Eqn(6)

we can see that that Eqn 5. is just F(u,v) evaluated at u = w*sin(phi) and v = -w*cos(phi), which is the line that the projection g(phi,s)
was taken on!

Now that we have shown the Fourier Slice Theorem, we can continue with the math to gain further insight. First, recall the definition
for the 2D inverse Fourier Transform

Eqn(7)

Now, we make a change of variable from rectangular to polar coordinates and replace F(phi,w) with G(phi,w) we get

Eqn(8)

where |w| is the determinant of the Jacobian of the change of variable from rectangular to polar coordinates. We now have a
relationship between the projection functions and the image we are trying to reconstruct, so we can easily write a program to do the
reconstruction.

Notice that we have to multiply our projections by |w| in the Fourier domain. This product

Eqn(9)
is called the filtered back projection at angle phi. If we look at Fig. 2, we can see that we have a lot of information at low frequencies
(near the origin), and not as much at high frequencies. The |w|, which is a ramp filter, compensates for this. Below, we show our
phantom object reconstructed from 1, 4, 8, 15, and 60 filtered back projections.
With only one back projection, not much information about the original image is revealed.

With 4 back projections, we can see some of the basic features start to emerge. The two squares on the left side start to come in, and
the main ellipse looks like a diamond.

At 8 back projections, our image is finally starting to take shape. We can see the squares and the circles well, and we can make out the
basic shape of the main ellipse.
With 15 back projections, we can see the bounds of the main ellipse very well, and the squares and cirlces are well defined. The lines
in the center of the ellipse appear as blurry triangles. Also, we have a lot of undesired residuals in the back ground (outside the main
ellipse).

At 60 back projections, our reconstructed image looks very nice. We still have some patterns outside the ellipse, and there are streaks
from the edge of the squares all the way out to the edge of the image. These appear because the edge of the square is such a sharp
transition at 0 and 90 degrees, that when we pass the projections through the ramp filter, there are sharp spikes in the filtered
projections. These never quite seem to get smoothed out.

The MATLAB code for the filtered back projections worked very nicely. The basic algorithm we used for filtered back projections
was:

f(x,y) is the image we are trying to recontruct, q(phi,s) is the filtered back projection at angle phi.

Initialize f(x,y)
For each p do
For each (x,y) do

Find the contributing spot in the filtered back projection


that corresponds to (x,y) at angle phi, in other words
s = xsin(phi) - ycos(phi)
f(x,y) = f(x,y) + q(phi,s);
end
end

Since we used MATLAB to do all the image processing, we were able to vectorize the computations, and cut out the entire inner loop
(which is really 2 loops, one for x and one for y). The run times were blazingly fast, our algorithm took about .2 seconds per back
projection on our phantom when running on a SPARC 5.

The Back Projection Code


% backproject3.m
% This is a MATLAB function that takes filtered back projections without using the 'imrotate' command. Here, we try % to cut out all
the loops.
% PR is a matrix whose columns are the projections at each angle.
% THETA is a row vector of the angles of the respective projections.
%
% Written by : Justin K. Romberg

function [BPI,M] = backproject3(PR, THETA)

% figure out how big our picture is going to be.


n = size(PR,1);
sideSize = n;

% filter the projections


filtPR = projfilter(PR);
%filtPR = filterplus(PR);
%filtPR = PR;

% convert THETA to radians


th = (pi/180)*THETA;

% set up the image


m = length(THETA);
BPI = zeros(sideSize,sideSize);

% find the middle index of the projections


midindex = (n+1)/2;

% set up x and y matrices


x = 1:sideSize;
y = 1:sideSize;
[X,Y] = meshgrid(x,y);
xpr = X - (sideSize+1)/2;
ypr = Y - (sideSize+1)/2;

% loop over each projection


%figure
%colormap(jet)
%M = moviein(m);
for i = 1:m
tic
disp(['On angle ', num2str(THETA(i))]);

% figure out which projections to add to which spots


filtIndex = round(midindex + xpr*sin(th(i)) - ypr*cos(th(i)));

% if we are "in bounds" then add the point


BPIa = zeros(sideSize,sideSize);
spota = find((filtIndex > 0) & (filtIndex <= n));
newfiltIndex = filtIndex(spota);
BPIa(spota) = filtPR(newfiltIndex(:),i);
%keyboard

BPI = BPI + BPIa;

toc

%imagesc(BPI)
%M(:,i) = getframe;
%figure(2)
%plot(filtPR(:,i));
%keyboard
end

BPI = BPI./m;

Backprojection Filters
Basic Filtering
The backprojection method has several drawbacks: First, it produces an image which has a high density in the center. This is due to
the fact that many different images are being overlapped in this area. Secondly, the resulting image is severely blurred, as shown in
the figures below. The first figure shows a phantom before taking projections. The second figure shows the unfiltered backprojection
reconstruction of the phantom. This effect comes from the overlapping of the Fourier-transformed images around the low frequency
region. To control these effects, it is clear that a filter is needed during reconstruction of the projections.

By means of a precise mathematical treatment, it can be shown that to reproduce the image exactly, it is necessary to use a ramp filter.
In the frequency domain, this filter is just |w|. The corresponding inverse Fourier transform
is a wavelet pattern.
The figures below illustrate the effect of using a simple ramp filter. The first figure shows
the normalized magnitude response of the ramp filter and the second figure shows the
reconstructed phantom using the filter.

This filter has the effect of filtering out low frequencies and passing high frequencies, with a linear behavior in between. Thus with
this filter, contrasting features (high-frequencies) are accentuated, while blurring (low-freqencies) is minimized.

Noise Filtering
The Ideal Ramp Filter works very well for reconstructing projections, but has the undesirable effect of passing and magnifying
extraneous noise from projection data. This is an important point for our application, because the projections are indeed subject to
noise.
The figures below show the reconstruction from projections of a simple square, using the simple ramp filter during reconstruction.
The first one shows the reconstruction from noisefree projections (taken at 60 projections), and the second shows the resulting
reconstruction when 1% random noise was added to the projections of the square.

For this reason, we experimented with several modified filters, reducing the high-frequency cutoffs to a different degree in each case,
so as to filter out the noise. Unfortunately, these filters had the unwanted effect of smoothing out definitions.
The following series of figures illustrates this tradeoff. The figures on the left show the normalized magnitude response of the filter
used in each case, and the figures on the right show the resulting reconstruction using that filter.
It was found that most of the experimental filters worked reasonably well for images that had a relatively less complex frequency
distribution. For images containing a high degree of complexity, the best tradeoff between noise removal and feature preservation did
not improve the image much.
The following series of figures illustrates this problem. The first figure below shows the original phantom used, and the second figure
shows its reconstruction from noiseless projections using the simple ramp filter.

The figures that follow show the series of changes experienced by the reconstructed image from noisy projections, as the filter
function is varied. The projections of the image above were exposed to 0.1% random noise.The figures on the left show the
normalized magnitude response of the filter used in each case, and the figures on the right show the resulting reconstruction using that
filter.
As can be seen from the above figures, as the high-frequency cutoff is decreased, the image becomes smoother and the edges become
less prominent. A perfect filter is thus quite difficult to construct without prior knowledge of the type of noise that plagues the
projection data.
The Matlab code for the sinc filters used above can be found here.
SINC Filter Code
function g = filtersinc(PR);

% filtersinc.m
%
% Written by Waqas Akram
%
% "a": This parameter varies the filter magnitude response.
% When "a" is very small (a<<1), the response approximates |w|
% As "a" is increased, the filter response starts to
% roll off at high frequencies.
a = 1;

[Length, Count] = size(PR);


w = [-pi:(2*pi)/Length:pi-(2*pi)/Length];

rn1 = abs(2/a*sin(a.*w./2));
rn2 = sin(a.*w./2);
rd = (a*w)./2;
r = rn1*(rn2/rd)^2;

f = fftshift(r);
for i = 1:Count
IMG = fft(PR(:,i));
fimg = IMG.*f';
g(:,i) = ifft(fimg);
end
g = real(g);

Conclusions

Although we were not ultimately able to receive medical patient data from the hospital, we considered this project to be highly
successful. We did in-depth studies of backprojection methodologies and were able to implement them on various images with
satisfying results. Considering the brevity of this study, we were very pleased with the outcome.

Possible future elaborations of this project include:


1. Further study of filter optimizations.
2. Correction algorithms for off-center rotation and attenuation.

We, the Five Fearless Thinkers, found this project to be both entertaining and rewarding. We would like to thank the following people:
Dr. Bud Wendt, for his invaluable assistance in background and theory. Dr. Richard Baraniuk, for his generous help during our
occasional roadblocks. Finally, thank you to the 1996 Rice University ELEC431 class for your attention during our presentation.

Potrebbero piacerti anche