-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathfiltBackProject.m
More file actions
75 lines (63 loc) · 2.59 KB
/
filtBackProject.m
File metadata and controls
75 lines (63 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
function out = filtBackProject( sino, sImg, varargin )
% out = filtBackProject( sino, sImg [, 'detCenter', detCenter, 'dProjAngle', dProjAngle, ...
% 'dSize', dSize, 'projAngles', projAngles ] )
%
% Inputs:
% sino - a parallel beam sinogram with one column per detector and one row per projection
% sImg - the size of the output image
%
% Optional Inputs:
% detCenter - the location of the center detector (defaults to center of projection)
% Note, for optical projection tomography, this is a component of the principal point
% dProjAngle - the angle between adjacent rotation angles
% Either dAngle or projAngles must be supplied
% dSize - the size of each detector. (More specifically, the spacing between detectors.)
% projAngles - the angle of the principal ray for each projection
% Either dAngle or projAngles must be supplied
%
% Written by Nicholas Dwork, Copyright 2025
%
% This software is offered under the GNU General Public License 3.0. It
% is offered without any warranty expressed or implied, including the
% implied warranties of merchantability or fitness for a particular
% purpose.
% TODO: Density compensation may be beneficial
p = inputParser;
p.addParameter( 'detCenter', [] );
p.addParameter( 'dProjAngle', [] );
p.addParameter( 'dSize', 1, @ispositive );
p.addParameter( 'projAngles', [] );
p.parse( varargin{:} );
detCenter = p.Results.detCenter;
dProjAngle = p.Results.dProjAngle;
dSize = p.Results.dSize;
projAngles = p.Results.projAngles;
if numel( dProjAngle ) == 0 && numel( projAngles ) == 0
error( 'Either dProjAngle or projAngles must be provided.' );
end
nDetectors = size( sino, 1 );
nProjections = size( sino, 2 );
if numel( projAngles ) == 0
projAngles = dProjAngle * ( 0 : nProjections-1 );
end
if numel( detCenter ) == 0
n = size2imgCoordinates( nDetectors );
else
n = ( (0:nDetectors-1) - detCenter );
end
h = zeros( numel(n), 1 );
oddNs = find( mod(n,2)~=0 );
h(oddNs) = -1 ./ ( n(oddNs).*n(oddNs) * pi*pi * dSize*dSize );
h( n==0 ) = 1 / ( 4 * dSize*dSize );
nPadded = 2 * nDetectors;
hZP = padData( h, nPadded );
fftHZP = fft( ifftshift( hZP ) );
fftHZP = fftHZP * ones( 1, nProjections );
sinoZP = padData( sino, [ nPadded, nProjections ] );
fftSino = fft( ifftshift( sinoZP, 1 ), [], 1 );
fftFiltSino = fftHZP .* fftSino;
filtSino = dSize * fftshift( ifft( fftFiltSino, [], 1 ), 1 );
filtSino = cropData( filtSino, [ nDetectors, nProjections ] );
out = backProject( filtSino, projAngles, sImg );
out = out * pi / nProjections;
end