Пример #1
0
def detail_mask(clip: vs.VideoNode,
                sigma: float = 1.0, rxsigma: List[int] = [50, 200, 350],
                pf_sigma: Optional[float] = 1.0,
                rad: int = 3, brz: Tuple[int, int] = (2500, 4500),
                rg_mode: int = 17,
                ) -> vs.VideoNode:
    """
    A detail mask aimed at preserving as much detail as possible
    within darker areas, even if it contains mostly noise.
    """
    from kagefunc import kirsch
    from vsutil import iterate

    bits, clip = _get_bits(clip)

    clip_y = get_y(clip)
    pf = core.bilateral.Gaussian(clip_y, sigma=pf_sigma) if pf_sigma else clip_y
    ret = core.retinex.MSRCP(pf, sigma=rxsigma, upper_thr=0.005)

    blur_ret = core.bilateral.Gaussian(ret, sigma=sigma)
    blur_ret_diff = core.std.Expr([blur_ret, ret], "x y -")
    blur_ret_dfl = core.std.Deflate(blur_ret_diff)
    blur_ret_ifl = iterate(blur_ret_dfl, core.std.Inflate, 4)
    blur_ret_brz = core.std.Binarize(blur_ret_ifl, brz[0])
    # blur_ret_brz = core.morpho.Close(blur_ret_brz, size=8)  # No longer in R55

    kirsch_mask = kirsch(clip_y).std.Binarize(brz[1])
    kirsch_ifl = kirsch_mask.std.Deflate().std.Inflate()
    kirsch_brz = core.std.Binarize(kirsch_ifl, brz[1])
    # kirsch_brz = core.morpho.Close(kirsch_brz, size=4)    # No longer in R55

    merged = core.std.Expr([blur_ret_brz, kirsch_brz], "x y +")
    rm_grain = core.rgvs.RemoveGrain(merged, rg_mode)
    return rm_grain if bits == 16 else depth(rm_grain, bits)
Пример #2
0
def kirsch_aa_mask(clip: vs.VideoNode, mthr: float = 0.25) -> vs.VideoNode:
    """
    Kirsh-based AA mask.

    Dependencies:
    * kagefunc

    :param clip: Input clip
    :param mthr: Mask threshold, scaled to clip range if between 0 and 1 (inclusive).
                 (Default: 0.25)
    """
    try:
        from kagefunc import kirsch
    except ModuleNotFoundError:
        raise ModuleNotFoundError(
            "kirsch_aa_mask: missing dependency 'kagefunc'")

    return kirsch(get_y(clip)).std.Binarize(scale_thresh(
        mthr, clip)).std.Maximum().std.Convolution([1] * 9)
Пример #3
0
def RainbowSmooth(clip, radius=3, lthresh=0, hthresh=220, mask="original"):
    core = vs.core
    
    if isinstance(mask, str):
        if mask == "original":
            mask = core.std.Expr(clips=[clip.std.Maximum(planes=0), clip.std.Minimum(planes=0)], expr=["x y - 90 > 255 x y - 255 90 / * ?", "", ""])
        elif mask == "prewitt":
            mask = core.std.Prewitt(clip=clip, planes=0)
        elif mask == "sobel":
            mask = core.std.Sobel(clip=clip, planes=0)
        elif mask == "tcanny":
            mask = core.tcanny.TCanny(clip)
        elif mask == "fast_sobel":
            import kagefunc as kage

            mask = kage.fast_sobel(clip)
        elif mask == "kirsch":
            import kagefunc as kage

            mask = kage.kirsch(clip)
        elif mask == "retinex_edgemask":
            import kagefunc as kage

            mask = kage.retinex_edgemask(clip)

    lderain = clip

    if lthresh > 0:
        lderain = clip.smoothuv.SmoothUV(radius=radius, threshold=lthresh, interlaced=False)

    hderain = clip.smoothuv.SmoothUV(radius=radius, threshold=hthresh, interlaced=False)

    if hthresh > lthresh:
        return core.std.MaskedMerge(clipa=lderain, clipb=hderain, mask=mask, planes=[1, 2], first_plane=True)
    else:
        return lderain
