Problem & API
Problem Definition
Use TVProblem to define a denoising/reconstruction task:
problem = TotalVariationImageFiltering.TVProblem(
f;
lambda,
spacing = nothing,
data_fidelity = TotalVariationImageFiltering.L2Fidelity(),
tv_mode = TotalVariationImageFiltering.IsotropicTV(),
boundary = TotalVariationImageFiltering.Neumann(),
constraint = TotalVariationImageFiltering.NoConstraint(),
)Key inputs:
f:AbstractArray{<:AbstractFloat,N}data.lambda: TV weight (>= 0).spacing:nothing, scalar,NTuple{N}, or length-Nvector.data_fidelity:L2Fidelity()orPoissonFidelity().tv_mode:IsotropicTV(),AnisotropicTV(), orGroupSparseTV(...).boundary:Neumann()orPeriodic().constraint:NoConstraint(),NonnegativeConstraint(), orBoxConstraint(lower, upper).
TVProblem is immutable, but it stores f by reference. For repeated solves with the same shape/eltype, update f in place (for example copyto!) and reuse the same TVProblem.
Solving a Single Input
Allocate output internally:
u, stats = TotalVariationImageFiltering.solve(problem, TotalVariationImageFiltering.ROFConfig())Or in place:
u = copy(problem.f)
stats = TotalVariationImageFiltering.solve!(u, problem, TotalVariationImageFiltering.ROFConfig())stats is:
TotalVariationImageFiltering.SolverStats(iterations, converged, rel_change)Supported solvers:
ROFConfig(ROF model withL2Fidelity).PDHGConfig(L2FidelityandPoissonFidelity, with optional primal constraints).GSTVConfig(L2Fidelity,GroupSparseTV, and no primal constraint).
ROFConfig currently supports only constraint = NoConstraint().
Warm Starts and State Reuse
For repeated solves, pass reusable workspace:
state = TotalVariationImageFiltering.ROFState(problem.f) # or PDHGState(problem.f)
u = copy(problem.f)
stats = TotalVariationImageFiltering.solve!(u, problem, TotalVariationImageFiltering.ROFConfig(); state = state)Behavior:
- For
PDHGConfig,uprovides primal warm start. - For
ROFConfig,state.pis the effective warm start;uis copied into the solver buffer and mainly affects the first relative-change check. state.p(dual variable) is retained across calls.- State shape/eltype must match the solve buffer.
For GSTV, construct GSTVState(problem.f, problem.tv_mode). Its ADMM split and scaled-dual fields are retained between calls. GSTVBatchState instead owns one contiguous spatial workspace and resets split variables between sequential batch items, keeping peak workspace independent of batch size.
Batch API
For arrays shaped (spatial..., batch):
u_batch, stats = TotalVariationImageFiltering.solve_batch(
f_batch,
TotalVariationImageFiltering.PDHGConfig();
lambda = 0.1,
data_fidelity = TotalVariationImageFiltering.L2Fidelity(),
constraint = TotalVariationImageFiltering.BoxConstraint(0.0, 1.0),
)TV operators act on spatial axes only; the last axis is batch index.
The batch stats aggregate per-sample results:
iterations: max iterations across samples.converged: true only if all samples converged.rel_change: max relative change across samples.