Sinograms of an Image

The discretized Radon transforms are often used to approximate sinograms of a known image. adrt provides utilities that map the ADRT output which is in the ADRT coordinates \((s, h)\) to a sinogram which is in the Cartesian coordinates \((\theta, t)\).

We make use of this package as well as a few other fundamental libraries.

import numpy as np
from matplotlib import pyplot as plt
import adrt

We will illustrate the computation of sinograms with a few examples. The simple geometry relating the two coordinates \((s, h)\) and \((\theta, t)\) is detailed in the Coordinate Transform Section.

Gaussian Humps

We compute an image that is a sum of two Gaussian humps.

n = 2**9
x1 = np.linspace(0.0, 1.0, n)
X, Y = np.meshgrid(x1, x1)
s1 = 200
s2 = 100

gaussians = np.exp(-s1 * (X - 0.75) ** 2 - s1 * (Y - 0.3) ** 2) + np.exp(
    -s2 * (X - 0.25) ** 2 - s2 * (Y - 0.8) ** 2
)
plt.imshow(gaussians, extent=(0, 1, 0, 1))
plt.colorbar();
_images/d19ae8641d1f75c2d5d2543ec1b90cbed84cb5be1106584d140793e6ed268c11.png

We compute the ADRT of this image and plot the image.

adrt_result = adrt.adrt(gaussians)
adrt_stitched = adrt.utils.stitch_adrt(adrt_result)

plt.imshow(adrt_stitched)
plt.colorbar()
for i in range(1, 4):
    plt.axvline(n * i - 0.5, color="white", linestyle="--")
plt.ylabel("$h$")
plt.xlabel("$s$")
plt.tight_layout();
_images/b3714c1e2e345d8fc2facfaf7b79393faecc7386e02aaf4ebf4e1b0439766a1b.png

From the ADRT data we compute the sinogram by using the function adrt.utils.interp_to_cart(). Each isotropic Gaussian hump corresponds to a sinusoidal curve of commensurate width in the sinogram.

img_cart = adrt.utils.interp_to_cart(adrt_result)
img_extent = 0.5 * np.array([-np.pi, np.pi, -np.sqrt(2), np.sqrt(2)])

plt.imshow(img_cart, aspect="auto", extent=img_extent)
plt.colorbar()
plt.xticks(
    [-np.pi / 2, -np.pi / 4, 0, np.pi / 4, np.pi / 2],
    [r"$-\pi/2$", r"$-\pi/4$", "0", r"$\pi/4$", r"$\pi/2$"],
)
plt.ylabel("$t$")
plt.xlabel(r"$\theta$");
_images/ab2e260e6bdd9e4ae574db187d894085b087d0633c9f0c734865f1bd1ff11bd3.png

Shepp-Logan Phantom

As a more involved example we can consider the Shepp-Logan phantom (data file).

phantom = np.load("data/shepp-logan.npz")["phantom"]
n = phantom.shape[0]

# Display the image
plt.imshow(phantom, cmap="bone")
plt.colorbar()
plt.tight_layout();
_images/6824c06d29e06e55a3c86e10f5bba57c2297d2a0d7851a6caae479b0570887da.png

We can start by computing the ADRT of this image

adrt_result = adrt.adrt(phantom)
adrt_stitched = adrt.utils.stitch_adrt(adrt_result)

plt.imshow(adrt_stitched)
plt.colorbar()
for i in range(1, 4):
    plt.axvline(n * i - 0.5, color="white", linestyle="--")
plt.ylabel("$h$")
plt.xlabel("$s$")
plt.tight_layout();
_images/4c6875ee8b02700a464b8cd231db69eb064869d2f14d801121e5842ffd7cc172.png

These can be interpolated to a Cartesian grid with adrt.utils.interp_to_cart().

img_cart = adrt.utils.interp_to_cart(adrt_result)
img_extent = 0.5 * np.array([-np.pi, np.pi, -np.sqrt(2), np.sqrt(2)])

plt.imshow(img_cart, aspect="auto", extent=img_extent)
plt.colorbar()
plt.xticks(
    [-np.pi / 2, -np.pi / 4, 0, np.pi / 4, np.pi / 2],
    [r"$-\pi/2$", r"$-\pi/4$", "0", r"$\pi/4$", r"$\pi/2$"],
)
plt.ylabel("$t$")
plt.xlabel(r"$\theta$");
_images/f6610684dfdd988b60e1d739db80efe5952fd20c52842ba66732659fdeeabc6b.png