0% found this document useful (0 votes)
11 views13 pages

L19 CTReconstruction

Uploaded by

Srushti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views13 pages

L19 CTReconstruction

Uploaded by

Srushti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

CT Image Reconstruction from a Sinogram

In this notebook, we will reconstruct a CT image from its sinogram using the Radon Transform
and Filtered Backprojection algorithm. The notebook uses the following steps:

1. Import required libraries


2. Create a phantom image (Shepp-Logan Phantom)
3. Generate a sinogram using the Radon transform
4. Reconstruct the image using Filtered Backprojection
5. Compare the original and reconstructed images
# Importing the necessary libraries
import numpy as np # For numerical
operations
import matplotlib.pyplot as plt # For plotting images
and graphs
from skimage.transform import iradon, radon # For Radon and inverse
Radon (FBP) transforms
from skimage.data import shepp_logan_phantom # To generate a test
phantom image (Shepp-Logan Phantom)

Details of the Libraries Used Above


1. NumPy (np): A powerful library for numerical computations in Python. We'll use it for
matrix manipulations.
2. Matplotlib (plt): A plotting library for Python. We will use it to visualize images,
sinograms, and reconstructed outputs.
3. Scikit-Image (skimage.transform): A collection of algorithms for image processing.
The radon function generates a sinogram, and the iradon function performs the
inverse Radon transform (Filtered Backprojection) for reconstruction.
4. Shepp-Logan Phantom: A pre-built test image, resembling a CT cross-section of the
human head, commonly used for image reconstruction.

In the next step, we will generate a phantom image (Shepp-Logan Phantom) to simulate a test
object for our CT scan.

# Create the Shepp-Logan Phantom image

image = shepp_logan_phantom()

# Function to generate a 2D synthetic image known as the Shepp-Logan


phantom
# Commonly used in medical imaging, particularly for testing
reconstruction algorithms like CT
# The function shepp_logan_phantom() comes from the skimage.data
module in the scikit-image library.
# This function creates a 256x256 grayscale image representing a
simplified model of a human head.

# Padding the image to make sure it has appropriate dimensions for


reconstruction
image = np.pad(image, ((0, 0), (0, 0)), mode='constant') #
adding a constant value of zero in the padding layer

# Display the original phantom image


plt.figure(figsize=(6, 6)) # Create a new figure for the
plot with a size of 6x6 inches.
plt.imshow(image, cmap='gray') # cmap = 'gray' Specifies that
the image should be displayed in grayscale. The cmap (colormap) option
is used to map pixel intensity values to colors. In this case, 'gray'
maps the intensity values directly to shades of gray (0 = black, 1 =
white).
plt.title('Original Phantom Image')
plt.axis('off')
plt.show()
Explanation of the Phantom and Padding
1. Phantom Image: The shepp_logan_phantom() function generates a 2D image of a
human head's cross-section, which is a typical dataset used in CT reconstruction
research. The image is ideal for testing because it contains well-defined structures.
2. Padding: We pad the image with zeros to ensure that it has the appropriate dimensions,
especially for reconstruction purposes. Here, padding is used to maintain a square image
if needed for testing.

Next, we will generate the sinogram (a series of projections from different angles) using the
Radon transform.

# Generate a range of angles (0 to 180 degrees) for projection


theta = np.linspace(0., 180., max(image.shape), endpoint=False)

# np.linspace generates an array of evenly spaced values between two


endpoints.
# max(image.shape): This specifies the number of projections (i.e.,
how many angles will be used).
# The max(image.shape) ensures that the number of projections is
proportional to the size of the image

# Compute the sinogram using the Radon transform


sinogram = radon(image, theta=theta)

# radon() This is the Radon transform function from the


skimage.transform module.
#The Radon transform is used to compute projections of the image at
various angles.

# Display the sinogram


plt.figure(figsize=(8, 8))
plt.imshow(sinogram, cmap='gray', extent=(0, 180, 0,
sinogram.shape[0]), aspect='auto')
plt.title('Sinogram (Radon Transform)')
plt.xlabel('Projection angle (degrees)')
plt.ylabel('Projection position (pixels)')
plt.show()
Explanation of Radon Transform and Sinogram
1. Radon Transform: The Radon transform converts the 2D image into a series of 1D
projections (sinogram) by simulating how X-rays pass through an object at different
angles.
2. Angles (theta): We define theta as a range of angles between 0 and 180 degrees. This
simulates rotating the object and capturing the projection at different angles.

