Beispiel #1
0
    def _vdf_fsrcnnx(clip: vs.VideoNode, width: int,
                     height: int) -> vs.VideoNode:
        clip = core.std.ShufflePlanes([
            vsutil.depth(clip.resize.Point(vsutil.get_w(864), 864), 16),
            src.resize.Bicubic(vsutil.get_w(864), 864)
        ],
                                      planes=[0, 1, 2],
                                      colorfamily=vs.YUV)

        return vsutil.get_y(
            vsutil.depth(vdf.fsrcnnx_upscale(clip, width, height, FSRCNNX),
                         32))
Beispiel #2
0
def rescaler(clip: vs.VideoNode, height: int) -> vs.VideoNode:
    """
    Basic rescaling function using nnedi3.
    """
    from lvsfunc.kernels import Bicubic, BicubicSharp
    from vardefunc.mask import FDOG
    from vardefunc.scale import nnedi3_upscale
    from vsutil import Range, depth, get_w, get_y

    clip = depth(clip, 32)

    clip_y = get_y(clip)
    descale = BicubicSharp().descale(clip_y,
                                     get_w(height, clip.width / clip.height),
                                     height)
    rescale = Bicubic(b=-1 / 2,
                      c=1 / 4).scale(nnedi3_upscale(descale, pscrn=1),
                                     clip.width, clip.height)

    l_mask = FDOG().get_mask(clip_y, lthr=0.065,
                             hthr=0.065).std.Maximum().std.Minimum()
    l_mask = l_mask.std.Median().std.Convolution([1] *
                                                 9)  # stolen from varde xd
    masked_rescale = core.std.MaskedMerge(clip_y, rescale, l_mask)

    scaled = join([masked_rescale, plane(clip, 1), plane(clip, 2)])

    return depth(scaled, 16)
Beispiel #3
0
def comparative_restore(clip: vs.VideoNode, width: int | None = None, height: int = 720,
                        kernel: Kernel | str | None = None) -> vs.VideoNode:
    """
    Companion function to go with comparative_descale
    to reupscale the clip for descale detail masking.

    :param clip:        Input clip
    :param width:       Width to upscale to (if None, auto-calculated)
    :param height:      Upscale height
    :param kernel:      Kernel to compare BicubicSharp to (Default: Spline36 if None)

    :return:            Reupscaled clip
    """
    check_variable(clip, "comparative_restore")

    if isinstance(kernel, str):
        kernel = get_kernel(kernel)()

    bsharp = BicubicSharp()
    kernel = kernel or Spline36()

    if isinstance(kernel, Bicubic) and bsharp.b == kernel.b and bsharp.c == kernel.c:
        raise ValueError("comparative_restore: 'You may not compare BicubicSharp with itself!'")

    if width is None:
        width = get_w(height, aspect_ratio=clip.width/clip.height)

    def _compare(n: int, f: vs.VideoFrame, sharp_up: vs.VideoNode, other_up: vs.VideoNode) -> vs.VideoNode:
        return sharp_up if get_prop(f, 'scaler', bytes) == b'BicubicSharp' else other_up

    # TODO: just read prop and automatically figure out scaler TBH
    sharp_up = bsharp.scale(clip, width, height)
    other_up = kernel.scale(clip, width, height)

    return core.std.FrameEval(sharp_up, partial(_compare, sharp_up=sharp_up, other_up=other_up), clip)
Beispiel #4
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 16)

    h = 828
    w = get_w(h)
    kernel = 'bilinear'

    denoise = CoolDegrain(src, tr=1, thsad=24, blksize=8, overlap=4, plane=4)
    out = denoise

    luma = get_y(out)

    descale = kgf.get_descale_filter(kernel)(depth(luma, 32), w, h)
    upscale = vdf.nnedi3_upscale(depth(descale, 16), correct_shift=False, pscrn=4) \
        .resize.Bicubic(src.width, src.height, src_left=.5, src_top=.5,
                        filter_param_a=0, filter_param_b=0)
    out = vdf.merge_chroma(upscale, out)

    deband_mask = lvf.denoise.detail_mask(out, brz_a=2000, brz_b=1000)

    deband = dbs.f3kpf(out, 17, 24, 24)

    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband

    grain = kgf.adaptive_grain(out, 0.2, luma_scaling=14)
    out = grain

    return depth(out, 10)
Beispiel #5
0
def scaled_grain(clip: vs.VideoNode,
                 var: float = 0.25,
                 uvar: float = 0,
                 grain_h: Optional[int] = None,
                 grain_w: Optional[int] = None,
                 static: bool = True,
                 adaptive: bool = False,
                 luma_scaling: int = 12,
                 kernel: str = 'bicubic',
                 b: float = 0,
                 c: float = 1 / 2,
                 taps: int = 3) -> vs.VideoNode:
    """Grains a clip in the given dimensions and merges it with the source clip.

    This is useful for making larger grain patterns when
    using a grain resolution smaller than the source clip's resolution.
    It supports static and dynamic grain with optional adaptive brightness
    masking to grain darker areas more than brighter areas.

    Args:
        clip: The source clip. Assumes YUV format.
        var: Luma grain variance (strength).
        uvar: Chroma grain variance (strength).
        grain_h: Height of the grained clip.
        grain_w: Width of the grained clip.
        static: Determines whether static (constant) or dynamic grain is used.
        adaptive: Determines whether adaptive brightness masking is used.
        luma_scaling: The scaling factor for adaptive brightness masking.
            Lower values increase the graining of brighter areas.
        kernel: The scaling kernel used to scale the grain clip to
            the source clip's dimensions.
        b, c, taps: Parameters for tweaking the kernel.
    """
    grain_h = fallback(grain_h, clip.height / 2)
    grain_w = fallback(grain_w, get_w(grain_h, clip.width / clip.height))

    blank_value = (1 << get_depth(clip)) / 2 if is_integer(clip) else 0
    blank_clip = core.std.BlankClip(
        clip,
        width=grain_w,
        height=grain_h,
        color=[blank_value, blank_value, blank_value])

    grained = core.grain.Add(blank_clip, var=var, uvar=uvar, constant=static)
    grained = fvf.Resize(grained,
                         clip.width,
                         clip.height,
                         kernel=kernel,
                         a1=b,
                         a2=c,
                         taps=taps)

    if adaptive:
        src_res_blank = core.resize.Point(blank_clip, clip.width, clip.height)
        adaptive_mask = core.adg.Mask(core.std.PlaneStats(clip), luma_scaling)
        grained = core.std.MaskedMerge(src_res_blank, grained, adaptive_mask)

    merged = core.std.MergeDiff(clip, grained)

    return clamp(merged)
