Description of sopt_mltb_prox_TVoA
Description: sopt_mltb_prox_TVoA - Agumented total variation proximal operator

Home > matlab > prox_operators > sopt_mltb_prox_TVoA.m

# sopt_mltb_prox_TVoA

## PURPOSE

sopt_mltb_prox_TVoA - Agumented total variation proximal operator

## SYNOPSIS

function sol = sopt_mltb_prox_TVoA(b, lambda, param)

## DESCRIPTION

     sopt_mltb_prox_TVoA - Agumented total variation proximal operator

     Compute the TV proximal operator when an additional linear operator A is
     incorporated in the TV norm, i.e. solve

       min_{x} ||y - x||_2^2 + lambda * ||A x||_{TV}

     where x is the input vector and the solution z* is returned as sol.
     The structure param should contain the following fields:

       - max_iter: Maximum number of iterations (default = 200).

       - rel_obj: Minimum relative change of the objective value
           (default = 1e-4).  The algorithm stops if
               | ||x(t)||_TV - ||x(t-1)||_TV | / ||x(t)||_1 < rel_obj,
           where x(t) is the estimate of the solution at iteration t.

       - verbose: Verbosity level (0 = no log, 1 = summary at convergence,
           2 = print main steps; default = 1).

       - A: Forward transform (default = Identity).

       - At: Adjoint of At (default = Identity).

       - nu: Bound on the norm^2 of the operator A, i.e.
           ||A x||^2 <= nu * ||x||^2 (default = 1)

     Reference:
     [1] A. Beck and  M. Teboulle, "Fast gradient-based algorithms for
     constrained Total Variation Image Denoising and Deblurring Problems",
     IEEE Transactions on Image Processing, VOL. 18, NO. 11, 2419-2434,
     November 2009.

## CROSS-REFERENCE INFORMATION

This function calls:

This function is called by:

