Computed tomography is a collection of X-ray images stacked together in order to get the depth information as the third dimension of a diagnostic image. These "stacked" X-ray images are received as a sinogram from the CT gantry, and represent the X-ray absorption profile of a single layer of the subject. The objective of this project was to re-construct the original 2D image of this single layer and also distinguish between different X-ray absorption levels by the subject's tissues using light attenuation information.
Below we see an example of how a sinogram (right) is formed by passing X-ray beams through a cross sectional layer of the body (left), with the X-ray absorption from each angle generating a graph of attenuation profile.
The X-ray projection of the object at each angle of the CT gantry rotation produces a sinogram where the Y axis shows the angle in degrees while the X axis shows the spatial distance.
I've created a sample sinogram and the goal of this project is to construct its corresponding phantom object. We'll be determining the X-ray attenuation through the different layers within the phantom and thereby get object density profile for the object.
Input Sinogram | Output should be close to |
---|---|
The 0th moment, as shown in the figure above is the response of the CT detectors when X-rays first hit them at each angle. This would be the sum of attenuation amplitude (Y axis) at each angle (X axis) and therefore will be the sum of each of the 256 angular projected columns of the sinogram.
The striking result of it being a flat line is because no matter which angle the projection is being taken from, the sum of the attenuation intensity will be constant since the object features are static.
A simple back-projection is computed by overlaying projections on top of each other which create a concentration gradient for all the components of the image. A single column will contain the attenuation information for a single angular projection. There are 256 angular projections in total which correspond to the 180 degree shown on the sinogram.
We therefore select one column at a time, smear the attenuation magnitude information over 128 rows and then rotate it to the angle which corresponds to in degrees (256th projection corresponds to 180 degrees, so nth projection will correspond to n*180/256 degrees).
Not close enough to the real output image, but certainly a step closer!The specific ‘greyness’ is added again and again every time a new projection smear is added to the old one. This makes the dark spots to show relatively dark and the light spots will show relatively light on the back-projected image.
For carrying out filtered back-projection of the sinogram, we need to construct the filter that we will be using in frequency domain. This will help us easily multiply it to the Fourier transformed sinogram instead of performing convolution. The filter response is then multiplied with a Fourier transformed (and shifted) sinogram. The result to this is a Ram-Lak (high-pass filter) filtered sinogram, in frequency domain and all zero frequencies centered.
To get the original frequency distribution, we inverse-Fourier-shift and then inverse-Fourier-transform it to later get the spatial domain sinogram. We see how the filter response is far more selective than the non-fitlered couterpartand we can see there are amplitude spikes when an edge is detected.
Filtered Sinogram | Filtered vs Original |
---|---|
As compared to our simple back-projected image, we see that the Ram-Lak filter has been able to remove low frequency noise (haze), improve contrast, thereby improving the total signal-to-noise ratio. The resolution also seems to have increased but mainly due to the increased sharpness and improved contrast.
Lets also explore MATLAB's inbuilt functions to do this. We use the Radon and inverse Radon transforms for this purpose.
theta=0:180;
[R,rad_angles]=radon(phantom,theta); % as shown in radon help file
imagesc(rad_angles,theta,R'); colormap('gray');
title('Sinogram Generated Using radon Function')
xlabel('Position')
ylabel('Angle')
RamLak_filtered=iradon(R, theta, 'linear','Ram-Lak', 1.0, size(phantom,1));
imagesc(RamLak_filtered); colormap('gray');
title('Filtered Backprojection Using iradon Function and Ram-Lak Filter')
xlabel('Position')
ylabel('Position')
Hamming_filtered=iradon(R, theta, 'linear','Hamming', 1.0, size(phantom,1));
imagesc(Hamming_filtered); colormap('gray');
title('Filtered Backprojection Using iradon Function and Hamming Filter')
xlabel('Position')
ylabel('Position')
Ram-Lak Filtered Output | Hamming Filtered Output |
---|---|
Ram-Lak filter being a high pass filter as compared to the mid-frequency pass Hamming filter, we see the Ram-Lak filtered image has sharper features than the Hamming filtered image. So to have better sharpness and better resolution on medical images, Ram-Lak filter would be the better fit.
If you want to try reconstructing images from your own sinogram database, go ahead!Fiddle with the parameters and try different filters to see how the result image varies.
Installations Required:
Michigan Image Reconstruction Toolbox (MIRT) - Matlab Version https://github.com/JeffFessler/mirt This directory contains various algorithms for image reconstruction and other inverse problems such as
MIRT 官方文档解读 原网页翻译如下: 密歇根图像重建工具箱(MIRT)是一组用Mathwork的Matlab语言编写的图像重建(和相关的图像问题)的开源算法。这个软件是由杰夫·费斯勒和他的团队在密歇根大学开发的。工具箱包括以下内容。 迭代和非迭代算法的层析成像(PET, SPECT, x射线CT)。 磁共振(MR)图像重建的方法,包括补偿非共振效应(场的不均匀性、磁化率等) 方法磁共振射频脉冲
Hello everyone,I am trying to reconstruct an image from a projection data mat file. It consists of data with 256 angles of projection. This is the program that I wrote to reconstruct the image. I need
COVID-CT The utility of this dataset has been confirmed by a senior radiologist in Tongji Hospital, Wuhan, China, who has performed diagnosis and treatment of a large number of COVID-19 patients durin
Recki-CT 是一个用 PHP 开发的 PHP 编译器。 简单示例: /** * @return void */function foo($bar) {}// Instead of using:foo($baz);// Use:$foo = Jit::JitFu('foo');$foo($baz);
CT-Eclipse 是一款 Eclipse 的持续测试插件。 首先解释一下,英文是Continuous testing,中文是持续测试 就是测试在后台自动运行,指出你的错误,然后对应的测试用例代码中会有错误提示。举一个简单例子在IDE中,我们写了代码以后然后顺手快捷键保存,然后后 台自动编译,然后报错,然后我们修改之到无错。然后运行单元测试,如果出错我们会在JUnit的Eclipse插件中查看错误,然后改之,然后运行单元测 试。
描述 图片展示组件,类似于 HTML image 标签,但提供了更丰富的功能,使用时需指定样式宽高值。 安装 $ npm install rax-image --save 属性 属性 类型 默认值 必填 描述 支持 source Object: {uri: String} - ✔️ 设置图片的 uri style Object: { width: Number height: Number } -
图片操作. 支持 安装 $ npm install universal-image --save 方法 choose(options) 拍照或从本地相册中选择图片。 参数 属性 类型 默认值 必选 描述 支持 count Number 1 x 最大可选照片数 sizeType String Array ['original', 'compressed'] x original 原图,compres
简介 <image> 用于在界面中显示单个图片。 TIP 在代码中请使用 <image> 标签, <img> 的存在只是因为兼容性原因,在将来的版本中可能删除。 Weex 没有内置的图片库,因为一些开源项目如 SDWebImage 和Picasso已经能很好的解决这个问题, 所以在使用 <image> 之前,请在 native 侧先接入相应的 adapter 或者 handler。参见: Andr