Beispiel #6
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 32)


    denoise = mvf.BM3D(src, 1.1, radius1=1, depth=16)
    out = denoise




    antialias = lvf.sraa(out, 2, 13, downscaler=core.resize.Bicubic, gamma=500, nrad=2, mdis=16)
    out = antialias



    deband_mask = lvf.denoise.detail_mask(out, brz_a=2250, brz_b=1600).std.Median()
    deband = dbs.f3kbilateral(out, 17, 36, 36)
    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband


    grain = core.grain.Add(out, 0.3, constant=True)
    out = grain


    endcard = endcard_source(r'endcards\yande.re 602496 isekai_quartet minami_seira overlord raphtalia re_zero_kara_hajimeru_isekai_seikatsu tagme tate_no_yuusha_no_nariagari youjo_senki.jpg', src)
    endcard = core.resize.Bicubic(endcard, get_w(src.height, endcard.width/endcard.height,
                                                 only_even=bool(endcard.format.name == 'YUV420P8')),
                                  src.height, range_in=1, range=0, dither_type='error_diffusion')
    final = core.std.Splice([out, endcard * 223], mismatch=True)


    return core.resize.Bicubic(final, format=vs.YUV420P10, dither_type='error_diffusion')
Beispiel #7
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 32)

    h = 720
    w = get_w(h)
    b, c = vdf.get_bicubic_params('robidoux')




    denoise = hybrid_denoise(src, 0.5, 2)
    out = denoise


    luma = get_y(out)
    line_mask = vdf.edge_detect(luma, 'FDOG', 0.05, (1, 1))


    descale = core.descale.Debicubic(luma, w, h, b, c)
    upscale = vdf.fsrcnnx_upscale(descale, None, descale.height*2, '_shaders/FSRCNNX_x2_56-16-4-1.glsl', core.resize.Point)

    antialias = single_rate_antialiasing(upscale, 13, alpha=0.3, beta=0.45, gamma=320, mdis=18)

    scaled = muvf.SSIM_downsample(antialias, src.width, src.height, kernel='Bicubic')
    rescale = core.std.MaskedMerge(luma, scaled, line_mask)
    merged = vdf.merge_chroma(rescale, out)
    out = depth(merged, 16)



    # Slight sharp though CAS
    sharp = hvf.LSFmod(out, strength=75, Smode=3, Lmode=1, edgemode=1, edgemaskHQ=True)
    out = sharp


    dering = gf.HQDeringmod(out, thr=16, darkthr=0.1)
    out = dering



    warp = xvs.WarpFixChromaBlend(out, thresh=48, depth=8)
    out = warp


    preden = core.knlm.KNLMeansCL(out, d=0, a=3, h=0.6, device_type='GPU', channels='Y')
    deband_mask = lvf.denoise.detail_mask(preden, brz_a=2000, brz_b=800, rad=4)
    deband = dbs.f3kpf(out, 17, 42, 42)
    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband


    adg_mask = core.adg.Mask(out.std.PlaneStats(), 20).std.Expr(f'x x {128<<8} - 0.25 * +')
    grain = core.grain.Add(out, 0.2, constant=True)
    grain = core.std.MaskedMerge(out, grain, adg_mask, 0)
    out = grain


    return depth(out, 10)
Beispiel #8
0
def rescaler(clip: vs.VideoNode,
             height: int) -> Tuple[vs.VideoNode, vs.VideoNode]:
    """
    Basic rescaling and mask generating function using nnedi3.
    """
    from lvsfunc.kernels import Bicubic
    from lvsfunc.scale import descale_detail_mask
    from vardefunc.mask import FDOG
    from vardefunc.scale import nnedi3_upscale
    from vsutil import Range, get_w, join, plane

    bits, clip = _get_bits(clip, expected_depth=32)

    clip_y = get_y(clip)
    descale = Bicubic().descale(clip_y, get_w(height,
                                              clip.width / clip.height),
                                height)
    rescale = Bicubic().scale(nnedi3_upscale(descale, pscrn=1), clip.width,
                              clip.height)

    l_mask = FDOG().get_mask(clip_y, lthr=0.065,
                             hthr=0.065).std.Maximum().std.Minimum()
    l_mask = l_mask.std.Median().std.Convolution([1] *
                                                 9)  # stolen from varde xd
    masked_rescale = core.std.MaskedMerge(clip_y, rescale, l_mask)

    scaled = join([masked_rescale, plane(clip, 1), plane(clip, 2)])

    upscale = Bicubic().scale(descale, 1920, 1080)
    detail_mask = descale_detail_mask(clip_y, upscale, threshold=0.055)

    scaled_down = scaled if bits == 32 else depth(scaled, bits)
    mask_down = detail_mask if bits == 32 else depth(
        detail_mask, 16, range_in=Range.FULL, range=Range.LIMITED)
    return scaled_down, mask_down
