def tv(value): """Total variation of a vector or matrix. Uses L1 norm of discrete gradients for vectors and L2 norm of discrete gradients for matrices. Parameters ---------- value : Expression or numeric constant The value to take the total variation of. Returns ------- Expression An Expression representing the total variation. """ value = Expression.cast_to_const(value) rows, cols = value.size if value.is_scalar(): raise ValueError("tv cannot take a scalar argument.") # L1 norm for vectors. elif value.is_vector(): return norm(value[1:] - value[0:max(rows, cols) - 1], 1) # L2 norm for matrices. else: row_diff = value[0:rows - 1, 1:cols] - value[0:rows - 1, 0:cols - 1] col_diff = value[1:rows, 0:cols - 1] - value[0:rows - 1, 0:cols - 1] return sum_entries(norm2_elemwise(row_diff, col_diff))
def l1_aniso_2d(value1, value2): """\sum \sqrt{value1^2 + value2^2} Parameters ---------- value : Expression or numeric constant The value to take the total variation of. Returns ------- Expression An Expression representing the total variation. """ value1 = Expression.cast_to_const(value1) value2 = Expression.cast_to_const(value2) len = value1.size[0] return sum_entries(cvxnorm(value1 + value2, p='1'))
def tv(value, *args): """Total variation of a vector, matrix, or list of matrices. Uses L1 norm of discrete gradients for vectors and L2 norm of discrete gradients for matrices. Parameters ---------- value : Expression or numeric constant The value to take the total variation of. args : Matrix constants/expressions Additional matrices extending the third dimension of value. Returns ------- Expression An Expression representing the total variation. """ # Accept single list as argument. if isinstance(value, list) and len(args) == 0: args = value[1:] value = value[0] value = Expression.cast_to_const(value) rows, cols = value.size if value.is_scalar(): raise ValueError("tv cannot take a scalar argument.") # L1 norm for vectors. elif value.is_vector(): return norm(value[1:] - value[0:max(rows, cols)-1], 1) # L2 norm for matrices. else: args = list(map(Expression.cast_to_const, args)) values = [value] + list(args) diffs = [] for mat in values: diffs += [ mat[0:rows-1, 1:cols] - mat[0:rows-1, 0:cols-1], mat[1:rows, 0:cols-1] - mat[0:rows-1, 0:cols-1], ] length = diffs[0].size[0]*diffs[1].size[1] stacked = vstack(*[reshape(diff, 1, length) for diff in diffs]) return sum_entries(norm(stacked, p='fro', axis=0))
def tv(value, *args): """Total variation of a vector, matrix, or list of matrices. Uses L1 norm of discrete gradients for vectors and L2 norm of discrete gradients for matrices. Parameters ---------- value : Expression or numeric constant The value to take the total variation of. args : Matrix constants/expressions Additional matrices extending the third dimension of value. Returns ------- Expression An Expression representing the total variation. """ # Accept single list as argument. if isinstance(value, list) and len(args) == 0: args = value[1:] value = value[0] value = Expression.cast_to_const(value) rows, cols = value.size if value.is_scalar(): raise ValueError("tv cannot take a scalar argument.") # L1 norm for vectors. elif value.is_vector(): return norm(value[1:] - value[0:max(rows, cols)-1], 1) # L2 norm for matrices. else: args = map(Expression.cast_to_const, args) values = [value] + list(args) diffs = [] for mat in values: diffs += [ mat[0:rows-1, 1:cols] - mat[0:rows-1, 0:cols-1], mat[1:rows, 0:cols-1] - mat[0:rows-1, 0:cols-1], ] length = diffs[0].size[0]*diffs[1].size[1] stacked = vstack(*[reshape(diff, 1, length) for diff in diffs]) return sum_entries(norm(stacked, p='fro', axis=0))
def tvnorm2d(value, Dx, Dy): """Total variation of a vector, matrix, or list of matrices. Uses L1 norm of discrete gradients for vectors and L2 norm of discrete gradients for matrices. Parameters ---------- value : Expression or numeric constant The value to take the total variation of. Returns ------- Expression An Expression representing the total variation. """ value = Expression.cast_to_const(value) len = value.size[0] diffs = [Dx * value, Dy * value] stack = vstack(*[reshape(diff, 1, len) for diff in diffs]) return sum_entries(cvxnorm(stack, p='fro', axis=0))
def tv(value, *args): """Total variation of a vector, matrix, or list of matrices. Uses L1 norm of discrete gradients for vectors and L2 norm of discrete gradients for matrices. Parameters ---------- value : Expression or numeric constant The value to take the total variation of. args : Matrix constants/expressions Additional matrices extending the third dimension of value. Returns ------- Expression An Expression representing the total variation. """ value = Expression.cast_to_const(value) rows, cols = value.size if value.is_scalar(): raise ValueError("tv cannot take a scalar argument.") # L1 norm for vectors. elif value.is_vector(): return norm(value[1:] - value[0:max(rows, cols)-1], 1) # L2 norm for matrices. else: args = list(map(Expression.cast_to_const, args)) values = [value] + list(args) diffs = [] for mat in values: diffs += [ mat[0:rows-1, 1:cols] - mat[0:rows-1, 0:cols-1], mat[1:rows, 0:cols-1] - mat[0:rows-1, 0:cols-1], ] return sum_entries(norm2_elemwise(*diffs))
def tv(value, *args): """Total variation of a vector, matrix, or list of matrices. Uses L1 norm of discrete gradients for vectors and L2 norm of discrete gradients for matrices. Parameters ---------- value : Expression or numeric constant The value to take the total variation of. args : Matrix constants/expressions Additional matrices extending the third dimension of value. Returns ------- Expression An Expression representing the total variation. """ value = Expression.cast_to_const(value) rows, cols = value.size if value.is_scalar(): raise ValueError("tv cannot take a scalar argument.") # L1 norm for vectors. elif value.is_vector(): return norm(value[1:] - value[0:max(rows, cols) - 1], 1) # L2 norm for matrices. else: args = map(Expression.cast_to_const, args) values = [value] + list(args) diffs = [] for mat in values: diffs += [ mat[0:rows - 1, 1:cols] - mat[0:rows - 1, 0:cols - 1], mat[1:rows, 0:cols - 1] - mat[0:rows - 1, 0:cols - 1], ] return sum_entries(norm2_elemwise(*diffs))
def l1_anisotropic_2d(signal): return sum_entries(cvxnorm(signal, 2, axis=1))
def tvnorm_anisotropic_2d(signal, Dx, Dy): magnitudes = pnorm(signal, 2, axis=1) diffs = [Dx * magnitudes, Dy * magnitudes] stack = vstack(*[reshape(diff, 1, magnitudes.size[0]) for diff in diffs]) return sum_entries(pnorm(stack, 2, axis=0))