src/AlgorithmBothMulti.jl.orig

changeset 0
a55e35d20336
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/AlgorithmBothMulti.jl.orig	Tue Apr 07 14:19:48 2020 -0500
@@ -0,0 +1,277 @@
+######################################################################
+# Predictive online PDPS for optical flow with unknown velocity field
+######################################################################
+
+__precompile__()
+
+module AlgorithmBothMulti
+
+using Printf
+
+using AlgTools.Util
+import AlgTools.Iterate
+using ImageTools.Gradient
+using ImageTools.ImFilter
+
+using ..OpticalFlow: Image,
+                     ImageSize,
+                     DisplacementConstant,
+                     pdflow!,
+                     horn_schunck_reg_prox!,
+                     pointwise_gradiprod_2d!,
+                     horn_schunck_reg_prox_op!,
+                     mldivide_step_plus_sym2x2!,
+                     ConstantDisplacementHornSchunckData,
+                     filter_hs
+
+using ..Algorithm: step_lengths
+
+#########################
+# Iterate initialisation
+#########################
+
+function init_displ(xinit::Image, ::Type{DisplacementConstant}, n::Integer)
+    return xinit, zeros(n, 2)
+end
+
+# function init_displ(xinit::Image, ::Type{DisplacementFull}, n::Integer)
+#     return xinit, zeros(n, 2, size(xinit)...)
+# end
+
+function init_rest(x::Image, u::DisplacementT) where DisplacementT
+    imdim=size(x)
+
+    y = zeros(2, imdim...)
+    Δx = copy(x)
+    Δy = copy(y)
+    x̄ = copy(x)
+
+    return x, y, Δx, Δy, x̄, u
+end
+
+function init_iterates( :: Type{DisplacementT},
+                       xinit::Image,
+                       n::Integer) where DisplacementT    
+    return init_rest(init_displ(copy(xinit), DisplacementT, n)...)
+end
+
+function init_iterates( :: Type{DisplacementT},
+                       dim::ImageSize,
+                       n::Integer) where DisplacementT
+    return init_rest(init_displ(zeros(dim...), DisplacementT, n)...)
+end
+
+############
+# Algorithm
+############
+
+function solve( :: Type{DisplacementT};
+               dim :: ImageSize,
+               iterate = AlgTools.simple_iterate, 
+               params::NamedTuple) where DisplacementT
+
+    ######################
+    # Initialise iterates
+    ######################
+
+    n = params.displacement_count
+    k = 0 # number of displacements we have already
+
+    x, y, Δx, Δy, x̄, u = init_iterates(DisplacementT, dim, n)
+    init_data = (params.init == :data)
+    hs = [ConstantDisplacementHornSchunckData() for i=1:n]
+    #hs = Array{ConstantDisplacementHornSchunckData}(undef, n)
+    A = Array{Float64,3}(undef, n, 2, 2)
+    d = Array{Float64,2}(undef, n, 2)
+
+    # … for tracking cumulative movement
+    ucumulbase = [0.0, 0.0]
+    
+    #############################################
+    # Extract parameters and set up step lengths
+    #############################################
+
+    α, ρ, λ, θ = params.α, params.ρ, params.λ, params.θ
+    R_K² = ∇₂_norm₂₂_est²
+    γ = 1
+    τ, σ, σ̃, ρ̃ = step_lengths(params, γ, R_K²)
+
+    kernel = params.kernel
+    T = params.timestep 
+
+    ####################
+    # Run the algorithm
+    ####################
+
+    b_next_filt = nothing
+    diffu = similar(u[1, :])
+
+    v = iterate(params) do verbose :: Function,
+                           b :: Image,
+                           🚫unused_v_known :: DisplacementT,
+                           b_next :: Image
+
+        ####################################
+        # Smooth data for Horn–Schunck term
+        ####################################
+
+        b_filt, b_next_filt = filter_hs(b, b_next, b_next_filt, kernel)
+
+        ################################################
+        # Prediction step
+        ################################################
+
+        # Predict x and y
+        if k==0
+            if init_data
+                x .= b
+                init_data = false
+            end 
+        else
+            # Displacement from previous to this image is estimated as
+            # the difference of their displacements from beginning of window.
+            if k>1
+                @. @views diffu = u[k, :] - u[k-1, :]
+            else
+                @. @views diffu = u[k, :]
+            end
+
+            pdflow!(x, Δx, y, Δy, diffu, params.dual_flow)
+        end
+
+        # Shift stored prox matrices
+        if k==n
+            tmp = copy(u[1, :])
+            ucumulbase .+= tmp
+            for j=1:(n-1)
+                @. @views u[j, :] = u[j+1, :] - tmp
+                hs[j] = hs[j+1]
+            end
+            # Create new struct as original contains references to objects that
+            # have been moved to index n-1.
+            hs[n]=ConstantDisplacementHornSchunckData()
+        else
+            k += 1
+        end
+
+        # Predict u: zero displacement from current to next image, i.e.,
+        # same displacement to beginning of window.
+        if k==1        
+            @. @views u[k, :] = 0.0
+        else
+            @. @views u[k, :] = u[k-1, :]
+        end
+
+        # Predictor proximals tep
+        if params.prox_predict
+            ∇₂!(Δy, x) 
+            @. y = (y + σ̃*Δy)/(1 + σ̃*(ρ̃+ρ/α))
+            proj_norm₂₁ball!(y, α) 
+        end
+
+        #################################################################################
+        # PDPS step
+        #
+        # For the displacements, with τ̃=τ/k, we need to solve for 2≤j<k,
+        #
+        # (1) (I/τ̃+M₀^j+M₀^{j+1})u^j = M₀^ju^{j-1} + M₀^{j+1}u^{j+1}
+        #                              + ũ^j/τ̃ - z^j + z^{j+1}, 
+        #
+        # as well as
+        #
+        # (2) (I/τ̃+M₀^k)u^k = M₀^k u^{k-1} + ũ^k/τ̃ - z^k
+        #
+        # and
+        #
+        # (3) (I/τ̃+M₀^1+M₀^2)u^1 = 0 + M₀^{2}u^{2} + ũ^1/τ̃ - z^1 + z^{2}
+        #
+        # We first construct from (2) that
+        #
+        #     u^k = A^k u^{k-1} + d^k
+        #
+        # for
+        #
+        #     A^k := (I/τ̃+M₀^k)^{-1} M₀^k
+        #     d_k := (I/τ̃+M₀^k)^{-1} (ũ^k/τ̃ - z^k).
+        #
+        # Inserting this into (1) we need
+        #
+        # (4)  (I/τ̃+M₀^j+M₀^{j+1}(I-A^{j+1}))u^j = M₀^ju^{j-1} + M₀^{j+1}d^{j+1}
+        #                                          + ũ^j/τ̃ - z^j + z^{j+1}.
+        # 
+        # This is well-defined because A^{j+1} < I. It also has the same form as (1), so 
+        # we continue with
+        #
+        # (5)   u^j = A^j u^{j-1} + d^j
+        #
+        # for
+        #
+        #      A^j := (I/τ̃+M₀^j+M₀^{j+1}(I-A^{j+1}))^{-1} M₀^j
+        #      d^j := (I/τ̃+M₀^j+M₀^{j+1}(I-A^{j+1}))^{-1}
+        #               (M₀^{j+1}d^{j+1} + ũ^j/τ̃ - z^j + z^{j+1})
+        # 
+        # Finally from (3) with these we need
+        #
+        #      (I/τ̃+M₀^1+M₀^2(I-A^2))u^1 = M₀^2d^2 + ũ^1/τ̃ - z^1 + z^2,
+        #
+        # which is of the same form as (4) with u^0=0, so by (5) u^1=d^1.
+        #
+        #################################################################################
+
+        ∇₂ᵀ!(Δx, y)                         # primal step:
+        @. x̄ = x                            # |  save old x for over-relax
+        @. x = (x-τ*(Δx-b))/(1+τ)           # |  prox
+                                            # |  | for displacement
+        # Calculate matrices for latest data; rest is stored. 
+        @views begin
+            horn_schunck_reg_prox_op!(hs[k], b_next_filt, b_filt, θ, λ, T)
+
+            τ̃=τ/k
+
+            B = hs[k].M₀
+            c = u[k, :]./τ̃-hs[k].z
+            mldivide_step_plus_sym2x2!(A[k, :, :], B, B, τ̃)
+            mldivide_step_plus_sym2x2!(d[k, :], B, c, τ̃)
+
+            for j=(k-1):-1:1
+                B = hs[j].M₀+hs[j+1].M₀*([1 0; 0 1]-A[j+1, :, :])
+                c = hs[j+1].M₀*d[j+1, :]+u[j, :]./τ̃-hs[j].z+hs[j+1].z
+                mldivide_step_plus_sym2x2!(A[j, :, :], B, hs[j].M₀, τ̃)
+                mldivide_step_plus_sym2x2!(d[j, :], B, c, τ̃)
+            end
+
+            u[1, :] .= d[1, :]
+            for j=2:k
+                u[j, :] .= A[j, :, :]*u[j-1, :] + d[j, :]
+            end
+        end
+
+        @. x̄ = 2x - x̄                       # over-relax: x̄ = 2x-x_old
+        ∇₂!(Δy, x̄)                          # dual step: y
+        @. y = (y + σ*Δy)/(1 + σ*ρ/α)       # |
+        proj_norm₂₁ball!(y, α)              # |  prox
+
+        ########################################################
+        # Give function value and cumulative movement if needed
+        ########################################################
+        v = verbose() do
+            ∇₂!(Δy, x)
+            hs_plus_reg=0            
+            for j=1:k
+                v=(j==1 ? u[j, :] : u[j, :]-u[j-1, :])                
+                hs_plus_reg += hs[j].cv/2 + dot(hs[j].Mv*v, v)/2+dot(hs[j].av, v)
+            end
+            value = (norm₂²(b-x)/2 + hs_plus_reg/k + α*γnorm₂₁(Δy, ρ))
+
+            value, x, u[k, :]+ucumulbase, u[1:k,:].+ucumulbase'
+        end
+
+        return v
+    end
+
+    return x, y, v
+end
+
+end # Module
+
+

mercurial