Beispiel #9
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 32)
    edstart, edend = 14969, src.num_frames - 1

    denoise = mvf.BM3D(src, 1.1, radius1=1, depth=16)
    out = denoise

    antialias = lvf.sraa(out,
                         2,
                         13,
                         downscaler=core.resize.Bicubic,
                         gamma=500,
                         nrad=2,
                         mdis=16)
    out = antialias

    deband_mask = lvf.denoise.detail_mask(out, brz_a=2250,
                                          brz_b=1600).std.Median()
    deband = dbs.f3kbilateral(out, 17, 48, 48)
    deband_a = dbs.f3kbilateral(out, 22, 96, 96)
    deband = lvf.rfs(deband, deband_a, [(edstart, edend)])
    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband

    grain = core.grain.Add(out, 0.3, constant=True)
    out = grain

    endcard = endcard_source(
        r'endcards\yande.re 611483 isekai_quartet iwamoto_tatsurou maid ram_(re_zero) rem_(re_zero) sketch tanya_degurechaff tate_no_yuusha_no_nariagari uniform youjo_senki.jpg',
        src)
    endcard_ar = endcard.width / endcard.height
    endcard_ev = bool(endcard.format.name == 'YUV420P8')

    if endcard_ar > 16 / 9:
        w, h = get_w(src.height, endcard_ar, only_even=endcard_ev), src.height
    elif endcard_ar < 16 / 9:
        w, h = src.width, get_h(src.width, endcard_ar, only_even=endcard_ev)
    else:
        w, h = src.width, src.height

    endcard = core.resize.Bicubic(endcard,
                                  w,
                                  h,
                                  vs.YUV444PS,
                                  range_in=1,
                                  range=0,
                                  dither_type='error_diffusion')
    endcard = mvf.BM3D(endcard, 0.5)
    endcard = core.std.CropAbs(endcard,
                               1920,
                               1080,
                               top=round((endcard.height - 1080) / 2 / 2) * 2)
    final = core.std.Splice([out, endcard * (17263 - src.num_frames)],
                            mismatch=True)

    return core.resize.Bicubic(final,
                               format=vs.YUV420P10,
                               dither_type='error_diffusion')
Beispiel #10
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 16)
    out = src
    h = 720
    w = get_w(h)

    fixedges = awf.bbmod(out, 2, 2, 2, 2, 64 << 8, 999)
    out = fixedges

    clean = core.knlm.KNLMeansCL(out,
                                 h=0.55,
                                 a=2,
                                 d=3,
                                 device_type='gpu',
                                 device_id=0,
                                 channels='UV')
    clean = core.knlm.KNLMeansCL(clean,
                                 h=0.55,
                                 a=2,
                                 d=3,
                                 device_type='gpu',
                                 device_id=0,
                                 channels='Y')
    diff_den = core.std.MakeDiff(out, clean)
    out = depth(clean, 32)

    luma = get_y(out)
    line_mask = vdf.edge_detect(luma, 'FDOG', 0.05, (1, 1))

    descale = core.descale.Debilinear(luma, w, h)
    upscale = vdf.nnedi3_upscale(descale, correct_shift=False,
                                 pscrn=1).resize.Bicubic(src.width,
                                                         src.height,
                                                         src_left=.5,
                                                         src_top=.5)
    rescale = core.std.MaskedMerge(luma, upscale, line_mask)

    merged = vdf.merge_chroma(rescale, out)
    out = depth(merged, 16)

    moozzi = warping(out, 0.4, 4)
    sharp = hvf.LSFmod(moozzi,
                       strength=95,
                       Smode=3,
                       Lmode=1,
                       edgemode=1,
                       edgemaskHQ=True)
    out = sharp

    deband_mask = lvf.denoise.detail_mask(out, brz_a=2000, brz_b=1000)
    deband = dbs.f3kpf(out, 17, 30, 30)
    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband

    grain_org = core.std.MergeDiff(out, diff_den)
    out = grain_org

    return depth(out, 10)
Beispiel #11
0
def descale_fields(clip: vs.VideoNode,
                   height: int = 720,
                   tff: bool = True,
                   kernel: Kernel = Catrom,
                   src_top: float = 0.0) -> vs.VideoNode:
    """
    Simple descaling wrapper for interwoven upscaled fields

    :param clip:        Input clip
    :param height:      Native height. Will be divided by two internally.
                        Width is autocalculated using height and the clip's aspect ratio.
    :param tff:         Top-field-first
    :param kernel:      lvsfunc.Kernel object

    :return:            Descaled GRAY clip
    """
    height_field = height / 2

    clip = clip.std.SetFieldBased(2 - int(tff))

    sep = core.std.SeparateFields(get_y(clip))
    descaled = kernel().descale(sep, get_w(height, clip.width / clip.height),
                                height_field, [src_top, 0])
    weave_y = core.std.DoubleWeave(descaled)[::2].std.SetFrameProp(
        'scaler', data=f'{kernel.__name__} (Fields)')
    return weave_y.std.SetFrameProp('_FieldBased', intval=0)
Beispiel #12
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 16)

    h = 882
    w = get_w(h)
    kernel = 'lanczos'
    taps = 5

    denoise = CoolDegrain(src, tr=1, thsad=24, blksize=8, overlap=4, plane=4)
    out = denoise

    luma = get_y(out)

    descale = kgf.get_descale_filter(kernel, taps=taps)(depth(luma, 32), w, h)
    upscale = vdf.fsrcnnx_upscale(
        depth(descale, 16), src.width, src.height,
        '_assets/shaders/FSRCNNX_x2_56-16-4-1.glsl',
        partial(core.resize.Bicubic, filter_param_a=0, filter_param_b=0))
    out = upscale

    unwarp = line_darkening(out, 0.275).warp.AWarpSharp2(depth=-2.5)
    sharp = hvf.LSFmod(unwarp,
                       strength=90,
                       Smode=3,
                       Lmode=1,
                       edgemode=1,
                       edgemaskHQ=True)

    stabilize = stabilization(out, sharp, 2, 1, 8, 16)
    out = vdf.merge_chroma(stabilize, denoise)

    antialias = lvf.sraa(out, 1.4, rep=7, downscaler=core.resize.Bicubic)
    out = antialias

    deband_mask = lvf.denoise.detail_mask(out, brz_a=2000, brz_b=1000)
    deband = dbs.f3kpf(out, 17, 42, 36)

    deband = core.std.MaskedMerge(deband, out, deband_mask)
    deband = core.neo_f3kdb.Deband(deband,
                                   preset='depth',
                                   grainy=24,
                                   grainc=18,
                                   keep_tv_range=True)
    out = deband

    grain = kgf.adaptive_grain(out, 0.2, luma_scaling=14)
    out = grain

    rescale_mask = vdf.drm(src, h, kernel, taps, mthr=40, sw=4, sh=4)
    credit = out
    credit = lvf.rfs(credit, core.std.MaskedMerge(credit, src, rescale_mask,
                                                  0), [(0, 647),
                                                       (29954, 34046)])
    credit = lvf.rfs(credit, src, [(0, 1)])
    out = credit

    return depth(out, 10)
