4.3. Methods and tools for removing ring artifacts

Algotom provides improved implementations of many methods for removing ring artifacts; which were published previously by the same author in Sarepy; to be easier to use and customize. More than that, there are many tools for users to design their own removal methods.

Note that ring artifacts in a reconstructed image are corresponding to stripe artifacts in the sinogram image or the polar-transformed image. Most of ring removal methods are actually stripe removal methods under the surface.


Fig. 4.3.1 Ring removal methods working on sinogram image, known as pre-processing methods. (a) Sinogram before correction. (b) Sinogram after correction. (c) Reconstructed image from sinogram (a). (d) Reconstructed image from sinogram (b).


Fig. 4.3.2 Ring removal methods working on polar-transformed image, known as post-processing methods. (a) Reconstructed image before correction. (b) Polar transformation of image (a). (d) Stripe artifacts removed from image (b). (c) Cartesian transformation of image (d).

4.3.1. Improvements

  • Users can select different smoothing filters available in Scipy or in Algotom utility module for removing stripes by passing keyword arguments as dict type:

    import algotom.io.loadersaver as losa
    import algotom.prep.removal as rem
    sinogram = losa.load_image("D:/data/sinogram.tif")
    # Sorting-based methods use the median filter by default, users can select
    # another filter as below.
    sinogram1 = rem.remove_stripe_based_sorting(sinogram, option={"method": "gaussian_filter",
                                                                  "para1": (1, 21)})
  • The sorting-based technique, which is simple but effective to remove partial stripes and avoid void-center artifacts, is an option for other ring removal methods.

    sinogram2 = rem.remove_stripe_based_filtering(sinogram, 3, sort=True)
    sinogram3 = rem.remove_stripe_based_regularization(sinogram, 0.005, sort=True)

4.3.2. Tools for designing ring removal methods

The cleaning capability with least side-effect of a ring removal method relies on a smoothing filter or an interpolation technique which the method employs. Other supporting techniques for revealing stripe artifacts such as sorting, filtering, fitting, wavelet decomposition, polar transformation, or forward projection are commonly used. Algotom provides these supporting tools for users to incorporate with their own smoothing filters or interpolation techniques. Back-and-forth sorting

The technique (algorithm 3 in [R19]) couples an image with an index array for sorting the image backward and forward along an axis. Users can combine the sorting forward method, a customized filter, and the sorting backward method as follows


Fig. 4.3.3 Demonstration of the forward sorting.

import algotom.util.utility as util
import scipy.ndimage as ndi

# Sort forward
sino_sort, mat_index = util.sort_forward(sinogram, axis=0)
# Use a customized smoothing filter here
sino_sort = apply_customized_filter(sino_sort, parameters)
# Sort backward
sino_corr = util.sort_backward(sino_sort, mat_index, axis=0)

Fig. 4.3.4 Demonstration of the backward sorting. Separation of frequency components

The technique can help to reveal stripe artifacts by separating frequency components of each image-column using a 1D window available in Scipy. Example of how to use the technique:

# Separate a sinogram image
sino_smooth, sino_sharp = util.separate_frequency_component(sinogram, axis=0,
                                                            window={"name": "gaussian",
                                                                    "sigma": 5})
# Use a customized smoothing filter here
sino_smooth_filtered = apply_customized_filter(sino_smooth, parameters)
# Add back
sino_corr = sino_smooth_filtered + sino_sharp

Fig. 4.3.5 Demonstration of how to separate frequency components of a sinogram along each column. Polynomial fitting along an axis

The technique can help to reveal low contrast stripes easily by applying a polynomial fit along each image-column.

sino_fit = util.generate_fitted_image(sinogram, 3, axis=0, num_chunk=1)
# Use a customized smoothing filter here
sino_smooth = apply_customized_filter(sino_fit, parameters)
# Get back the sinogram
sino_corr = (sinogram / sino_fit) * sino_smooth

Fig. 4.3.6 Demonstration of how to apply a polynomial fitting along each column of a sinogram. Wavelet decomposition and reconstruction

Functions for wavelet decomposition, wavelet reconstruction, and applying a smoothing filter to specific levels of directional image-details are provided. The following codes decompose a sinogram to level 2. As can be seen in Fig. 4.3.7 stripe artifacts are visible in vertical details of results. One can apply a smoothing filter to remove these stripes then apply a wavelet reconstruction to get the resulting sinogram.

outputs = util.apply_wavelet_decomposition(sinogram, "db9", level=2)
[mat_2, (cH_level_2, cV_level_2, cD_level_2), (cH_level_1, cV_level_1, cD_level_1)] = outputs
# Save results of vertical details
# losa.save_image("D:/output/cV_level_2.tif", cV_level_2)
# losa.save_image("D:/output/cV_level_1.tif", cV_level_1)

# Apply the gaussian filter to each level of vertical details
outputs = util.apply_filter_to_wavelet_component(outputs, level=None, order=1,
                                                 method="gaussian_filter", para=[(1, 11)])
# Optional: remove stripes on the approximation image (mat_2 above)
outputs[0] = rem.remove_stripe_based_sorting(outputs[0], 11)
# Apply the wavelet reconstruction
sino_corr = util.apply_wavelet_reconstruction(outputs, "db9")

Fig. 4.3.7 Demonstration of the wavelet decomposition. Stripe interpolation

Users can design a customized stripe-detection method, then pass the result (as a 1D binary array) to the following function to remove stripes by interpolation.

sino_corr = util.interpolate_inside_stripe(sinogram, list_mask, kind="linear") Transformation between Cartesian and polar coordinate system

This is a well-known technique to remove ring artifacts from a reconstructed image as shown in Fig. 4.3.2.

img_rec = losa.load_image("D:/data/reconstructed_image.tif")
# Transform the reconstructed image into polar coordinates
img_polar = util.transform_slice_forward(img_rec)

# Use a customized smoothing filter here
img_corr = apply_customized_filter(img_polar, parameters)

# Transform the resulting image into Cartesian coordinates
img_carte = util.transform_slice_backward(img_corr) Transformation between sinogram space and reconstruction space

Algotom provides a re-projection method to convert a reconstructed image to the sinogram image. As using directly the Fourier slice theorem it’s fast compared to ray-tracing-based methods or image-rotation-based methods.

import numpy as np
import algotom.util.simulation as sim
import algotom.rec.reconstruction as rec

rec_img = losa.load_image("D:/data/reconstructed_image.tif")
(height, width) = rec_img.shape
angles = np.deg2rad(np.linspace(0.0, 180.0, height))

# Re-project the reconstructed image
sino_calc = sim.make_sinogram(rec_img, angles=angles)

# Use a customized stripe-removal method
sino_corr = apply_customized_filter(sino_calc, parameters)

# Reconstruct
img_rec = rec.dfi_reconstruction(sino_corr, (width - 1) / 2, apply_log=False)

Fig. 4.3.8 Demonstration of how to re-project a reconstructed image.