11module ImageReconstruction
22
3+ using FFTW
4+
35export radon, iradon
46
57"""
68radon transform
79
810https://en.wikipedia.org/wiki/Radon_transform
911"""
10- radon
12+ function radon end
1113
1214"""
1315inverse radon transform
1416
1517https://en.wikipedia.org/wiki/Radon_transform
1618"""
17- iradon
19+ function iradon end
1820
1921
2022"""
@@ -24,24 +26,75 @@ function radon(image::AbstractMatrix, θ::AbstractRange, t::AbstractRange)
2426 P = zeros (eltype (image), length (t), length (θ))
2527 nr, nc = size (image)
2628
27- for i = 1 : nr, j = 1 : nc
29+ for i in 1 : nr, j in 1 : nc
2830 x = j - nc / 2 + 0.5
2931 y = i - nr / 2 + 0.5
3032 @inbounds for (k, θₖ) in enumerate (θ)
3133 t′ = x * cos (θₖ) + y * sin (θₖ)
3234
33- a = convert (Int, round ((t′ - t . start ) / step (t) + 1 ))
35+ a = convert (Int, round ((t′ - minimum (t) ) / step (t) + 1 ))
3436
3537 (a < 1 || a > length (t)) && continue
3638 α = abs (t′ - t[a])
3739 P[a, k] += (1 - α) * image[i, j]
3840
3941 (a > length (t) + 1 ) && continue
40- P[a+ 1 , k] += α * image[i, j]
42+ P[a + 1 , k] += α * image[i, j]
4143 end
4244 end
4345
4446 P
4547end
4648
49+ function _ramp_spatial (N:: Int , τ)
50+ h = zeros (N)
51+ N2 = N ÷ 2
52+ for i in eachindex (h)
53+ n = i - N2 - 1
54+ if mod (n, 2 ) != 0
55+ h[i] = - 1 / (π * n * τ)^ 2
56+ elseif n == 0
57+ h[i] = 1 / (4 * τ^ 2 )
58+ end
59+ end
60+ h
61+ end
62+
63+ _zero_pad (p:: AbstractVector , N:: Int ) = vcat (p, zeros (N))
64+
65+ """
66+ Inverse radon transform using a ramp filter and a pixel-driven algorithm.
67+ """
68+ function iradon (sinogram:: AbstractMatrix , θ:: AbstractRange , t:: AbstractRange )
69+ pixels = 128
70+
71+ N = length (t)
72+ K = length (θ)
73+ Npad = nextpow (2 , 2 * N - 1 )
74+ τ = step (t)
75+ ramp = fft (_zero_pad (_ramp_spatial (N, τ), Npad - N))
76+ i = div (N, 2 ) + 1
77+ j = i + N - 1
78+
79+ image = zeros (eltype (sinogram), pixels, pixels)
80+ Q = Vector {eltype(sinogram)} (undef, N)
81+ for (k, θₖ) in enumerate (θ)
82+ # filter projection
83+ Q[:] .= τ .* real .(ifft (fft (_zero_pad (sinogram[:, k], Npad - N)) .* ramp)[i: j])
84+
85+ # backproject
86+ for c in CartesianIndices (image)
87+ x = c. I[2 ] - pixels ÷ 2 + 0.5
88+ y = c. I[1 ] - pixels ÷ 2 + 0.5
89+ t′ = x * cos (θₖ) + y * sin (θₖ)
90+ # linear interpolation
91+ # image pixel (x, y) at θₖ is projected on t[z] and t[z+1]
92+ z = convert (Int, round ((t′ - minimum (t)) / step (t) + 1 ))
93+ α = abs (t′ - t[z])
94+ image[c] += (1 - α) * Q[z] + α * Q[z + 1 ]
95+ end
96+ end
97+ @. image * π / K
98+ end
99+
47100end # module
0 commit comments