Beispiel #13
0
def stack_compare(*clips: vs.VideoNode,
                  make_diff: bool = False,
                  height: Optional[int] = None,
                  warn: bool = True) -> vs.VideoNode:
    """
    A simple wrapper that allows you to compare two clips by stacking them.
    You can stack an infinite amount of clips.

    Best to use when trying to match two sources frame-accurately, however by setting height to the source's
    height (or None), it can be used for comparing frames.

    Alias for this function is `lvsfunc.scomp`.

    :param clips:             Clips to compare
    :param make_diff:         Create and stack a diff (only works if two clips are given) (Default: False)
    :param height:            Output height, determined automatically if None (Default: None)
    :param warn:              Warns if the length of given clips don't align (Default: True)

    :return:                  Clip with clips stacked
    """
    if len(clips) < 2:
        raise ValueError("stack_compare: 'Too few clips supplied'")

    if len(clips) != 2 and make_diff:
        raise ValueError(
            "stack_compare: 'You can only create a diff for two clips'")

    formats = set()
    for c in clips:
        if c.format is None:
            raise ValueError(
                "stack_compare: 'Variable-format clips not supported'")
        formats.add(c.format.id)
    if len(formats) != 1:
        raise ValueError(
            "stack_compare: 'The format of every clip must be equal'")

    if make_diff:
        diff = core.std.MakeDiff(clips[0], clips[1])
        diff = core.resize.Spline36(diff, get_w(576), 576).text.FrameNum(8)
        resize = [
            core.resize.Spline36(c, int(diff.width / 2), int(diff.height / 2))
            for c in clips
        ]
        resize[0], resize[1] = resize[0].text.Text("Clip A",
                                                   3), resize[1].text.Text(
                                                       "Clip B", 1)
        stack = core.std.StackVertical(
            [core.std.StackHorizontal([resize[0], resize[1]]), diff])
    else:
        stack = core.std.StackHorizontal(clips)
    if warn:
        if len(set([c.num_frames for c in clips])) != 1:
            stack = core.text.Text(
                stack,
                "Clip Length Mismatch Detected!\nPlease make sure the lengths of all clips match!\n"
                + "".join(f"\nClip {i+1}: {c.num_frames} Frames"
                          for i, c in enumerate(clips)), 2)
    return stack
Beispiel #14
0
def filterchain() -> Union[vs.VideoNode, Tuple[vs.VideoNode, ...]]:
    """Main filterchain"""
    import lvsfunc as lvf
    import muvsfunc as muf
    import vardefunc as vdf
    from adptvgrnMod import adptvgrnMod
    from ccd import ccd
    from vsutil import depth, get_w, get_y, iterate
    from xvs import WarpFixChromaBlend

    # Can't mean this one out this time because of credit changes
    src = JP_CR.clip_cut
    src = depth(src, 32)

    src_y = get_y(src)
    descale = lvf.kernels.Lanczos(taps=5).descale(src_y, get_w(945), 945)
    rescale = vdf.scale.nnedi3cl_double(descale, pscrn=1)
    rescale = muf.SSIM_downsample(rescale, src_y.width, src_y.height)
    scaled = vdf.misc.merge_chroma(rescale, src)
    scaled = depth(scaled, 16)

    # Having a hard time reliably catching the EDs. Oh well.
    upscale = lvf.kernels.Lanczos(taps=5).scale(descale, src_y.width,
                                                src_y.height)
    credit_mask = depth(
        lvf.scale.descale_detail_mask(src_y, upscale, threshold=0.08), 16)
    credit_mask = iterate(credit_mask, core.std.Minimum, 5)
    credit_mask = iterate(credit_mask, core.std.Maximum, 9)
    credit_mask = core.morpho.Close(credit_mask, 9)

    credits_merged = core.std.MaskedMerge(scaled, depth(src, 16), credit_mask)

    denoise_y = core.knlm.KNLMeansCL(credits_merged,
                                     d=1,
                                     a=3,
                                     s=4,
                                     h=0.55,
                                     channels='Y')
    denoise_uv = ccd(denoise_y, threshold=6, matrix='709')
    decs = vdf.noise.decsiz(denoise_uv,
                            sigmaS=8,
                            min_in=208 << 8,
                            max_in=232 << 8)

    darken = flt.line_darkening(decs, strength=0.175)

    deband = flt.masked_f3kdb(darken, thr=24, grain=[24, 12])
    grain: vs.VideoNode = adptvgrnMod(deband,
                                      seed=42069,
                                      strength=0.45,
                                      luma_scaling=10,
                                      size=1.25,
                                      sharp=100,
                                      static=True,
                                      grain_chroma=False)

    return grain
Beispiel #15
0
def auto_descale(clip: vs.VideoNode,
                 height: int = 720,
                 thr: float = 0.000015) -> vs.VideoNode:
    """
    Quick wrapper to descale to Sharp Bicubic and Spline36,
    compare them, and then pick one or the other.

    Could've sworn there was another function that did this, but I forgot what it was lol
    """
    from functools import partial

    from lvsfunc.kernels import BicubicSharp, Spline36
    from lvsfunc.util import get_prop

    def _compare(n: int, f: vs.VideoFrame, sharp: vs.VideoNode,
                 spline: vs.VideoNode) -> vs.VideoNode:
        """Compare PlaneStatsDiff's"""
        sharp_diff = get_prop(f[0], 'PlaneStatsDiff', float)
        spline_diff = get_prop(f[1], 'PlaneStatsDiff', float)

        return sharp if spline_diff - thr > sharp_diff else spline

    clip_y = get_y(clip)
    sharp = BicubicSharp().descale(clip_y,
                                   get_w(height, clip.width / clip.height),
                                   height)
    sharp_up = BicubicSharp().scale(sharp, clip.width, clip.height)

    spline = Spline36().descale(clip_y, get_w(height,
                                              clip.width / clip.height),
                                height)
    spline_up = Spline36().scale(spline, clip.width, clip.height)

    # We need a diff between the rescaled clips and the original clip
    sharp_diff = sharp_up.std.PlaneStats(clip_y)
    spline_diff = spline_up.std.PlaneStats(clip_y)

    # Extra props for future frame evalling in case it might prove useful (for credits, for example)
    sharp = sharp.std.SetFrameProp('scaler', data='BicubicSharp')
    spline = spline.std.SetFrameProp('scaler', data='Spline36')

    return core.std.FrameEval(sharp,
                              partial(_compare, sharp=sharp, spline=spline),
                              [sharp_diff, spline_diff])
