reconstructing an image from projection data -凯发k8网页登录
this example shows how to form parallel-beam and fan-beam projections from a head phantom image, and how to reconstruct the image using radon and fan-beam transforms.
the
radon
and iradon
functions use a parallel-beam geometry for the projections, whereas the fanbeam
and ifanbeam
use a fan-beam geometry. to compare parallel-beam and fan-beam geometries, the examples below create synthetic projections for each geometry and then use those synthetic projections to reconstruct the original image.
a real-world application that requires image reconstruction is x-ray absorption tomography where projections are formed by measuring the attenuation of radiation that passes through a physical specimen at different angles. the original image can be thought of as a cross section through the specimen in which intensity values represent the density of the specimen. projections are collected by special medical imaging devices and then an internal image of the specimen is reconstructed using iradon
or ifanbeam
.
the function iradon
reconstructs an image from parallel-beam projections. in parallel-beam geometry, each projection is formed by combining a set of line integrals through an image at a specific angle. the function ifanbeam
reconstructs an image from fan-beam projections, which have one emitter and multiple sensors.
create head phantom
the test image is the shepp-logan head phantom which can be generated using the function phantom
. the phantom image illustrates many qualities that are found in real-world tomographic imaging of human heads. the bright elliptical shell along the exterior is analogous to a skull and the many ellipses inside are analogous to brain features or tumors.
p = phantom(256); imshow(p)
parallel beam - calculate synthetic projections
calculate synthetic projections using parallel-beam geometry and vary the number of projection angles. for each of these calls to radon
, the output is a matrix in which each column is the radon transform for one of the angles in the corresponding theta
.
theta1 = 0:10:170; [r1,~] = radon(p,theta1); num_angles_r1 = size(r1,2)
num_angles_r1 = 18
theta2 = 0:5:175; [r2,~] = radon(p,theta2); num_angles_r2 = size(r2,2)
num_angles_r2 = 36
theta3 = 0:2:178; [r3,xp] = radon(p,theta3); num_angles_r3 = size(r3,2)
num_angles_r3 = 90
note that for each angle, the projection is computed at n points along the xp-axis, where n is a constant that depends on the diagonal distance of the image such that every pixel will be projected for all possible projection angles.
n_r1 = size(r1,1)
n_r1 = 367
n_r2 = size(r2,1)
n_r2 = 367
n_r3 = size(r3,1)
n_r3 = 367
so, if you use a smaller head phantom, the projection needs to be computed at fewer points along the xp-axis.
p_128 = phantom(128); [r_128,xp_128] = radon(p_128,theta1); n_128 = size(r_128,1)
n_128 = 185
display the projection data r3
. some of the features of the original phantom image are visible in the image of r3
. the first column of r3
corresponds to a projection at 0 degrees, which is integrating in the vertical direction. the centermost column corresponds to a projection at 90 degrees, which is integrating in the horizontal directions. the projection at 90 degrees has a wider profile than the projection at 0 degrees due to the large vertical semi-axis of the outermost ellipse of the phantom.
imagesc(theta3,xp,r3) colormap(hot) colorbar xlabel('parallel rotation angle - \theta (degrees)'); ylabel('parallel sensor position - x\prime (pixels)');
parallel beam - reconstruct head phantom from projection data
match the parallel rotation-increment, dtheta
, in each reconstruction with that used above to create the corresponding synthetic projections. in a real-world case, you would know the geometry of your transmitters and sensors, but not the source image, p
.
the following three reconstructions (i1
, i2
, and i3
) show the effect of varying the number of angles at which projections are made. for i1
and i2
some features that were visible in the original phantom are not clear. specifically, look at the three ellipses at the bottom of each image. the result in i3
closely resembles the original image, p
.
notice the significant artifacts present in i1
and i2
. to avoid these artifacts, use a larger number of angles.
% constrain the output size of each reconstruction to be % the same as the size of the original image, |p|. output_size = max(size(p)); dtheta1 = theta1(2) - theta1(1); i1 = iradon(r1,dtheta1,output_size); dtheta2 = theta2(2) - theta2(1); i2 = iradon(r2,dtheta2,output_size); dtheta3 = theta3(2) - theta3(1); i3 = iradon(r3,dtheta3,output_size); figure montage({i1,i2,i3},'size',[1 3]) title(['reconstruction from parallel beam projection ' ... 'with 18, 24, and 90 projection angles'])
fan beam - calculate synthetic projections
calculate synthetic projections using fan-beam geometry and vary the 'fansensorspacing'
.
d = 250; dsensor1 = 2; f1 = fanbeam(p,d,'fansensorspacing',dsensor1); dsensor2 = 1; f2 = fanbeam(p,d,'fansensorspacing',dsensor2); dsensor3 = 0.25; [f3,sensor_pos3,fan_rot_angles3] = fanbeam(p,d, ... 'fansensorspacing',dsensor3);
display the projection data f3
. notice that the fan rotation angles range from 0 to 360 degrees and the same patterns occur at an offset of 180 degrees because the same features are being sampled from both sides. you can correlate features in this image of fan-beam projections with the same features in the image of parallel-beam projections, above.
imagesc(fan_rot_angles3,sensor_pos3,f3) colormap(hot) colorbar xlabel('fan rotation angle (degrees)') ylabel('fan sensor position (degrees)')
fan beam - reconstruct head phantom from projection data
match the fan-sensor-spacing in each reconstruction with that used to create each of the synthetic projections. in a real-world case, you would know the geometry of your transmitters and sensors, but not the source image, p
.
changing the value of the 'fansensorspacing'
effectively changes the number of sensors used at each rotation angle. for each of these fan-beam reconstructions, the same rotation angles are used. this is in contrast to the parallel-beam reconstructions which each used different rotation angles.
note that 'fansensorspacing' is only one parameter of several that you can control when using fanbeam
and ifanbeam
. you can also convert back and forth between parallel- and fan-beam projection data using the functions fan2para
and para2fan
.
ifan1 = ifanbeam(f1,d,'fansensorspacing',dsensor1, ... 'outputsize',output_size); ifan2 = ifanbeam(f2,d,'fansensorspacing',dsensor2, ... 'outputsize',output_size); ifan3 = ifanbeam(f3,d,'fansensorspacing',dsensor3, ... 'outputsize',output_size); montage({ifan1,ifan2,ifan3},'size',[1 3]) title(['reconstruction from fan beam projection with '... '18, 24, and 90 projection angles'])