Пример #4
0
def nneedi3_clamp(clip: vs.VideoNode,
                  strength: float = 1,
                  mask: Optional[vs.VideoNode] = None,
                  ret_mask: bool = False,
                  mthr: float = 0.25,
                  show_mask: bool = False,
                  opencl: bool = False,
                  nnedi3cl: Optional[bool] = None,
                  eedi3cl: Optional[bool] = None) -> vs.VideoNode:
    """
    A function that clamps eedi3 to nnedi3 for the purpose of reducing eedi3 artifacts.
    This should fix every issue created by eedi3. For example: https://i.imgur.com/hYVhetS.jpg

    Original function written by Zastin, modified by LightArrowsEXE.

    Dependencies:
    * kagefunc (optional: retinex edgemask)
    * vapoursynth-retinex (optional: retinex edgemask)
    * vapoursynth-tcanny (optional: retinex edgemask)
    * vapoursynth-eedi3
    * vapoursynth-nnedi3
    * vapoursynth-nnedi3cl (optional: opencl)

    :param clip:                Input clip
    :param strength:            Set threshold strength for over/underflow value for clamping eedi3's result
                                to nnedi3 +/- strength * 256 scaled to 8 bit (Default: 1)
    :param mask:                Clip to use for custom mask (Default: None)
    :param ret_mask:            Replace default mask with a retinex edgemask (Default: False)
    :param mthr:                Binarize threshold for the mask, scaled to float (Default: 0.25)
    :param show_mask:           Return mask instead of clip (Default: False)
    :param opencl:              OpenCL acceleration (Default: False)
    :param nnedi3cl:            OpenCL acceleration for nnedi3 (Default: False)
    :param eedi3cl:             OpenCL acceleration for eedi3 (Default: False)

    :return:                    Antialiased clip
    """

    if clip.format is None:
        raise ValueError(
            "nneedi3_clamp: 'Variable-format clips not supported'")

    clip_y = get_y(clip)

    bits = clip.format.bits_per_sample
    sample_type = clip.format.sample_type
    shift = bits - 8
    thr = strength * (
        1 >> shift) if sample_type == vs.INTEGER else strength / 219
    expr = 'x z - y z - xor y x y {0} + min y {0} - max ?'.format(thr)

    if sample_type == vs.INTEGER:
        mthr = round(mthr * ((1 >> shift) - 1))

    if mask is None:
        try:
            from kagefunc import kirsch
        except ModuleNotFoundError:
            raise ModuleNotFoundError(
                "nnedi3_clamp: missing dependency 'kagefunc'")
        mask = kirsch(clip_y)
        if ret_mask:
            # workaround to support float input
            ret = depth(clip_y, min(16, bits))
            ret = core.retinex.MSRCP(ret,
                                     sigma=[50, 200, 350],
                                     upper_thr=0.005)
            ret = depth(ret, bits)
            tcanny = core.tcanny.TCanny(ret, mode=1, sigma=[1.0])
            tcanny = core.std.Minimum(tcanny,
                                      coordinates=[1, 0, 1, 0, 0, 1, 0, 1])
            # no clamping needed when binarizing
            mask = core.std.Expr([mask, tcanny], 'x y +')
        mask = mask.std.Binarize(thr).std.Maximum().std.Convolution([1] * 9)

    nnedi3cl = fallback(nnedi3cl, opencl)
    eedi3cl = fallback(eedi3cl, opencl)

    nnedi3_args: Dict[str, Any] = dict(nsize=3, nns=3, qual=1)
    eedi3_args: Dict[str, Any] = dict(alpha=0.25,
                                      beta=0.5,
                                      gamma=40,
                                      nrad=2,
                                      mdis=20)

    clip_tra = core.std.Transpose(clip_y)

    if eedi3cl:
        strong = core.eedi3m.EEDI3CL(clip_tra, 0, True, **eedi3_args)
        strong = core.resize.Spline36(strong, height=clip.width, src_top=0.5)
        strong = core.std.Transpose(strong)
        strong = core.eedi3m.EEDI3CL(strong, 0, True, **eedi3_args)
        strong = core.resize.Spline36(strong, height=clip.height, src_top=0.5)
    else:
        strong = core.eedi3m.EEDI3(clip_tra,
                                   0,
                                   True,
                                   mclip=mask.std.Transpose(),
                                   **eedi3_args)
        strong = core.resize.Spline36(strong, height=clip.width, src_top=0.5)
        strong = core.std.Transpose(strong)
        strong = core.eedi3m.EEDI3(strong, 0, True, mclip=mask, **eedi3_args)
        strong = core.resize.Spline36(strong, height=clip.height, src_top=0.5)

    nnedi3: Callable[..., vs.VideoNode] = core.nnedi3.nnedi3
    if nnedi3cl:
        nnedi3 = core.nnedi3cl.NNEDI3CL

    weak = nnedi3(clip_tra, 0, True, **nnedi3_args)
    weak = core.resize.Spline36(weak, height=clip.width, src_top=0.5)
    weak = core.std.Transpose(weak)
    weak = nnedi3(weak, 0, True, **nnedi3_args)
    weak = core.resize.Spline36(weak, height=clip.height, src_top=0.5)

    aa = core.std.Expr([strong, weak, clip_y], expr)

    merged = core.std.MaskedMerge(clip_y, aa, mask)

    if show_mask:
        return mask
    return merged if clip.format.color_family == vs.GRAY else core.std.ShufflePlanes(
        [merged, clip], [0, 1, 2], vs.YUV)
