|
1 ######################################################## |
|
2 # TV reconstruction via primal–dual proximal splitting |
|
3 ######################################################## |
|
4 |
|
5 __precompile__() |
|
6 |
|
7 module TVRecon |
|
8 |
|
9 using AlgTools.Util |
|
10 using AlgTools.LinOps |
|
11 import AlgTools.Iterate |
|
12 using ImageTools.Gradient |
|
13 |
|
14 ############## |
|
15 # Our exports |
|
16 ############## |
|
17 |
|
18 export recon_pdps |
|
19 |
|
20 ############# |
|
21 # Data types |
|
22 ############# |
|
23 |
|
24 ImageSize = Tuple{Integer,Integer} |
|
25 Image = Array{Float64,2} |
|
26 Primal = Image |
|
27 Dual = Array{Float64,3} |
|
28 |
|
29 ######################### |
|
30 # Iterate initialisation |
|
31 ######################### |
|
32 |
|
33 function init_rest(x::Primal, b::Array{Float64, N}) where N |
|
34 imdim=size(x) |
|
35 datadim=size(b) |
|
36 |
|
37 y = zeros(2, imdim...) |
|
38 λ = zeros(datadim...) |
|
39 Δx₁ = copy(x) |
|
40 Δx₂ = copy(x) |
|
41 Δy = copy(y) |
|
42 Δλ = copy(λ) |
|
43 x̄ = copy(x) |
|
44 |
|
45 return x, y, λ, Δx₁, Δx₂, Δy, Δλ, x̄ |
|
46 end |
|
47 |
|
48 function init_primal(xinit::Image) |
|
49 return copy(xinit) |
|
50 end |
|
51 |
|
52 ############ |
|
53 # Algorithm |
|
54 ############ |
|
55 |
|
56 function recon_pdps(b :: Data, op :: LinOp{Image, Data}; |
|
57 xinit :: Union{Image, Nothing} = nothing, |
|
58 iterate = Iterate.simple_iterate, |
|
59 params::NamedTuple) where Data |
|
60 |
|
61 ################################ |
|
62 # Extract and set up parameters |
|
63 ################################ |
|
64 |
|
65 α, ρ = params.α, params.ρ |
|
66 τ₀, σ₀ = params.τ₀, params.σ₀ |
|
67 |
|
68 R_K = √(∇₂_norm₂₂_est^2+opnorm_estimate(op)^2) |
|
69 γ = 1 |
|
70 |
|
71 @assert(τ₀*σ₀ < 1) |
|
72 σ = σ₀/R_K |
|
73 τ = τ₀/R_K |
|
74 |
|
75 ###################### |
|
76 # Initialise iterates |
|
77 ###################### |
|
78 |
|
79 x, y, λ, Δx₁, Δx₂, Δy, Δλ, x̄ = init_rest(copy(xinit), b) |
|
80 |
|
81 #################### |
|
82 # Run the algorithm |
|
83 #################### |
|
84 |
|
85 v = iterate(params) do verbose :: Function |
|
86 ω = params.accel ? 1/√(1+2*γ*τ) : 1 |
|
87 |
|
88 ∇₂ᵀ!(Δx₁, y) # primal step: x |
|
89 inplace!(Δx₂, op', λ) # | |
|
90 @. x̄ = x # | |
|
91 @. x = x-τ*(Δx₁+Δx₂) # | |
|
92 @. x̄ = (1+ω)*x - ω*x̄ # over-relax: x̄ = 2x-x_old |
|
93 ∇₂!(Δy, x̄) # dual step: y, λ |
|
94 inplace!(Δλ, op, x̄) # | |
|
95 @. y = (y + σ*Δy)/(1 + σ*ρ/α) # | |
|
96 proj_norm₂₁ball!(y, α) # | |
|
97 @. λ = (λ + σ*(Δλ-b))/(1 + σ) # | |
|
98 |
|
99 if params.accel |
|
100 τ, σ = τ*ω, σ/ω |
|
101 end |
|
102 |
|
103 ################################ |
|
104 # Give function value if needed |
|
105 ################################ |
|
106 v = verbose() do |
|
107 ∇₂!(Δy, x) |
|
108 inplace!(Δλ, op, x) |
|
109 value = norm₂²(Δλ-b)/2 + params.α*γnorm₂₁(Δy, params.ρ) |
|
110 value, x |
|
111 end |
|
112 |
|
113 v |
|
114 end |
|
115 |
|
116 return x, y, v |
|
117 end |
|
118 |
|
119 end # Module |
|
120 |
|
121 |