Creation of a set of sinograms and the subsequent tomogram slices via back projection
Matlab code
% Movie cartoon of sinograms and back projections in x-ray tomography
% 34 slices through a skull and brain distributed across a 5 x 7 matrix,
% whereby the central element is first reserved for the rotating projection
% recorded during the scan, with a yellow bar moving down the image. As
% each new region is arrived at by the yellow bar, the border of the
% corresponding sinogram lights up. Once this is finished, the sinograms
% are replaced with the developing back projections.
% Number of sinogram images corresponding to different heights = 35
% Number of projections = 181
clear all; close all
vid = VideoWriter('sinograms.mp4','MPEG-4');
vid.Quality = 100;
vid.FrameRate = 15;
open(vid);
figure('units','pixels','position',[0 0 1920 1080],'ToolBar','none');
set(0,'defaultfigurecolor',[1 1 1]);
% Create an array of sinograms 7 across and 5 down. The middle one (4,3) is
% reserved for the original rotating transmission image, then the resulting
% layers of tomograms
width = 0.12; % width of sinogram/backprojection image
height = 0.17; % height of sinogram/backprojection image
stepcol = 0.14; % horizontal steps between columns
steprow = 0.2; % vertical steps between rows
%sinoarray = zeros(7,5,4);
% Generic basis for making a frame using 'fill'
xTh = 0.05;
xFr = [0 1 1 0 0 xTh 1-xTh 1-xTh xTh xTh];
yFr = [0 0 1 1 0 xTh xTh 1-xTh 1-xTh xTh];
LL = 2*180/37;
% Read in original slice files, modified to remove outer arcs at bottom of
% images and renamed from the public domain wikipedia source
% https://commons.wikimedia.org/wiki/Scrollable_computed_tomography_images_of_a_normal_brain_(case_2)
for slice = 1:34
str1 = 'skull/Computedtomographyofhumanbrain';
str2 = num2str(sprintf('%02d',slice));
str3 = '.png';
imgStr = [str1 str2 str3];
temp = imread(imgStr);
myIm(:,:,slice) = rgb2gray(temp);
Radon(:,:,slice) = radon(myIm(:,:,slice));
end
% Read in transmission projection image files
for proj = 1:75
str1 = 'skull/3dCTscananimation-';
% Start at file 20, close to skull being face on
imgIndx = 1+mod(18+proj,75);
str2 = num2str(sprintf('%02d',imgIndx));
str3 = '.tiff';
imgStr = [str1 str2 str3];
temp = imread(imgStr,'PixelRegion',{[3,172],[31,200]});
myIm2(:,:,proj) = rgb2gray(temp(:,:,1:3));
end
for theta = -1:180
slice = 1;
for row = 2:-1:-2
for col = -3:3
blx = 0.01+stepcol*(col+3)+(stepcol-width)/2; % bottom left x-coord
bly = steprow*(row+2)+(steprow-height)/2; % bottom left y-coord
pos = [blx bly width height];
hold off
subplot('position',pos);
newplot
R = radon(myIm(:,:,35-slice),0:theta);
a = size(R,1);
sinogramDummy = zeros(a,181);
if (theta >= 0) % Not first frame
sinogramDummy(:,1:theta+1) = R;
finalIm = imrotate(sinogramDummy,-90);
end
if (theta < 0) % First frame
if (row^2+col^2 == 0)
imshow(myIm2(:,:,1))
caxis([0 max(max(myIm2(:,:,1)))]);
else
imshow(sinogramDummy);
end
elseif (row^2+col^2 ~= 0) % Not the central image
imshow(finalIm);
caxis([0 max(max(finalIm))]);
frameFlagSt = 11 + (slice-1)*5;
frameFlagEnd = 10 + slice*5;
if (theta >= frameFlagSt) && (theta <= frameFlagEnd)
hold on
frame = fill(xFr*730,yFr*181,'y','LineStyle','none');
alpha(frame,0.7);
end
slice = slice+1;
else % The central image - only 38 projections between 0 and
% 180 degrees, so I fill in the frames in between by
% merging neighbouring images with different weightings.
% Relationship between theta and xx, the progression of the
% central image from straight on (image 1) to 180 deg
% around (image 38)
xx = 1 + theta*37/180;
yy = xx - floor(xx); % Goes from 0 to 1 in between images
mergeIm = myIm2(:,:,floor(xx))*(1-yy) + myIm2(:,:,ceil(xx))*yy;
imshow(mergeIm);
caxis([0 max(max(mergeIm))]);
hold on
xline = [1 170];
yline = 10+[theta theta]/2;
sliceHeight = plot(xline, yline,'y','LineWidth',4);
sliceHeight.Color(4) = 0.7;
end
axis square
colormap(bone)
hold off
end
end
frame = getframe(gcf);
writeVideo(vid,frame);
hold off
end
% Fade out sinograms to black and central projection image to white
for fadeOut = 1:-0.05:0
slice = 1;
for row = 2:-1:-2
for col = -3:3
blx = 0.01+stepcol*(col+3)+(stepcol-width)/2; % bottom left x-coord
bly = steprow*(row+2)+(steprow-height)/2; % bottom left y-coord
pos = [blx bly width height];
hold off
subplot('position',pos);
newplot
if (row^2+col^2 ~= 0)
Dummy = Radon(:,:,35-slice);
finalIm = imrotate(Dummy,-90);
imshow(finalIm*fadeOut);
caxis([0 max(max(finalIm))]);
hold on
slice = slice+1;
else
imshow(myIm2(:,:,38));
caxis([0 max(max(myIm2(:,:,38)))]);
hold on
fill([0 171 171 0 0],[0 0 171 171 0],'w','LineStyle',...
'none','FaceAlpha',1-fadeOut);
end
axis square
colormap(bone)
end
end
frame = getframe(gcf);
writeVideo(vid,frame);
hold off
end
pauseMov(vid,15);
for theta = 0:180
slice = 1;
for row = 2:-1:-2
for col = -3:3
if (row^2+col^2 ~= 0) % Not the central image
blx = 0.01+stepcol*(col+3)+(stepcol-width)/2; % bottom left x-coord
bly = steprow*(row+2)+(steprow-height)/2; % bottom left y-coord
pos = [blx bly width height];
hold off
subplot('position',pos);
newplot
R = radon(myIm(:,:,35-slice),0:theta);
backp = iradon(R,0:theta);
imshow(backp);
caxis([0 max(max(backp))]);
axis square
colormap(bone)
slice = slice+1;
else % The central image
blx = 0.01+stepcol*(col+3)+(stepcol-width)/2; % bottom left x-coord
bly = steprow*(row+2)+(steprow-height)/2; % bottom left y-coord
pos = [blx-0.019 bly-0.019 width+0.038 height+0.034];
hold off
subplot('position',pos);
newplot
set(gca, 'Projection','perspective');
x = [-1 1;-1 1];
y = [1 1;-1 -1];
z = [0 0;0 0];
slice2 = ceil((theta+1)*34/181);
for ii = 1:slice2
dumIm1 = radon(myIm(:,:,ii),0:180);
dumIm2 = iradon(dumIm1,0:180);
dumIm3 = dumIm2;
dumIm3(dumIm2 <=50) = NaN;
hhh = surf(x,y,z+ii*10,dumIm3,'FaceColor','texturemap',...
'EdgeColor','none');
rotate(hhh,[0 0 1],theta*2+144.1,[0,0,0]);
hold on
hhh.AlphaData =(dumIm3>40);
hhh.FaceAlpha = 'texturemap';
% Add a dummy line to stop resizing of viewed volume
% with skull rotation angle
dumLine = plot3([-1. 1.],[0 0],[0 0],'Color','w');
dumLine.Color(4) = 0.0; % alpha = 0; fully transparent
end
xlim([-1 1]);
ylim([-1 1]);
zlim([-10 350]);
axis square
axis off
colormap(gray)
end
end
end
frame = getframe(gcf);
writeVideo(vid,frame);
hold off
end
% Output the movie as an mpg file
close(vid);