|
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 |