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/1afebaeb664adb04f2f234f9c1f8656aa70c7199880b33e6f9c00d7652eba3d4.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/03e5986db21c055f8ebe2704f8c1b75780f21d025f7b257efaee34d49591ac0b.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/de56b4f162fd428375394c9ca3e587de34c53d17c39208deac7a53a112f203ed.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/07fc2fdb27b19dcfc7dd7ebff0faa3c60eb540b3cab01f21294d82037e699f87.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/9c924fed4e35f6bd147f58369d2b922be2320c07e4bcd4a03119c58a6e66ef67.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/a043c895e0820d8c66fe94ecd7a7ae6812e1c7fe1b011b13d1868326fdac226c.png