In the next step, we will reconstruct the image from this sinogram using the Filtered
Backprojection (FBP) algorithm.
Radon Transform and Inverse Radon Transform
Radon Transform:
The Radon Transform is a fundamental tool in medical imaging and computed tomography (CT)
that represents the projection of an image along various directions. For a 2D image f ( x , y ), the
Radon transform R f ( θ , t ) is defined as the integral of the image intensity along a line at angle θ
and distance t from the origin.

The formula for the Radon transform is:



R f ( θ , t )=∫ f ( x ′ , y ′ ) d s
−∞

Where:

• x ′ and y ′ are the coordinates rotated by an angle θ , which are given by:
x ′=x cos ( θ ) + y sin ( θ )
y ′=− x sin ( θ )+ y cos ( θ )
• t is the perpendicular distance from the origin to the projection line.
In essence, the Radon transform sums the image values along lines at different angles,
producing what is called a sinogram (a 2D array of projections).

Inverse Radon Transform:


The Inverse Radon Transform is the process of reconstructing an image from its projections.
This is the key mathematical operation behind image reconstruction in CT. One common
method of performing the inverse Radon transform is Filtered Back Projection (FBP), where the
projection data is first filtered and then "smeared" back along the corresponding lines to recover
the original image.

The formula for the inverse Radon transform can be written as:
π ∞
f ( x , y )=∫ ∫ R f ( θ , t )|t ) d t d θ
0 −∞

This integral reconstructs the original image from the Radon-transformed data, with
appropriate filtering applied to reduce artifacts aSummary Pointshe image quality.

Key Concepts:
• The Radon transform produces projections of an image at various angles.
• The Inverse Radon transform is used to reconstruct the original image from these
projections.
• Filtered Back Projection (FBP) is a widely used algorithm for reconstructing images
from Radon transform data in CT imaging.
Inverse Radon Transform and the Filtered Back Projection
(FBP) Algorithm
The iradon function from the skimage.transform module in Python implements the
Filtered Back Projection (FBP) algorithm to reconstruct an image from its sinogram. The FBP
algorithm is widely used in medical imaging, especially for computed tomography (CT)
reconstruction. The key idea behind FBP is to reconstruct the original image by reversing the
Radon transform through backprojection, combined with a filtering process to reduce blurring
and improve accuracy.

Steps of the FBP Algorithm in iradon:


1. Radon Transform Input (Sinogram):
– The iradon function takes a sinogram as input, which is the result of applying
the Radon transform to the original image. The sinogram contains projection data
for various angles.
2. Ramp Filter Application:
– Before backprojection, the algorithm applies a ramp filter (or another chosen
filter) in the frequency domain to the sinogram. This filtering step compensates
for the fact that backprojection alone tends to blur the image.
– The ramp filter enhances the higher frequencies in the projection data,
countering the over-smoothing effect of the backprojection.
The filtering is typically performed as follows:
– Perform a Fourier transform on each projection.
– Multiply the Fourier transform by the ramp filter (or other specified filter).
– Perform an inverse Fourier transform to bring the data back to the spatial
domain.
3. Backprojection:
– The filtered projections are then "smeared" back across the image space in their
respective directions (angles) to form the reconstructed image.
– For each projection, the values are distributed (or backprojected) along the lines
at the corresponding projection angle.
– The contribution of each backprojected projection is summed, pixel by pixel, over
all projection angles.
Mathematically, this step is represented by:
π
f ( x , y )=∫ Filtered Projections ( θ , t ) d θ
0

Here, the backprojection process distributes the filtered projection data back over
the image grid.

4. Reconstruction Output:
– After summing the contributions from all projection angles, the resulting image is
the reconstructed version of the original object.
– The result of this process is an approximation of the original image that was
projected into the sinogram.

Internal Steps of iradon in Summary:


1. Input: Sinogram (Radon transform data).
2. Filtering: Apply a ramp filter (or other filter) in the frequency domain to each projection.
3. Backprojection: Backproject the filtered projections along the corresponding angles.
4. Summation: Sum the contributions from all angles to reconstruct the image.

By combining filtering and backprojection, the FBP algorithm produces an accurate