## SOURCE CODE

    0001 function sol = sopt_mltb_prox_TVoA(b, lambda, param)
    0002 % sopt_mltb_prox_TVoA - Agumented total variation proximal operator
    0003 %
    0004 % Compute the TV proximal operator when an additional linear operator A is
    0005 % incorporated in the TV norm, i.e. solve
    0006 %
    0007 %   min_{x} ||y - x||_2^2 + lambda * ||A x||_{TV}
    0008 %
    0009 % where x is the input vector and the solution z* is returned as sol.
    0010 % The structure param should contain the following fields:
    0011 %
    0012 %   - max_iter: Maximum number of iterations (default = 200).
    0013 %
    0014 %   - rel_obj: Minimum relative change of the objective value
    0015 %       (default = 1e-4).  The algorithm stops if
    0016 %           | ||x(t)||_TV - ||x(t-1)||_TV | / ||x(t)||_1 < rel_obj,
    0017 %       where x(t) is the estimate of the solution at iteration t.
    0018 %
    0019 %   - verbose: Verbosity level (0 = no log, 1 = summary at convergence,
    0020 %       2 = print main steps; default = 1).
    0021 %
    0022 %   - A: Forward transform (default = Identity).
    0023 %
    0024 %   - At: Adjoint of At (default = Identity).
    0025 %
    0026 %   - nu: Bound on the norm^2 of the operator A, i.e.
    0027 %       ||A x||^2 <= nu * ||x||^2 (default = 1)
    0028 %
    0029 % Reference:
    0030 % [1] A. Beck and  M. Teboulle, "Fast gradient-based algorithms for
    0031 % constrained Total Variation Image Denoising and Deblurring Problems",
    0032 % IEEE Transactions on Image Processing, VOL. 18, NO. 11, 2419-2434,
    0033 % November 2009.
    0034
    0035 % Optional input arguments
    0036 if ~isfield(param, 'rel_obj'), param.rel_obj = 1e-4; end
    0037 if ~isfield(param, 'verbose'), param.verbose = 1; end
    0038 if ~isfield(param, 'max_iter'), param.max_iter = 200; end
    0039 if ~isfield(param, 'At'), param.At = @(x) x; end
    0040 if ~isfield(param, 'A'), param.A = @(x) x; end
    0041 if ~isfield(param, 'nu'), param.nu = 1; end
    0042
    0043 % Advanced input arguments (not exposed in documentation)
    0044 if ~isfield(param, 'weights_dx'), param.weights_dx = 1; end
    0045 if ~isfield(param, 'weights_dy'), param.weights_dy = 1; end
    0046 if ~isfield(param, 'zero_weights_flag'), param.zero_weights_flag = 1; end
    0047 if ~isfield(param, 'identical_weights_flag')
    0048     param.identical_weights_flag = 0;
    0049 end
    0050 if ~isfield(param, 'sphere_flag'), param.sphere_flag = 0; end
    0051 if ~isfield(param, 'incNP'), param.incNP = 0; end
    0052
    0053 % Set grad and div operators to planar or spherical case and also
    0054 % include weights or not (depending on parameter flags).
    0055 if (param.sphere_flag)
    0056    G = @sopt_mltb_gradient_op_sphere;
    0057    D = @sopt_mltb_div_op_sphere;
    0058 else
    0059    G = @sopt_mltb_gradient_op;
    0060    D = @sopt_mltb_div_op;
    0061 end
    0062
    0063 if (~param.identical_weights_flag && param.zero_weights_flag)
    0064     grad = @(x) G(x, param.weights_dx, param.weights_dy);
    0065     div = @(r, s) D(r, s, param.weights_dx, param.weights_dy);
    0066     max_weights = max([abs(param.weights_dx(:)); ...
    0067         abs(param.weights_dy(:))])^2;
    0068 else
    0069     grad = @(x) G(x);
    0070     div = @(r, s) D(r, s);
    0071 end
    0072
    0073 % Initializations
    0074 [r, s] = grad(param.A(b*0));
    0075 pold = r; qold = s;
    0076 told = 1; prev_obj = 0;
    0077
    0078 % Main iterations
    0079 if param.verbose > 1
    0080     fprintf('  Proximal TV operator:\n');
    0081 end
    0082 for iter = 1:param.max_iter
    0083
    0084     % Current solution
    0085     sol = b - lambda*param.At(div(r, s));
    0086
    0087     % Objective function value
    0088     obj = .5*norm(b(:)-sol(:), 2) + lambda * ...
    0089         sopt_mltb_TV_norm(param.A(sol), param.weights_dx, param.weights_dy);
    0090     rel_obj = abs(obj-prev_obj)/obj;
    0091     prev_obj = obj;
    0092
    0093     % Stopping criterion
    0094     if param.verbose>1
    0095         fprintf('   Iter %i, obj = %e, rel_obj = %e\n', ...
    0096             iter, obj, rel_obj);
    0097     end
    0098     if rel_obj < param.rel_obj
    0099         crit_TV = 'TOL_EPS'; break;
    0100     end
    0101
    0102     % Udpate divergence vectors and project
    0103     [dx, dy] = grad(param.A(sol));
    0104     if (param.identical_weights_flag)
    0105         r = r - 1/(8*lambda*param.nu) * dx;
    0106         s = s - 1/(8*lambda*param.nu) * dy;
    0107         weights = max(param.weights_dx, sqrt(abs(r).^2+abs(s).^2));
    0108         p = r./weights.*param.weights_dx; q = s./weights.*param.weights_dx;
    0109     else
    0110         if (~param.zero_weights_flag)
    0111             r = r - 1/(8*lambda*param.nu) * dx;
    0112             s = s - 1/(8*lambda*param.nu) * dy;
    0113             weights = max(1, sqrt(abs(r./param.weights_dx).^2+...
    0114                 abs(s./param.weights_dy).^2));
    0115             p = r./weights; q = s./weights;
    0116         else
    0117             % Weights go into grad and div operators so usual update
    0118             r = r - 1/(8*lambda*param.nu*max_weights) * dx;
    0119             s = s - 1/(8*lambda*param.nu*max_weights) * dy;
    0120             weights = max(1, sqrt(abs(r).^2+abs(s).^2));
    0121             p = r./weights; q = s./weights;
    0122         end
    0123     end
    0124
    0125     % FISTA update
    0126     t = (1+sqrt(4*told^2))/2;
    0127     r = p + (told-1)/t * (p - pold); pold = p;
    0128     s = q + (told-1)/t * (q - qold); qold = q;
    0129     told = t;
    0130
    0131 end
    0132
    0133 % Log after the minimization
    0134 if ~exist('crit_TV', 'var'), crit_TV = 'MAX_IT'; end
    0135 if param.verbose >= 1
    0136     fprintf(['  Prox_TV: obj = %e, rel_obj = %e,' ...
    0137         ' %s, iter = %i\n'], obj, rel_obj, crit_TV, iter);
    0138 end
    0139
    0140 end