Com­put­er­ized tomog­ra­phy (CT) and related tech­niques such as PET or MRI are very com­mon tools in med­ical imag­ing. They allow to resolve the 3D struc­ture of liv­ing tis­sues. Tomog­ra­phy itself is divided into two process­ing steps. First, pro­jec­tion images are recorded for sev­eral angles, the result of which is called a sino­gram. Second, this sino­gram is used to recon­struct a 3D rep­re­sen­ta­tion of the orig­i­nal object. In the most sim­ple case, the object (or detec­tor) rota­tion is per­formed only about one axis, which means that the 3D recon­struction from 2D images can be bro­ken down to sev­eral 2D slice recon­structions from 1D line scans. For CT, the sino­gram con­sists of x-ray absorp­tion images: Bone tis­sue absorbs x-ray radi­a­tion and thus bones appear white on the devel­oped pho­to­graphic x-ray film. A PET image visu­al­izes the radi­a­tion of radioac­tive trac­ers linked to bio­log­i­cal mole­cules that accu­mu­late in the tar­geted tis­sue. In MRI, image con­trast is com­puted from the time-de­pen­dent mag­netic response of tis­sues to strong dynamic mag­netic fields. The main prob­lem to solve in tomo­graphic imag­ing is the recon­struction step, i.e. the ill-­posed inver­sion of the Radon transform. While nowa­days there exist iter­a­tive approaches that take into account prior knowl­edge about the imaged sample, the most beau­ti­ful recon­struc­tion arti­facts can be achieved with the clas­si­cal back­prop­a­ga­tion algorithm. In general, the qual­ity of the 3D recon­struc­tion in CT-­like imag­ing depends on the num­ber of recorded images (the more the bet­ter) and on the angu­lar cov­er­age (be­low 180° only par­tial cov­er­age can be achieved). The artis­tic tomo­graphic image fil­ter enforces low recon­struc­tion qual­ity by address­ing such aspects.

Filter operation

The basic mode of oper­a­tion of the artis­tic tomo­graphic fil­ter is to sim­u­late the sino­gram acqui­si­tion process and to recon­struct the orig­i­nal image from the sim­u­lated sino­gram. Here is an exam­ple that illus­trates the steps from orig­i­nal image to sino­gram image to recon­structed image with 256 angles (de­lib­er­ately match­ing the image dimen­sions 256x256 px for visu­al­iza­tion purposes):

original sinogram reconstruction

As men­tioned above, the actual artis­tic poten­tial of the fil­ter will only be released, if the num­ber of angles in the sino­gram used for the recon­struc­tion is reduced:

5 angles 10 angles 20 angles

The result­ing arti­facts con­sist of streaks through the image that, when many of them intersect, repro­duce the orig­i­nal image content. The fil­ter can be mod­i­fied in sev­eral dif­fer­ent ways, some of which are cov­ered fur­ther below.

Python setup

The artis­tic tomo­graphic fil­ter uses the back­pro­jec­tion algo­rithm I imple­mented in the Python library radontea. Radon­tea also comes with an imple­men­ta­tion of the Radon trans­form which is used to com­pute the sino­gram from the input image. For load­ing and writ­ing images, imageio is used. For Python 3, imageio and radon­tea can be installed from the Python pack­age index via pip install imageio radontea.

To use the filter, down­load and exe­cute it like so:

python input_image.jpg

This will pro­duce a new image input_image_tf.jpg, gen­er­ated with the stan­dard fil­ter­ing parameters.

Tweak and tune

The script comes with a con­ve­nient com­mand line inter­face that allows to tune sev­eral parameters, from Radon trans­form to backprojection, affect­ing the artis­tic char­ac­ter of the filter.

By default, the fil­ter uses 37 equally spaced angles with a full angu­lar cov­er­age (from 0° to 180°).

orig­i­nal [highres] fil­ter with defaults [highres]

The angu­lar cov­er­age can be mod­i­fied with the argu­ments --cov-min (de­fault 0) and --cov-max (de­fault 180), lead­ing to so-­called miss­ing-an­gle artifacts.

orig­i­nal [highres] defaults [highres] --cov-max 120 [highres]

To achieve a more chaotic behavior, the angles can be dis­trib­uted ran­domly using the --randomness argument. To improve the recog­niz­abil­ity of the object, --weight-angles can be com­bined with ran­domly dis­trib­uted angles.

orig­i­nal [highres] --randomness 47 [highres] --randomness 47 and --weight-angles [highres]

Ran­dom dis­tri­b­u­tion of angles can also be com­bined with par­tial angu­lar coverage. The choice of angles affects the angu­lar posi­tions of the streaks, some­times result­ing in exag­ger­ated edge contrast.

orig­i­nal [highres] --randomness 8472, --cov-min 20, and --cov-max 160 [highres] --randomness 8472 and --cov-min 70 [highres]

For bright images (black images would have to be inverted first), it might also be worth­while to dis­able the color nor­mal­iza­tion prior to com­put­ing the sinogram. This pro­duces a ring-shaped arti­fact around the image.

--no-normalize and --num-angles 20 --no-normalize [highres] --no-normalize, --randomness 42 and --weight-angles [highres]

Video generation

The --offset option allows to change the off­set of the angles used. The fol­low­ing script imports as a mod­ule and gen­er­ates a series of 180 fil­tered images at a 1°-spacing.

import tomographic_filter

path_in = "crow.jpg"

for ii in range(0, 180):
    path_out = "crow_tf_{:03d}.png".format(ii)

The result­ing png files can be con­verted to a browser-­com­pat­i­ble video using avconv/ffmpeg:

avconv -r 15 -i crow_tf_%03d.png -c:v vp8 -b:v 10M crow.webm
original off­set series video

Angu­lar off­sets are also a nice way of visu­al­iz­ing miss­ing-an­gle artifacts. Recog­niz­abil­ity of the orig­i­nal image often depends on the angu­lar range cov­ered by the sinogram. In the next example, the key­word argu­ments ival_coverage=(0,100) and normalize=False were used.

original off­set series video


The exam­ples shown here do not exhaust the full capa­bil­ity of the tomo­graphic fil­ter. Besides the var­i­ous com­bi­na­tions of the fil­ter para­me­ters given, other parameters could be used, such as padding or filtering. In addition, a dif­fer­ent recon­struc­tion algorithm, such as Fourier domain map­ping could be used. A qual­i­ta­tive com­par­i­son of the avail­able algo­rithms can be found at the radon­tea docs.


Install Python 3, pip install imageio radontea, down­load, and exe­cute it, pass­ing an image path as an argument.

python /path/to/image.jpg

For a list of pos­si­ble com­mand-­line arguments, use --help.

python --help.