This post was translated from Korean into English by AI.
Today, I suddenly became curious about how CT images are reconstructed. So I came up with a simple hypothesis about CT image reconstruction and tested it myself.
Hypothesis
I know the following facts about CT.
- A CT scanner has a doughnut-shaped structure that rotates as it images an object inside the opening.
- CT captures only one cross-section at a time.
- CT uses X-rays.
- When a ray passes through an object, its intensity decreases exponentially.
From these facts, we can make the following additional inferences.
- A CT scanner emits beams from one side and detects them on the other.
- If there were only a single beam, it would be impossible to distinguish a solid cylinder from a hollow cylinder. Therefore, there must be multiple beams.
Modeling
Based on this, I first modeled X-ray attenuation in a homogeneous object as follows.
Here, is the intensity of the light before it passes through the object, is its intensity after it passes through the object, is the object's attenuation coefficient, and is the thickness of the object.
For convenience, if we set to 1, the equation can be rewritten as follows.
From this, as an X-ray passes through an object,
- when it passes through infinitesimal areas (which can therefore be assumed to be homogeneous) , , , ...,
- if the attenuation coefficients of the respective infinitesimal areas are , , , ..., and
- if the distances the ray travels through the respective infinitesimal areas are , , , ...,
then the intensity of the light after it passes through the object can be expressed as follows.
Because this is difficult to calculate, we can take the logarithm of both sides and rewrite it as follows.
Here, and have different values for each ray, so multiple rays cannot be represented in a single matrix. To solve this problem, we use the following method.
- Divide the cross-section to be measured into infinitesimal areas. (Any suitable tessellation will work. Dividing it into a square grid will probably make the calculations easier.)
- Assign an index to each infinitesimal area. (The order in which the indices are assigned does not matter.)
- Define a selection matrix . is the distance that the th ray travels through the th infinitesimal area. For example, for a square grid in which every side has length , this value can be .
The equation above can then be expressed in the following form.
This can be expressed as a matrix operation as follows.
Here, is a vector whose elements are the attenuation coefficients of the infinitesimal cross-sectional areas, and is the selection matrix. is a vector whose elements are the measured light intensities of the respective rays.
- is a known value obtained through actual measurement.
- is a known value obtained through calculation.
- is the value we want to determine.
If the number of infinitesimal areas into which the cross-section is divided is n and the number of rays is m, the matrices have the following dimensions.
In general, , so is not a square matrix. Therefore, this matrix operation does not have an exact solution, and the solution must be found using the pseudo-inverse. It can then be expressed in the following form.
For convenience, if we let ,
Implementation
- The infinitesimal areas are treated as a 64x64 square grid in which every side has length 1.
- For computational convenience, if the distance between the th ray and the th infinitesimal area is , I approximated it as . Since the grid length was set to 1, this becomes .
- To model a CT scanner, I assumed that m parallel rays capture images while rotating through 180 degrees. Each step is rad.
- Because solving the matrix equation directly without explicitly calculating is slightly faster, I implemented it that way.
- The matrix should originally contain values in , but errors produce values outside this range. To prevent this, I clip the elements of the matrix so that their values remain in .
The code was implemented using Python, NumPy, and OpenCV, and is available in the repository below.
https://github.com/unknownpgr/ct-reconstruction
config.pycontains resolution-related settings.calculate.pyperforms the matrix operations described above.visualize.pyvisualizes the results.
Result
- Original image

- Reconstructed image

We can see that the resulting image is very similar to the original.
Discussion
The most time-consuming task in the process above is finding the pseudo-inverse. The computational time complexity of the pseudo-inverse operation is (where is the number of rays and is the number of infinitesimal areas), and the matrix is extremely large, with dimensions of approximately . However, once the ray emission pattern has been determined, the matrix does not change. Therefore, by deciding on the ray emission pattern in advance and precomputing the matrix and its pseudo-inverse, it should be possible to save a great deal of time later.