Skip to content

Commit 5426d6b

Browse files
authored
Inverse radon (#2)
pixel-driven inverse radon transform
1 parent 82531b2 commit 5426d6b

File tree

3 files changed

+68
-17
lines changed

3 files changed

+68
-17
lines changed

Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ name = "ImageReconstruction"
22
uuid = "d5d0ac58-a118-45a5-925e-339d09fa0c5f"
33
version = "0.1.0"
44

5+
[deps]
6+
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
7+
58
[compat]
69
julia = "1"
710

docs/make.jl

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
using Documenter, ImageReconstruction
22

33
makedocs(;
4-
modules=[ImageReconstruction],
5-
format=Documenter.HTML(),
6-
pages=[
7-
"Home" => "index.md",
8-
],
9-
repo="https://github.com/kczimm/ImageReconstruction.jl/blob/{commit}{path}#L{line}",
10-
sitename="ImageReconstruction.jl",
11-
authors="Kevin C. Zimmerman",
12-
assets=String[],
4+
modules = [ImageReconstruction],
5+
format = Documenter.HTML(),
6+
pages = ["Home" => "index.md"],
7+
repo = "https://github.com/JuliaImages/ImageReconstruction.jl/blob/{commit}{path}#L{line}",
8+
sitename = "ImageReconstruction.jl",
9+
assets = String[],
1310
)
1411

15-
deploydocs(;
16-
repo="github.com/kczimm/ImageReconstruction.jl",
17-
)
12+
deploydocs(; repo = "github.com/JuliaImages/ImageReconstruction.jl")

src/ImageReconstruction.jl

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
module ImageReconstruction
22

3+
using FFTW
4+
35
export radon, iradon
46

57
"""
68
radon transform
79
810
https://en.wikipedia.org/wiki/Radon_transform
911
"""
10-
radon
12+
function radon end
1113

1214
"""
1315
inverse radon transform
1416
1517
https://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
4547
end
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+
47100
end # module

0 commit comments

Comments
 (0)