def XDoG(clip, sigma=1.0, k=1.6, p=20, epsilon=0.7, lamda=0.01): """XDoG - An eXtended difference-of-Gaussian filter Args: clip: Input clip. sigma: (float) Strength of gaussian filter. Default is 1. k: (float) Amplifier of "sigma" for second gaussian filtering. Default is 1.6. p: (float) Amplifier of difference of gaussian. Default is 20. epsilon: (float, 0~1) Threshold of DoG response. Scaled automatically. Default is 0.7. lamda: (float) Multiplier in the thresholding function. Default is 0.01. Ref: [1] Winnemöller, H., Kyprianidis, J. E., & Olsen, S. C. (2012). XDoG: an extended difference-of-Gaussians compendium including advanced image stylization. Computers & Graphics, 36(6), 740-753. """ bits = clip.format.bits_per_sample peak = (1 << bits) - 1 epsilon = muf.scale(epsilon, bits) f1 = core.tcanny.TCanny(clip, sigma=sigma, mode=-1) f2 = core.tcanny.TCanny(clip, sigma=sigma * k, mode=-1) return core.std.Expr([f1, f2], f'x y - {p} * x + {epsilon} >= 1 2 2 2 x y - {p} * x + {epsilon} - {lamda} * * exp 1 + / - ? {peak} *')
def tv(I, iter=5, dt=None, ep=1, lam=0, I0=None, C=0): """Total Variation Denoising Args: I: Input. Recommended to input floating type clip. iter: (int) Num of iterations. Default is 5. dt: (float) Time step. Default is ep/5. ep: (float) Epsilon (of gradient regularization). Default is 1. lam: (float) Fidelity term lambda. Default is 0. I0: (clip) Input (noisy) image. Default is "I". Ref: [1] Rudin, L. I., Osher, S., & Fatemi, E. (1992). Nonlinear total variation based noise removal algorithms. Physica D: Nonlinear Phenomena, 60(1-4), 259-268. [2] Total Variation Denoising : http://visl.technion.ac.il/~gilboa/PDE-filt/tv_denoising.html """ core = vs.get_core() if dt is None: dt = ep / 5 if I0 is None: I0 = I ep2 = ep * ep isFloat = I.format.sample_type == vs.FLOAT neutral = 0 if isFloat else muf.scale(128, I.format.bits_per_sample) for i in range(iter): I_x = core.std.Convolution(I, [-1, 0, 1], divisor=2, bias=neutral, mode='h') # correct I_y = core.std.Convolution(I, [-1, 0, 1], divisor=2, bias=neutral, mode='v') # correct I_xx = core.std.Convolution(I, [1, -2, 1], divisor=1 if isFloat else 4, bias=neutral, mode='h') # x4 I_yy = core.std.Convolution(I, [1, -2, 1], divisor=1 if isFloat else 4, bias=neutral, mode='v') # x4 Dp = core.std.Convolution(I, [1, 0, 0, 0, 0, 0, 0, 0, 1], divisor=2) Dm = core.std.Convolution(I, [0, 0, 1, 0, 0, 0, 1, 0, 0], divisor=2) I_xy = core.std.Expr([Dp, Dm], ['x y - 2 / {} +'.format(neutral)]) # correct if isFloat: expr = 'x {dt} a {ep2} z dup * + * 2 y * z * b * - c {ep2} y dup * + * + {ep2} y dup * + z dup * + 1.5 pow / {lam} d x - {C} + * + * +'.format(dt=dt, ep2=ep2, lam=lam, C=C) else: # isInteger expr = 'x {dt} a {neutral} - 4 * {ep2} z {neutral} - dup * + * 2 y {neutral} - * z {neutral} - * b {neutral} - * - c {neutral} - 4 * {ep2} y {neutral} - dup * + * + {ep2} y {neutral} - dup * + z {neutral} - dup * + 1.5 pow / {lam} d x - {C} + * + * +'.format(dt=dt, neutral=neutral, ep2=ep2, lam=lam, C=C) I = core.std.Expr([I, I_x, I_y, I_xx, I_xy, I_yy, I0], [expr]) return I