Beispiel #16
0
def test_descale(clip: vs.VideoNode,
                 height: int,
                 kernel: str = 'bicubic',
                 b: Union[float, Fraction] = Fraction(1, 3),
                 c: Union[float, Fraction] = Fraction(1, 3),
                 taps: int = 3,
                 show_error: bool = True) -> vs.VideoNode:
    """
    Generic function to test descales with;
    descales and reupscales a given clip, allowing you to compare the two easily.

    When comparing, it is recommended to do atleast a 4x zoom using Nearest Neighbor.
    I also suggest using 'compare' (py:func:lvsfunc.comparison.compare),
    as that will make comparing the output with the source clip a lot easier.

    Some of this code was leveraged from DescaleAA found in fvsfunc.

    Dependencies: vapoursynth-descale

    :param clip:           Input clip
    :param height:         Target descaled height.
    :param kernel:         Kernel used to descale (see :py:func:`lvsfunc.util.get_scale_filter`)
    :param b:              B-param for bicubic kernel (Default: 1 / 3)
    :param c:              C-param for bicubic kernel (Default: 1 / 3)
    :param taps:           Taps param for lanczos kernel (Default: 3)
    :param show_error:     Show diff between the original clip and the reupscaled clip (Default: True)

    :return: A clip re-upscaled with the same kernel
    """
    try:
        from descale import get_filter
    except ModuleNotFoundError:
        raise ModuleNotFoundError("test_descale: missing dependency 'descale'")

    b = float(b)
    c = float(c)

    if get_depth(clip) != 32:
        clip = util.resampler(clip, 32)

    clip_y = get_y(clip)

    desc = get_filter(b, c, taps, kernel)(clip_y,
                                          get_w(height,
                                                clip.width / clip.height),
                                          height)
    upsc = util.get_scale_filter(kernel, b=b, c=c, taps=taps)(desc, clip.width,
                                                              clip.height)
    upsc = core.std.PlaneStats(clip_y, upsc)

    if clip is vs.GRAY:
        return core.text.FrameProps(upsc,
                                    "PlaneStatsDiff") if show_error else upsc
    merge = core.std.ShufflePlanes([upsc, clip], [0, 1, 2], vs.YUV)
    return core.text.FrameProps(merge,
                                "PlaneStatsDiff") if show_error else merge
Beispiel #17
0
def get_chroma_shift(src_h: int,
                     dst_h: int,
                     aspect_ratio: float = 16 / 9) -> float:
    """Intended to calculate the right value for chroma shifting when doing subsampled scaling.

    Args:
        src_h (int): Source height.
        dst_h (int): Destination height.
        aspect_ratio (float, optional): Defaults to 16/9.

    Returns:
        float:
    """
    src_w = get_w(src_h, aspect_ratio)
    dst_w = get_w(dst_h, aspect_ratio)

    ch_shift = 0.25 - 0.25 * (src_w / dst_w)
    ch_shift = float(round(ch_shift, 5))
    return ch_shift
Beispiel #18
0
 def simple_descale(y_clip: vs.VideoNode,
                    h: int) -> Tuple[vs.VideoNode, vs.VideoNode]:
     ar = y_clip.width / y_clip.height
     down = global_clip_descaler(y_clip, get_w(h, ar), h)
     if rescale:
         up = global_clip_resizer(down, target_w, target_h)
     else:
         up = global_clip_resizer(down, y_clip.width, y_clip.height)
     diff = core.std.Expr([y, up], "x y - abs").std.PlaneStats()
     return down, diff
Beispiel #19
0
 def _get_error(clip, height, kernel, b, c, taps):
     descale = get_filter(b, c, taps,
                          kernel)(clip,
                                  get_w(height, clip.width / clip.height),
                                  height)
     upscale = util.get_scale_filter(kernel, b=b, c=c,
                                     taps=taps)(clip, clip.width,
                                                clip.height)
     diff = core.std.PlaneStats(upscale, clip)
     return descale, diff
Beispiel #20
0
 def _perform_descale(height: int) -> ScaleAttempt:
     resolution = Resolution(get_w(height, clip.width / clip.height),
                             height)
     descaled = get_filter(b, c, taps, kernel)(clip, resolution.width, resolution.height) \
         .std.SetFrameProp('descaleResolution', intval=height)
     rescaled = util.get_scale_filter(kernel, b=b, c=c,
                                      taps=taps)(descaled, clip.width,
                                                 clip.height)
     diff = core.std.Expr([rescaled, clip], 'x y - abs').std.PlaneStats()
     return ScaleAttempt(descaled, rescaled, resolution, diff)