reconstruction of the original image, minimizing artifacts and improving the sharpness of edges.

Commonly Used Filters:


• Ramp Filter (Default): This filter enhances the high-frequency components, reducing
blurring in the backprojected image.
• Other filters like Hann, Hamming, or Shepp-Logan can also be used, each with different
effects on the image's smoothness and sharpness.

In iradon, you can specify the filter using the filter_name parameter, and by default, it uses
the ramp filter.

# Perform the inverse Radon transform (Filtered Backprojection)


reconstruction_fbp = iradon(sinogram, theta=theta, filter_name='ramp')

# Display the reconstructed image


plt.figure(figsize=(6, 6))
plt.imshow(reconstruction_fbp, cmap='gray')
plt.title('Reconstructed Image (Filtered Backprojection)')
plt.axis('off')
plt.show()
Explanation of Filtered Backprojection (FBP)
1. Inverse Radon Transform (iradon): This function reconstructs the image from the
sinogram using the Filtered Backprojection algorithm.
2. filter_name='ramp': This parameter specifies the type of filter to be used during
reconstruction. The 'ramp' filter is the most commonly used for basic filtered
backprojection. You can also try 'shepp-logan', 'cosine', 'hamming', and 'hann'
to see different effects on image quality.
3. FBP Algorithm: It works by applying a filter to the projections and then backprojecting
them across the image plane to reconstruct the image.

In the next step, we will compare the original and reconstructed images to observe the
reconstruction quality.

# Plotting the original and reconstructed images side by side


fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

ax1.imshow(image, cmap='gray')
ax1.set_title('Original Image')
ax1.axis('off')
ax2.imshow(reconstruction_fbp, cmap='gray')
ax2.set_title('Reconstructed Image')
ax2.axis('off')

plt.show()

Comparison and Conclusion


1. Comparison: In this final comparison, we see the original Shepp-Logan Phantom on the
left and the reconstructed image on the right. The reconstruction is fairly accurate but
may contain artifacts, especially if we used fewer projection angles or different filters.
2. Experimentation: You can try varying the number of projection angles by modifying the
theta parameter, or try different filters (filter_name parameter) to observe changes
in the reconstruction. Fewer angles will lead to lower-quality reconstructions, while
different filters can affect the sharpness and smoothness of the reconstructed image.

Steps for Manual Filtered Back Projection (FBP)


Reconstruction
Step 1: Create the Shepp-Logan Phantom Image
• The Shepp-Logan phantom is a standard test image used in medical imaging to evaluate
image reconstruction algorithms.
• This phantom simulates the human head structure, and it's commonly used for testing
CT reconstruction techniques.

Step 2: Generate the Sinogram (Radon Transform)


• The sinogram is created by applying the Radon Transform to the image.
• The Radon transform projects the image at different angles (theta), simulating what a CT
scanner captures during the imaging process.
• The sinogram contains these projections at various angles, typically from 0 to 180
degrees.

Step 3: Apply the Ramp Filter in the Frequency Domain


• Before performing backprojection, the projections (sinogram) are filtered using a ramp
filter.
• The ramp filter compensates for the blurring that occurs during the backprojection
process and helps to recover high-frequency details.
• This is done by performing a Fourier transform on each projection, multiplying the
Fourier coefficients by the ramp filter, and then performing an inverse Fourier transform
to get the filtered projections back in the spatial domain.

Step 4: Perform Backprojection


• Backprojection is the process of reconstructing the image by "smearing" each filtered
projection back into the image space at the corresponding angle.
• For each projection:
a. The 1D projection data is expanded into a 2D projection (using np.tile).
b. The 2D projection is then rotated to the appropriate angle using the rotate
function from scipy.ndimage.
c. The rotated projection is then added (accumulated) into the reconstructed image.

Step 5: Visualize the Results


• Finally, display the original Shepp-Logan phantom image and the reconstructed image
side by side for comparison.
• The reconstructed image should approximate the original image closely if the Filtered
Back Projection (FBP) algorithm is correctly implemented.
import numpy as np
import matplotlib.pyplot as plt
from skimage.data import shepp_logan_phantom
from skimage.transform import radon
from scipy.fftpack import fft, ifft, fftfreq
from scipy.ndimage import rotate

# Step 1: Create the Shepp-Logan Phantom image


image = shepp_logan_phantom()

# Step 2: Generate the sinogram (Radon transform)