Пример #5
0
def faggotdb_mod(clip: vs.VideoNode,
                 thrY=40,
                 thrC=None,
                 radiusY=15,
                 radiusC=15,
                 CbY=44,
                 CrY=44,
                 CbC=44,
                 CrC=44,
                 grainY=32,
                 grainC=None,
                 grainCC=0,
                 sample_mode=2,
                 neo=True,
                 dynamic_grainY=False,
                 dynamic_grainC=False,
                 tv_range=True,
                 mask="retinex",
                 binarize=False,
                 binarize_thr=70,
                 grayscale=True,
                 bitresamp=False,
                 outbits=None,
                 blurmask=True,
                 horizblur=2,
                 vertblur=2) -> vs.VideoNode:

    funcName = "faggotdb_mod"  # name kept to be fallback compatible

    # Original Idea: Author who created Fag3kdb. Edited by AlucardSama04; additional modifications by l00t

    if not isinstance(clip, vs.VideoNode):
        raise TypeError(f"{funcName}: This is not a clip")

    if outbits is None:
        outbits = clip.format.bits_per_sample

    if bitresamp:
        if clip.format.bits_per_sample != outbits:
            clip = fvf.Depth(
                clip,
                bits=outbits)  # instead of error, auto convert to 16 bits
    elif clip.format.bits_per_sample != outbits:
        raise TypeError(f"{funcName}: Input-output bitdepth mismatch")

    # if not isinstance(mask, vs.VideoNode):
    # raise vs.Error(f"{funcName}: mask' only clip inputs")

    if mask in [-1]:  # more user friendly if we do the masking intentionally
        mask = clip
        blurmask = False
    elif mask in [0, "retinex"]:
        mask = kgf.retinex_edgemask(clip)
    elif mask in [1, "kirsch"]:
        mask = kgf.kirsch(clip)
    elif mask in [2, "Sobel"]:
        mask = core.std.Sobel(clip, scale=1)
    elif mask in [3, "Prewitt"]:
        mask = core.std.Prewitt(clip)
    elif mask in [4, "GF"]:
        mask = fvf.GradFun3(clip, mask=2, debug=1)
    else:
        raise ValueError(f"{funcName}: Unknown Mask Mode")

    if grayscale:
        mask = core.std.ShufflePlanes(mask, planes=0, colorfamily=vs.GRAY)

    if binarize:  # binarize threshold should be adjusted according to bitdepth
        mask = core.std.Binarize(mask, threshold=binarize_thr)

    if blurmask:
        mask = core.std.BoxBlur(mask, hradius=horizblur, vradius=vertblur)

    if thrC is None:
        thrC = int(round(thrY / 2))

    if grainC is None:
        grainC = int(round(grainY / 2))

    if grainCC is None:
        grainCC = 0

    f3kdb = core.neo_f3kdb.Deband if neo else core.f3kdb.Deband

    U = plane(clip, 1)
    V = plane(clip, 2)

    U = f3kdb(U,
              range=radiusC,
              y=thrC,
              cb=CbC,
              cr=CrC,
              grainy=grainC,
              grainc=0,
              sample_mode=sample_mode,
              dynamic_grain=dynamic_grainC,
              keep_tv_range=tv_range,
              output_depth=outbits)

    V = f3kdb(V,
              range=radiusC,
              y=thrC,
              cb=CbC,
              cr=CrC,
              grainy=grainC,
              grainc=0,
              sample_mode=sample_mode,
              dynamic_grain=dynamic_grainC,
              keep_tv_range=tv_range,
              output_depth=outbits)

    filtered = core.std.ShufflePlanes([clip, U, V], [0, 0, 0], vs.YUV)

    filtered = f3kdb(filtered,
                     range=radiusY,
                     y=thrY,
                     cb=CbY,
                     cr=CrY,
                     grainy=grainY,
                     grainc=grainCC,
                     sample_mode=sample_mode,
                     dynamic_grain=dynamic_grainY,
                     keep_tv_range=tv_range,
                     output_depth=outbits
                     )  # if grainCC > 0 UV planes will be debanded once again

    return core.std.MaskedMerge(filtered, clip, mask)