Beispiel #21
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 32)
    edstart, edend = 14313, 16383

    denoise = mvf.BM3D(src, 1.1, radius1=1, depth=16)
    out = denoise

    antialias = lvf.sraa(out,
                         2,
                         13,
                         downscaler=core.resize.Bicubic,
                         gamma=500,
                         nrad=2,
                         mdis=16)
    out = antialias

    deband_mask = lvf.denoise.detail_mask(out, brz_a=2250,
                                          brz_b=1600).std.Median()
    deband = dbs.f3kbilateral(out, 17, 48, 48)
    deband_a = dbs.f3kbilateral(out, 22, 96, 96)
    deband = lvf.rfs(deband, deband_a, [(edstart, edend)])
    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband

    grain = core.grain.Add(out, 0.3, constant=True)
    out = grain

    endcard = endcard_source(
        r'endcards\yande.re 607473 cheerleader isekai_quartet pointy_ears ram_(re_zero) rem_(re_zero) satou_kazuma seifuku tagme tanya_degurechaff trap youjo_senki.jpg',
        src)
    endcard_ar = endcard.width / endcard.height
    endcard_ev = bool(endcard.format.name == 'YUV420P8')

    if endcard_ar > 16 / 9:
        w, h = get_w(src.height, endcard_ar, only_even=endcard_ev), src.height
    elif endcard_ar < 16 / 9:
        w, h = src.width, get_h(src.width, endcard_ar, only_even=endcard_ev)
    else:
        w, h = src.width, src.height

    endcard = core.resize.Bicubic(endcard,
                                  w,
                                  h,
                                  range_in=1,
                                  range=0,
                                  dither_type='error_diffusion')
    endcard = lvf.sraa(depth(endcard, 16), 1.5, 7)
    final = core.std.Splice([out, endcard * (17263 - src.num_frames)],
                            mismatch=True)

    return core.resize.Bicubic(final,
                               format=vs.YUV420P10,
                               dither_type='error_diffusion')
Beispiel #22
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    h = 720
    w = get_w(h)


    edgesfix = awf.bbmod(src, 1, 1, 1, 1, 48, 500)
    out = edgesfix


    clip = depth(out, 32)
    denoise = hybrid_denoise(clip, 0.45, 1.5)
    out = denoise



    luma = get_y(out)
    line_mask = line_mask_func(luma)

    descale = core.descale.Debilinear(luma, w, h)
    upscale = vdf.nnedi3_upscale(descale, pscrn=1)
    antialias = single_rate_antialiasing(upscale, 13, alpha=0.2, beta=0.5, gamma=600, mdis=15)


    scaled = core.resize.Bicubic(antialias, src.width, src.height)
    rescale = core.std.MaskedMerge(luma, scaled, depth(line_mask, 32))
    merged = vdf.merge_chroma(rescale, out)
    out = depth(merged, 16)



    preden = core.knlm.KNLMeansCL(get_y(out), h=0.75, a=2, d=3, device_type='gpu', device_id=0)
    detail_dark_mask = detail_dark_mask_func(preden, brz_a=8000, brz_b=6000)
    detail_light_mask = lvf.denoise.detail_mask(preden, brz_a=2500, brz_b=1200)
    detail_mask = core.std.Expr([detail_dark_mask, detail_light_mask], 'x y +').std.Median()
    detail_mask_grow = iterate(detail_mask, core.std.Maximum, 2)
    detail_mask_grow = iterate(detail_mask_grow, core.std.Inflate, 2).std.Convolution([1, 1, 1, 1, 1, 1, 1, 1, 1])

    detail_mask = core.std.Expr([preden, detail_mask_grow, detail_mask], f'x {32<<8} < y z ?')


    deband_a = dbs.f3kpf(out, 16, 30, 42, thr=0.5, elast=2, thrc=0.2)
    deband_b = placebo.deband(out, 18, 5.5, 2, 4)
    deband = core.std.MaskedMerge(deband_a, deband_b, preden)
    deband = core.std.MaskedMerge(deband_a, out, detail_mask)
    deband = core.neo_f3kdb.Deband(deband, preset='depth', grainy=24, grainc=24)
    out = deband


    grain = adptvgrnMod(out, 0.4, 0.3, 1.25, luma_scaling=8, sharp=80, static=False, lo=19)
    out = grain


    return depth(out, 10)
Beispiel #23
0
def comparative_descale(clip: vs.VideoNode, width: int | None = None, height: int = 720,
                        kernel: Kernel | str | None = None, thr: float = 5e-8) -> vs.VideoNode:
    """
    Easy wrapper to descale to SharpBicubic and an additional kernel,
    compare them, and then pick one or the other.

    The output clip has props that can be used to frameeval specific kernels by the user.

    :param clip:        Input clip
    :param width:       Width to descale to (if None, auto-calculated)
    :param height:      Descale height
    :param kernel:      Kernel to compare BicubicSharp to. This can also be a string (Default: Spline36 if None).
    :param thr:         Threshold for which kernel to pick

    :return:            Descaled clip
    """
    def _compare(n: int, f: vs.VideoFrame, sharp: vs.VideoNode, other: vs.VideoNode) -> vs.VideoNode:
        sharp_diff = get_prop(f[0], 'PlaneStatsDiff', float)  # type:ignore[arg-type]
        other_diff = get_prop(f[1], 'PlaneStatsDiff', float)  # type:ignore[arg-type]

        return sharp if other_diff - thr > sharp_diff else other

    check_variable(clip, "comparative_descale")

    if isinstance(kernel, str):
        kernel = get_kernel(kernel)()

    bsharp = BicubicSharp()
    kernel = kernel or Spline36()

    if isinstance(kernel, Bicubic) and bsharp.b == kernel.b and bsharp.c == kernel.c:
        raise ValueError("comparative_descale: 'You may not compare BicubicSharp with itself!'")

    if width is None:
        width = get_w(height, aspect_ratio=clip.width/clip.height)

    clip_y = get_y(clip)
    # TODO: Add support for multiple scaler combos. Gotta rethink how `thr` will work tho
    sharp = bsharp.descale(clip_y, width, height)
    sharp_up = bsharp.scale(sharp, clip.width, clip.height)

    # TODO: Fix so you can also pass additional params to object. Breaks currently (not callable)
    other = kernel.descale(clip_y, width, height)
    other_up = kernel.scale(other, clip.width, clip.height)

    # We need a diff between the rescaled clips and the original clip
    sharp_diff = core.std.PlaneStats(sharp_up, clip_y)
    other_diff = core.std.PlaneStats(other_up, clip_y)

    # Extra props for future frame evalling in case it might prove useful (credit masking, for example)
    sharp = sharp.std.SetFrameProp('scaler', data=bsharp.__class__.__name__)
    other = other.std.SetFrameProp('scaler', data=kernel.__class__.__name__)

    return core.std.FrameEval(sharp, partial(_compare, sharp=sharp, other=other), [sharp_diff, other_diff])