theta = np.linspace(0., 180., max(image.shape), endpoint=False) #
Projection angles
sinogram = radon(image, theta=theta, circle=True)

# Step 3: Implement the Ramp filter


def ramp_filter(sinogram):
num_projections, num_detectors = sinogram.shape
freqs = fftfreq(num_detectors).reshape(-1, 1)
ramp = np.abs(freqs)
sinogram_fft = fft(sinogram, axis=0)
filtered_sinogram_fft = sinogram_fft * ramp
filtered_sinogram = np.real(ifft(filtered_sinogram_fft, axis=0))
return filtered_sinogram

# Apply the ramp filter to the sinogram


filtered_sinogram = ramp_filter(sinogram)

# Step 4: Optimized Backprojection using `rotate`


def backprojection(filtered_sinogram, theta):
reconstructed_image = np.zeros((filtered_sinogram.shape[0],
filtered_sinogram.shape[0]))
mid_index = reconstructed_image.shape[0] // 2

# For each projection angle, backproject the filtered projections


onto the image
for i, angle in enumerate(theta):
projection = filtered_sinogram[:, i]
projection_image = np.tile(projection,
(filtered_sinogram.shape[0], 1))

# Rotate the projection image to the correct angle


rotated_projection = rotate(projection_image, angle,
reshape=False)

# Add the rotated projection to the reconstructed image


reconstructed_image += rotated_projection

return reconstructed_image

# Reconstruct the image using optimized backprojection


reconstructed_image = backprojection(filtered_sinogram, theta)

# Step 5: Display the original and reconstructed images


fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

ax1.imshow(image, cmap='gray')
ax1.set_title('Original Image')
ax1.axis('off')

ax2.imshow(reconstructed_image, cmap='gray')
ax2.set_title('Reconstructed Image (Optimized FBP)')
ax2.axis('off')

plt.show()
Explanation of the Filtered Back Projection (FBP) Code
1. Mid Index (mid_index):
• mid_index = reconstructed_image.shape[0] // 2
• This variable represents the center of the reconstructed image. It is used to ensure that
the filtered projections are centered correctly in the image grid during the backprojection
process.
• Since the image grid is symmetric (square), dividing the number of pixels by 2 gives the
middle index. This is important when you are rotating and placing projections back onto
the grid, so they are aligned properly around the center.

2. Rotation of Projections (rotate):


• rotate(projection_image, angle, reshape=False)
• This line rotates the projection_image (a 2D projection created by tiling the 1D
filtered sinogram data).
• angle: This is the angle by which the projection should be rotated to align it with its
original acquisition direction (i.e., the angle at which the projection was captured during
the Radon transform).
• reshape=False: This parameter ensures that the dimensions of the rotated image are
the same as the original. Without this, the rotate function would expand the image's
dimensions to fit the entire rotated image, which would slow down the process and
create unnecessary border space around the rotated image. Keeping reshape=False
ensures the rotated image fits within the original grid size, maintaining efficiency.

3. Tiling the Projection (np.tile):


• projection_image = np.tile(projection,
(filtered_sinogram.shape[0], 1))
• This line converts a 1D projection (a single column of the sinogram) into a 2D image by
repeating it across all rows. This creates a "flat" 2D projection that can then be rotated
and backprojected.
• Why?: Since we need to rotate the projection data to align it with the corresponding
angle, we first need to transform the 1D projection into a 2D form that can be rotated and
backprojected onto the image space.

4. Accumulate Rotated Projections:


• reconstructed_image += rotated_projection
• This line adds the rotated projection to the final reconstructed image. The idea of
backprojection is to "smear" the projection data back across the image grid in the
direction it was originally projected from. By summing the contributions from all the
projections at different angles, the final image is gradually reconstructed.

Summary of Key Optimizations:


1. rotate Function: This replaces the manual rotation logic with a highly efficient function
from scipy.ndimage. It handles the rotation internally in an optimized way, speeding
up the backprojection step significantly.
2. reshape=False: Ensures that the rotated projections stay within the same image size,
avoiding unnecessary computational overhead.
3. Vectorized Operations (np.tile): This efficiently converts 1D projections into 2D
format for rotation, eliminating the need for nested loops.

This approach should execute much faster and produce an accurate reconstruction using the
Filtered Back Projection (FBP) method.

You might also like