Sun, 21 Apr 2024 18:55:00 +0300
clarified sino_sparsity
| 16 | 1 | #################################################################### |
| 2 | # Predictive online PDPS for optical flow with known velocity field | |
| 3 | #################################################################### | |
| 4 | ||
| 5 | __precompile__() | |
| 6 | ||
| 7 | module AlgorithmZeroDual | |
| 8 | ||
| 9 | identifier = "pdps_known_zerodual" | |
| 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 | y .= zeros(size(y)...) | |
| 129 | ||
| 130 | if params.L_experiment | |
| 131 | @. oldx = x | |
| 132 | end | |
| 133 | ||
| 134 | ############ | |
| 135 | # PDPS step | |
| 136 | ############ | |
| 137 | ||
| 138 | ∇₂ᵀ!(Δx, y) # primal step: | |
| 139 | @. x̄ = x # | save old x for over-relax | |
| 140 | petgrad!(r∇, x, b, c, S) # | Calculate gradient of fidelity term | |
| 141 | ||
| 142 | @. x = x-(τ*λ)*r∇-τ*Δx # | | |
| 143 | proj_nonneg!(x) # | non-negativity constaint prox | |
| 144 | @. x̄ = 2x - x̄ # over-relax: x̄ = 2x-x_old | |
| 145 | ∇₂!(Δy, x̄) # dual step: | |
| 146 | @. y = y + σ*Δy # | | |
| 147 | proj_norm₂₁ball!(y, α) # | prox | |
| 148 | ||
| 149 | ##################### | |
| 150 | # L update if needed | |
| 151 | ##################### | |
| 152 | if params.L_experiment | |
| 153 | petgrad!(petgradx, x, b, c, S) | |
| 154 | petgrad!(oldpetgradx, oldx, b, c, S) | |
| 155 | if norm₂(x-oldx)>1e-12 | |
| 156 | L = max(0.9*norm₂(petgradx - oldpetgradx)/norm₂(x-oldx),L) | |
| 157 | println("Step length parameters: L=$(L)") | |
| 158 | τ = τ₀/L | |
| 159 | σ = σ₀*(1-τ₀)/(R_K²*τ) | |
| 160 | end | |
| 161 | end | |
| 162 | ||
| 163 | ################################ | |
| 164 | # Give function value if needed | |
| 165 | ################################ | |
| 166 | ||
| 167 | v = verbose() do | |
| 168 | ∇₂!(Δy, x) | |
| 169 | value = λ*petvalue(x, b, c) + params.α*norm₂₁(Δy) | |
| 170 | value, x, [NaN, NaN], nothing, τ, σ | |
| 171 | end | |
| 172 | ||
| 173 | v | |
| 174 | end | |
| 175 | ||
| 176 | return x, y, v | |
| 177 | end | |
| 178 | ||
| 179 | end # Module | |
| 180 | ||
| 181 |