Beispiel #24
0
    def rescale(self, clip: vs.VideoNode, height: int = 720,
                kernel: lvsfunc.kernels.Kernel = lvsfunc.kernels.Catrom(),
                thr: Union[int, float] = 55, expand: int = 2) -> vs.VideoNode:
        """Makes a mask based on rescaled difference.
           Modified version of Atomchtools.

        Args:
            clip (vs.VideoNode):
                Source clip. Can be Gray, YUV or RGB.
                Keep in mind that descale plugin will descale all planes
                after conversion to GRAYS, YUV444PS and RGBS respectively.

            height (int, optional):
                Height to descale to. Defaults to 720.

            kernel (lvsfunc.kernels.Kernel, optional):
                Kernel used to descale. Defaults to lvsfunc.kernels.Bicubic(b=0, c=0.5).

            thr (Union[int, float], optional):
                Binarization threshold. Defaults to 55.

            expand (int, optional):
                Growing/shrinking shape. 0 is allowed. Defaults to 2.

        Returns:
            vs.VideoNode: Rescaled mask.
        """
        if clip.format is None:
            raise FormatError('diff_rescale_mask: Variable format not allowed!')

        bits = get_depth(clip)
        gray_only = clip.format.num_planes == 1
        thr = scale_value(thr, bits, 32, scale_offsets=True)

        pre = core.resize.Bicubic(
            clip, format=clip.format.replace(
                bits_per_sample=32, sample_type=vs.FLOAT, subsampling_w=0, subsampling_h=0
            ).id
        )
        descale = kernel.descale(pre, get_w(height), height)
        rescale = kernel.scale(descale, clip.width, clip.height)

        diff = core.std.Expr(split(pre) + split(rescale), mae_expr(gray_only))

        mask = iterate(diff, lambda x: core.rgsf.RemoveGrain(x, 2), 2)
        mask = core.std.Expr(mask, f'x 2 4 pow * {thr} < 0 1 ?')

        mask = self._minmax(mask, 2 + expand, True)
        mask = mask.std.Deflate()

        return mask.resize.Point(
            format=clip.format.replace(color_family=vs.GRAY, subsampling_w=0, subsampling_h=0).id,
            dither_type='none'
        )
Beispiel #25
0
 def _transpose_shift(n, f, clip):
     try:
         h = f.props['descaleResolution']
     except:
         raise ValueError(
             f"smart_reupscale: 'This clip was not descaled using smart_descale'"
         )
     w = get_w(h)
     clip = core.resize.Bicubic(clip, w, h * 2, src_top=.5)
     clip = core.std.Transpose(clip)
     return clip
Beispiel #26
0
def do_filter():
    """Vapoursynth filtering"""
    def _nnedi3(clip: vs.VideoNode, factor: float, args: dict)-> vs.VideoNode:
        upscale = clip.std.Transpose().nnedi3.nnedi3(0, True, **args) \
            .std.Transpose().nnedi3.nnedi3(0, True, **args)
        sraa = _sraa(upscale, dict(nsize=3, nns=3, qual=1, pscrn=1))
        return core.resize.Bicubic(sraa, clip.width*factor, clip.height*factor,
                                   src_top=.5, src_left=.5, filter_param_a=0, filter_param_b=0.25)

    # My GPU’s dying on it
    def _sraa(clip: vs.VideoNode, nnargs: dict)-> vs.VideoNode:
        clip = clip.nnedi3cl.NNEDI3CL(0, False, **nnargs).std.Transpose()
        clip = clip.nnedi3cl.NNEDI3CL(0, False, **nnargs).std.Transpose()
        return clip

    # Fun part / Cutting
    src_funi, src_wkn = [depth(c, 16) for c in CLIPS_SRC]
    src_funi, src_wkn = src_funi[744:], src_wkn[0] + src_wkn

    # Dehardsubbing
    # comp = lvf.comparison.stack_compare(src_funi, src_wkn, make_diff=True)
    src = core.std.MaskedMerge(src_wkn, src_funi, kgf.hardsubmask(src_wkn, src_funi))
    hardsub_rem = core.std.MaskedMerge(src, src_funi, kgf.hardsubmask_fades(src, src_funi, 8, 2000))
    src = lvf.rfs(src, hardsub_rem, [(3917, 4024)])


    # Regular filterchain
    op, ed = (17238, 19468), (31889, 34045)
    h = 846
    w = get_w(h)
    b, c = vdf.get_bicubic_params('robidoux')

    luma = get_y(src)

    thr = 8000
    line_mask = gf.EdgeDetect(luma, 'FDOG').std.Median().std.Expr(f'x {thr} < x x 3 * ?')

    descale = core.descale.Debicubic(depth(luma, 32), w, h, b, c)
    rescaled = _nnedi3(depth(descale, 16), src.height/h, dict(nsize=0, nns=4, qual=2, pscrn=2))
    rescaled = core.std.MaskedMerge(luma, rescaled, line_mask)
    merged = vdf.merge_chroma(rescaled, src)
    out = merged

    cred_m = vdf.drm(src, h, b=b, c=c, mthr=80, mode='ellipse')
    credit = lvf.rfs(out, core.std.MaskedMerge(out, src, cred_m), [op])
    credit = lvf.rfs(credit, src, [ed])
    out = credit

    deband = dbs.f3kpf(out, 17, 36, 36)
    deband = core.std.MaskedMerge(deband, out, line_mask)
    grain = core.grain.Add(deband, 0.25)

    return depth(grain, 10)
