Add TV reconstruction code for abstract linear operators

Fri, 08 Jan 2021 00:34:47 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Fri, 08 Jan 2021 00:34:47 -0500
changeset 47
b32ced049cbd
parent 46
46053b3af251
child 48
1b9e90ca81e3

Add TV reconstruction code for abstract linear operators

Manifest.toml file | annotate | diff | comparison | revisions
src/ImageTools.jl file | annotate | diff | comparison | revisions
src/TVRecon.jl file | annotate | diff | comparison | revisions
--- a/Manifest.toml	Thu Jan 07 17:52:42 2021 -0500
+++ b/Manifest.toml	Fri Jan 08 00:34:47 2021 -0500
@@ -181,10 +181,10 @@
 version = "1.0.2"
 
 [[MbedTLS_jll]]
-deps = ["Libdl", "Pkg"]
-git-tree-sha1 = "c0b1286883cac4e2b617539de41111e0776d02e8"
+deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
+git-tree-sha1 = "0eef589dd1c26a3ac9d753fe1a8bcad63f956fa6"
 uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
-version = "2.16.8+0"
+version = "2.16.8+1"
 
 [[Missings]]
 deps = ["DataAPI"]
--- a/src/ImageTools.jl	Thu Jan 07 17:52:42 2021 -0500
+++ b/src/ImageTools.jl	Fri Jan 08 00:34:47 2021 -0500
@@ -9,6 +9,7 @@
 include("Denoise.jl")
 include("Visualise.jl")
 include("ImFilter.jl")
+include("TVRecon.jl")
 
 end # module
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/TVRecon.jl	Fri Jan 08 00:34:47 2021 -0500
@@ -0,0 +1,121 @@
+########################################################
+# TV reconstruction via primal–dual proximal splitting
+########################################################
+
+__precompile__()
+
+module TVRecon
+
+using AlgTools.Util
+using AlgTools.LinOps
+import AlgTools.Iterate
+using ImageTools.Gradient
+
+##############
+# Our exports
+##############
+
+export recon_pdps
+
+#############
+# Data types
+#############
+
+ImageSize = Tuple{Integer,Integer}
+Image = Array{Float64,2}
+Primal = Image
+Dual = Array{Float64,3}
+
+#########################
+# Iterate initialisation
+#########################
+
+function init_rest(x::Primal, b::Array{Float64, N}) where N
+    imdim=size(x)
+    datadim=size(b)
+
+    y = zeros(2, imdim...)
+    λ = zeros(datadim...)
+    Δx₁ = copy(x)
+    Δx₂ = copy(x)
+    Δy = copy(y)
+    Δλ = copy(λ)
+    x̄ = copy(x)
+
+    return x, y, λ, Δx₁, Δx₂, Δy, Δλ, x̄
+end
+
+function init_primal(xinit::Image)
+    return copy(xinit)
+end
+
+############
+# Algorithm
+############
+
+function recon_pdps(b :: Data, op :: LinOp{Image, Data};
+                    xinit :: Union{Image, Nothing} = nothing,
+                    iterate = Iterate.simple_iterate,
+                    params::NamedTuple) where Data
+
+    ################################
+    # Extract and set up parameters
+    ################################
+
+    α, ρ = params.α, params.ρ
+    τ₀, σ₀ =  params.τ₀, params.σ₀
+
+    R_K = √(∇₂_norm₂₂_est^2+opnorm_estimate(op)^2)
+    γ = 1
+
+    @assert(τ₀*σ₀ < 1)
+    σ = σ₀/R_K
+    τ = τ₀/R_K
+    
+    ######################
+    # Initialise iterates
+    ######################
+
+    x, y, λ, Δx₁, Δx₂, Δy, Δλ, x̄ = init_rest(copy(xinit), b)
+
+    ####################
+    # Run the algorithm
+    ####################
+
+    v = iterate(params) do verbose :: Function
+        ω = params.accel ? 1/√(1+2*γ*τ) : 1
+        
+        ∇₂ᵀ!(Δx₁, y)                      # primal step: x
+        inplace!(Δx₂, op', λ)             # |
+        @. x̄ = x                          # |
+        @. x = x-τ*(Δx₁+Δx₂)              # |
+        @. x̄ = (1+ω)*x - ω*x̄              # over-relax: x̄ = 2x-x_old
+        ∇₂!(Δy, x̄)                        # dual step: y, λ
+        inplace!(Δλ, op, x̄)               # |
+        @. y = (y + σ*Δy)/(1 + σ*ρ/α)     # |
+        proj_norm₂₁ball!(y, α)            # |
+        @. λ = (λ + σ*(Δλ-b))/(1 + σ)     # |
+
+        if params.accel
+            τ, σ = τ*ω, σ/ω
+        end
+                
+        ################################
+        # Give function value if needed
+        ################################
+        v = verbose() do
+            ∇₂!(Δy, x)
+            inplace!(Δλ, op, x)
+            value = norm₂²(Δλ-b)/2 + params.α*γnorm₂₁(Δy, params.ρ)
+            value, x
+        end
+
+        v
+    end
+
+    return x, y, v
+end
+
+end # Module
+
+

mercurial