| |
1 #################################################################### |
| |
2 # Predictive online PDPS for optical flow with known velocity field |
| |
3 #################################################################### |
| |
4 |
| |
5 __precompile__() |
| |
6 |
| |
7 module AlgorithmPrimalOnly |
| |
8 |
| |
9 identifier = "pdps_known_primalonly" |
| |
10 |
| |
11 using Printf |
| |
12 |
| |
13 using AlgTools.Util |
| |
14 import AlgTools.Iterate |
| |
15 using ImageTools.Gradient |
| |
16 using ImageTools.Translate |
| |
17 |
| |
18 using ..Radon |
| |
19 using ImageTransformations |
| |
20 using Images, CoordinateTransformations, Rotations, OffsetArrays |
| |
21 using ImageCore, Interpolations |
| |
22 |
| |
23 using ..OpticalFlow: ImageSize, |
| |
24 Image, |
| |
25 petpdflow! |
| |
26 |
| |
27 ######################### |
| |
28 # Iterate initialisation |
| |
29 ######################### |
| |
30 |
| |
31 function init_rest(x::Image) |
| |
32 imdim=size(x) |
| |
33 y = zeros(2, imdim...) |
| |
34 Δx = copy(x) |
| |
35 Δy = copy(y) |
| |
36 x̄ = copy(x) |
| |
37 radonx = copy(x) |
| |
38 return x, y, Δx, Δy, x̄, radonx |
| |
39 end |
| |
40 |
| |
41 function init_iterates(xinit::Image) |
| |
42 return init_rest(copy(xinit)) |
| |
43 end |
| |
44 |
| |
45 function init_iterates(dim::ImageSize) |
| |
46 return init_rest(zeros(dim...)) |
| |
47 end |
| |
48 |
| |
49 ######################### |
| |
50 # PETscan related |
| |
51 ######################### |
| |
52 function petvalue(x, b, c) |
| |
53 tmp = similar(b) |
| |
54 radon!(tmp, x) |
| |
55 return sum(@. tmp - b*log(tmp+c)) |
| |
56 end |
| |
57 |
| |
58 function petgrad!(res, x, b, c, S) |
| |
59 tmp = similar(b) |
| |
60 radon!(tmp, x) |
| |
61 @. tmp = S .- b/(tmp+c) |
| |
62 backproject!(res, S.*tmp) |
| |
63 end |
| |
64 |
| |
65 function proj_nonneg!(y) |
| |
66 @inbounds @simd for i=1:length(y) |
| |
67 if y[i] < 0 |
| |
68 y[i] = 0 |
| |
69 end |
| |
70 end |
| |
71 return y |
| |
72 end |
| |
73 |
| |
74 ############ |
| |
75 # Algorithm |
| |
76 ############ |
| |
77 |
| |
78 function solve( :: Type{DisplacementT}; |
| |
79 dim :: ImageSize, |
| |
80 iterate = AlgTools.simple_iterate, |
| |
81 params::NamedTuple) where DisplacementT |
| |
82 |
| |
83 ################################ |
| |
84 # Extract and set up parameters |
| |
85 ################################ |
| |
86 α, ρ = params.α, params.ρ |
| |
87 R_K² = ∇₂_norm₂₂_est² |
| |
88 γ = 1 |
| |
89 L = params.L |
| |
90 τ₀, σ₀ = params.τ₀, params.σ₀ |
| |
91 τ = τ₀/L |
| |
92 σ = σ₀*(1-τ₀)/(R_K²*τ) |
| |
93 |
| |
94 println("Step length parameters: τ=$(τ), σ=$(σ)") |
| |
95 |
| |
96 λ = params.λ |
| |
97 c = params.c*ones(params.radondims...) |
| |
98 |
| |
99 |
| |
100 ###################### |
| |
101 # Initialise iterates |
| |
102 ###################### |
| |
103 |
| |
104 x, y, Δx, Δy, x̄, r∇ = init_iterates(dim) |
| |
105 |
| |
106 if params.L_experiment |
| |
107 oldpetgradx = zeros(size(x)...) |
| |
108 petgradx = zeros(size(x)) |
| |
109 oldx = ones(size(x)) |
| |
110 end |
| |
111 |
| |
112 #################### |
| |
113 # Run the algorithm |
| |
114 #################### |
| |
115 |
| |
116 v = iterate(params) do verbose :: Function, |
| |
117 b :: Image, # noisy_sinogram |
| |
118 v_known :: DisplacementT, |
| |
119 theta_known :: DisplacementT, |
| |
120 b_true :: Image, |
| |
121 S :: Image |
| |
122 |
| |
123 ################### |
| |
124 # Prediction steps |
| |
125 ################### |
| |
126 |
| |
127 petpdflow!(x, Δx, y, Δy, v_known, theta_known, false) |
| |
128 |
| |
129 if params.L_experiment |
| |
130 @. oldx = x |
| |
131 end |
| |
132 |
| |
133 ############ |
| |
134 # PDPS step |
| |
135 ############ |
| |
136 |
| |
137 ∇₂ᵀ!(Δx, y) # primal step: |
| |
138 @. x̄ = x # | save old x for over-relax |
| |
139 petgrad!(r∇, x, b, c, S) # | Calculate gradient of fidelity term |
| |
140 |
| |
141 @. x = x-(τ*λ)*r∇-τ*Δx # | |
| |
142 proj_nonneg!(x) # | non-negativity constaint prox |
| |
143 @. x̄ = 2x - x̄ # over-relax: x̄ = 2x-x_old |
| |
144 ∇₂!(Δy, x̄) # dual step: |
| |
145 @. y = y + σ*Δy # | |
| |
146 proj_norm₂₁ball!(y, α) # | prox |
| |
147 |
| |
148 ##################### |
| |
149 # L update if needed |
| |
150 ##################### |
| |
151 if params.L_experiment |
| |
152 petgrad!(petgradx, x, b, c, S) |
| |
153 petgrad!(oldpetgradx, oldx, b, c, S) |
| |
154 if norm₂(x-oldx)>1e-12 |
| |
155 L = max(0.9*norm₂(petgradx - oldpetgradx)/norm₂(x-oldx),L) |
| |
156 end |
| |
157 println("Step length parameters: L=$(L)") |
| |
158 τ = τ₀/L |
| |
159 σ = σ₀*(1-τ₀)/(R_K²*τ) |
| |
160 end |
| |
161 |
| |
162 ################################ |
| |
163 # Give function value if needed |
| |
164 ################################ |
| |
165 |
| |
166 v = verbose() do |
| |
167 ∇₂!(Δy, x) |
| |
168 value = λ*petvalue(x, b, c) + params.α*norm₂₁(Δy) |
| |
169 value, x, [NaN, NaN], nothing |
| |
170 end |
| |
171 |
| |
172 v |
| |
173 end |
| |
174 |
| |
175 return x, y, v |
| |
176 end |
| |
177 |
| |
178 end # Module |
| |
179 |
| |
180 |