Beispiel #27
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 32)
    ed = (30089, 32247)

    denoise = kgf.hybriddenoise(src, 0.45, 2)
    out = denoise

    h = 720
    w = get_w(h)
    b, c = vdf.get_bicubic_params('mitchell')


    luma = get_y(out)
    line_mask = shf.edge_mask_simple(luma, 'FDOG', 0.08, (1, 1))


    descale = core.descale.Debicubic(luma, w, h, b, c)
    upscale = shf.fsrcnnx_upscale(descale, src.height, 'shaders/FSRCNNX_x2_56-16-4-1.glsl',
                                  partial(SSIM_downsample, kernel='Bicubic'))
    rescale = core.std.MaskedMerge(luma, upscale, line_mask)
    merged = vdf.merge_chroma(rescale, denoise)
    out = depth(merged, 16)



    mask = shf.detail_mask(out, (10000, 4000), (12000, 3500), [(2, 2), (2, 2)], sigma=[50, 250, 400], upper_thr=0.005)
    deband = dbs.f3kpf(out, 17, 42, 48, thrc=0.4)
    deband = core.std.MaskedMerge(deband, out, mask)

    deband_b = placebo.deband(out, 27, 8, 3, 0)
    deband = lvf.rfs(deband, deband_b, [(3404, 3450)])

    deband_c = shf.deband_stonks(out, 20, 8, 3, shf.edge_mask_simple(out, 'prewitt', 2500, (8, 1)))
    deband = lvf.rfs(deband, deband_c, [(5642, 5784), (6222, 6479), (7798, 8073), (8133, 8256), (9699, 9817)])

    deband_d = placebo.deband(out, 17, 7.5, 1, 0)
    deband_d = core.std.MaskedMerge(deband_d, out, mask)
    deband = lvf.rfs(deband, deband_d, [(8074, 8132), (8711, 8766), (12267, 12433), (28468, 28507)])

    grain = core.neo_f3kdb.Deband(deband, preset='depth', grainy=24, grainc=24)
    out = grain


    grain = adptvgrnMod(out, 0.3, size=4/3, sharp=55, luma_scaling=14, grain_chroma=False)
    out = grain


    ending = shinyori_ed01.filtering(src, *ed)
    final = lvf.rfs(out, ending, [ed])

    return depth(final, 10)
Beispiel #28
0
 def _transpose_shift(n, f, clip):
     try:
         h = f.props.descaleResolution
     except:
         raise ValueError(
             f"smart_reupscale: 'This clip was not descaled using smart_descale'"
         )
     w = get_w(h)
     clip = util.get_scale_filter(kernel, b=b, c=c, taps=taps)(clip,
                                                               width=w,
                                                               height=h * 2,
                                                               src_top=.5)
     return core.std.Transpose(clip)
Beispiel #29
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 32)
    edstart, edend = 14969, src.num_frames-1


    denoise = mvf.BM3D(src, 1.1, radius1=1, depth=16)
    out = denoise




    antialias = lvf.sraa(out, 2, 13, downscaler=core.resize.Bicubic, gamma=500, nrad=2, mdis=16)
    out = antialias



    deband_mask = lvf.denoise.detail_mask(out, brz_a=2250, brz_b=1600).std.Median()
    deband = dbs.f3kbilateral(out, 17, 48, 48)
    deband_a = dbs.f3kbilateral(out, 22, 96, 96)
    deband = lvf.rfs(deband, deband_a, [(edstart, edend)])
    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband


    grain = core.grain.Add(out, 0.3, constant=True)
    out = grain


    endcard = endcard_source(r'endcards\yande.re 605709 albedo_(overlord) armor cleavage gun horns isekai_quartet maid overlord rem_(re_zero) tagme thighhighs uniform weapon youjo_senki.jpg', src)
    endcard_ar = endcard.width/endcard.height
    endcard_ev = bool(endcard.format.name == 'YUV420P8')

    endcard = depth(endcard, 16)
    endcard = gf.MaskedDHA(endcard, rx=2.0, ry=2.0, darkstr=0.3, brightstr=1.0, maskpull=48, maskpush=140)


    if endcard_ar > 16/9:
        w, h = get_w(src.height, endcard_ar, only_even=endcard_ev), src.height
    elif endcard_ar < 16/9:
        w, h = src.width, get_h(src.width, endcard_ar, only_even=endcard_ev)
    else:
        w, h = src.width, src.height

    endcard = core.resize.Bicubic(endcard, w, h, range_in=1, range=0, dither_type='error_diffusion')
    endcard = lvf.sraa(endcard, 1.45, 7)
    final = core.std.Splice([out, endcard * (17263 - src.num_frames)], mismatch=True)


    return core.resize.Bicubic(final, format=vs.YUV420P10, dither_type='error_diffusion')
Beispiel #30
0
def do_filter():
    """Vapoursynth filtering"""
    src = JPBD.src_cut
    src = depth(src, 32)

    denoise = mvf.BM3D(src, 1.1, radius1=1, depth=16)
    out = denoise

    antialias = lvf.sraa(out,
                         2,
                         13,
                         downscaler=core.resize.Bicubic,
                         gamma=500,
                         nrad=2,
                         mdis=16)
    out = antialias

    deband_mask = lvf.denoise.detail_mask(out, brz_a=2250,
                                          brz_b=1600).std.Median()
    deband = dbs.f3kbilateral(out, 17, 48, 48)
    deband = core.std.MaskedMerge(deband, out, deband_mask)
    out = deband

    grain = core.grain.Add(out, 0.3, constant=True)
    out = grain

    endcard = endcard_source(
        r'endcards\yande.re 622847 animal_ears armor chibi dress emilia_(re_zero) firo horns isekai_quartet neko overlord pack_(re_zero) raphtalia uniform wallpaper youjo_senki.jpg',
        src)
    endcard_ar = endcard.width / endcard.height
    endcard_ev = bool(endcard.format.name == 'YUV420P8')

    if endcard_ar > 16 / 9:
        w, h = get_w(src.height, endcard_ar, only_even=endcard_ev), src.height
    elif endcard_ar < 16 / 9:
        w, h = src.width, get_h(src.width, endcard_ar, only_even=endcard_ev)
    else:
        w, h = src.width, src.height

    endcard = core.resize.Bicubic(endcard,
                                  w,
                                  h,
                                  range_in=1,
                                  range=0,
                                  dither_type='error_diffusion')
    final = core.std.Splice([out, endcard * (17263 - src.num_frames)],
                            mismatch=True)

    return core.resize.Bicubic(final,
                               format=vs.YUV420P10,
                               dither_type='error_diffusion')