Skip to content

deblock

dpir module-attribute

dpir = DEBLOCK

deblock_qed

deblock_qed(
    clip: VideoNode,
    quant_edge: int = 24,
    quant_inner: int = 26,
    alpha_edge: int = 1,
    beta_edge: int = 2,
    alpha_inner: int = 1,
    beta_inner: int = 2,
    chroma_mode: int = 0,
    align: Align = TOP_LEFT,
    planes: PlanesT = None,
) -> VideoNode

A postprocessed Deblock: Uses full frequencies of Deblock's changes on block borders, but DCT-lowpassed changes on block interiours.

Parameters:

  • clip

    (VideoNode) –

    Clip to process.

  • quant_edge

    (int, default: 24 ) –

    Strength of block edge deblocking.

  • quant_inner

    (int, default: 26 ) –

    Strength of block internal deblocking.

  • alpha_edge

    (int, default: 1 ) –

    Halfway "sensitivity" and halfway a strength modifier for borders.

  • beta_edge

    (int, default: 2 ) –

    "Sensitivity to detect blocking" for borders.

  • alpha_inner

    (int, default: 1 ) –

    Halfway "sensitivity" and halfway a strength modifier for block interiors.

  • beta_inner

    (int, default: 2 ) –

    "Sensitivity to detect blocking" for block interiors.

  • chroma_mode

    (int, default: 0 ) –

    Chroma deblocking behaviour. - 0 = use proposed method for chroma deblocking - 1 = directly use chroma deblock from the normal Deblock - 2 = directly use chroma deblock from the strong Deblock

  • align

    (Align, default: TOP_LEFT ) –

    Where to align the blocks for eventual padding.

  • planes

    (PlanesT, default: None ) –

    What planes to process.

Returns:

  • VideoNode

    Deblocked clip

Source code
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
def deblock_qed(
    clip: vs.VideoNode,
    quant_edge: int = 24,
    quant_inner: int = 26,
    alpha_edge: int = 1, beta_edge: int = 2,
    alpha_inner: int = 1, beta_inner: int = 2,
    chroma_mode: int = 0,
    align: Align = Align.TOP_LEFT,
    planes: PlanesT = None
) -> vs.VideoNode:
    """
    A postprocessed Deblock: Uses full frequencies of Deblock's changes on block borders,
    but DCT-lowpassed changes on block interiours.

    :param clip:            Clip to process.
    :param quant_edge:      Strength of block edge deblocking.
    :param quant_inner:     Strength of block internal deblocking.
    :param alpha_edge:      Halfway "sensitivity" and halfway a strength modifier for borders.
    :param beta_edge:       "Sensitivity to detect blocking" for borders.
    :param alpha_inner:     Halfway "sensitivity" and halfway a strength modifier for block interiors.
    :param beta_inner:      "Sensitivity to detect blocking" for block interiors.
    :param chroma_mode:      Chroma deblocking behaviour.
                            - 0 = use proposed method for chroma deblocking
                            - 1 = directly use chroma deblock from the normal Deblock
                            - 2 = directly use chroma deblock from the strong Deblock
    :param align:           Where to align the blocks for eventual padding.
    :param planes:          What planes to process.

    :return:                Deblocked clip
    """
    func = FunctionUtil(clip, deblock_qed, planes)
    if not func.chroma:
        chroma_mode = 0

    with padder.ctx(8, align=align) as p8:
        clip = p8.MIRROR(func.work_clip)

        block = padder.COLOR(
            clip.std.BlankClip(
                width=6, height=6, length=1, color=0,
                format=func.work_clip.format.replace(color_family=vs.GRAY, subsampling_w=0, subsampling_h=0)
            ), 1, 1, 1, 1, True
        )
        block = core.std.StackHorizontal([block] * (clip.width // block.width))
        block = core.std.StackVertical([block] * (clip.height // block.height))

        if func.chroma:
            blockc = block.std.CropAbs(*get_plane_sizes(clip, 1))
            block = join(block, blockc, blockc)

        block = block * clip.num_frames

        normal, strong = (
            clip.deblock.Deblock(quant_edge, alpha_edge, beta_edge, func.norm_planes if chroma_mode < 2 else 0),
            clip.deblock.Deblock(quant_inner, alpha_inner, beta_inner, func.norm_planes if chroma_mode != 1 else 0)
        )

        normalD2, strongD2 = (
            norm_expr([clip, dclip, block], 'z x y - 0 ? neutral +', planes)
            for dclip in (normal, strong)
        )

        with padder.ctx(16, align=align) as p16:
            strongD2 = p16.CROP(
                norm_expr(p16.MIRROR(strongD2), 'x neutral - 1.01 * neutral +', planes)
                .dctf.DCTFilter([1, 1, 0, 0, 0, 0, 0, 0], planes)
            )

        strongD4 = norm_expr([strongD2, normalD2], 'y neutral = x y ?', planes)
        deblocked = clip.std.MakeDiff(strongD4, planes)

        if func.chroma and chroma_mode:
            deblocked = join([deblocked, strong if chroma_mode == 2 else normal])

        deblocked = p8.CROP(deblocked)

    return func.return_clip(deblocked)

dpir_mask

dpir_mask(
    clip: VideoNode,
    low: float = 5,
    high: float = 10,
    lines: float | None = None,
    luma_scaling: float = 12,
    linemask: GenericMaskT | bool = True,
    relative: bool = False,
) -> VideoNode
Source code
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
def dpir_mask(
    clip: vs.VideoNode, low: float = 5, high: float = 10, lines: float | None = None,
    luma_scaling: float = 12, linemask: GenericMaskT | bool = True, relative: bool = False
) -> vs.VideoNode:
    y = depth(get_y(clip), 32)

    if linemask is True:
        linemask = FDoG

    mask = adg_mask(y, luma_scaling, relative, func=dpir_mask)

    if relative:
        mask = gauss_blur(mask, 1.5)

    mask = norm_expr(mask, f'{high} 255 / x {low} 255 / * -')

    if linemask:
        lines = fallback(lines, high)
        linemask = normalize_mask(linemask, y)

        lines_clip = mask.std.BlankClip(color=lines / 255)

        mask = mask.std.MaskedMerge(lines_clip, linemask)

    return mask

mpeg2stinx

mpeg2stinx(
    clip: VideoNode,
    bobber: VSFunction | None = None,
    radius: int | tuple[int, int] = 2,
    limit: float | None = 1.0,
) -> VideoNode

This filter is designed to eliminate certain combing-like compression artifacts that show up all too often in hard-telecined MPEG-2 encodes, and works to a smaller extent on bitrate-starved hard-telecined AVC as well. General artifact removal is better accomplished with actual denoisers.

Parameters:

  • clip

    (VideoNode) –

    Clip to process

  • bobber

    (VSFunction | None, default: None ) –

    Callable to use in place of the internal deinterlacing filter.

  • radius

    (int | tuple[int, int], default: 2 ) –

    x, y radius of min-max clipping (i.e. repair) to remove artifacts.

  • limit

    (float | None, default: 1.0 ) –

    If specified, temporal limiting is used, where the changes by crossfieldrepair are limited to this times the difference between the current frame and its neighbours.

Returns:

  • VideoNode

    Clip with cross-field noise reduced.

Source code
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
def mpeg2stinx(
        clip: vs.VideoNode, bobber: VSFunction | None = None,
        radius: int | tuple[int, int] = 2, limit: float | None = 1.0
    ) -> vs.VideoNode:
    """
    This filter is designed to eliminate certain combing-like compression artifacts that show up all too often
    in hard-telecined MPEG-2 encodes, and works to a smaller extent on bitrate-starved hard-telecined AVC as well.
    General artifact removal is better accomplished with actual denoisers.

    :param clip:       Clip to process
    :param bobber:     Callable to use in place of the internal deinterlacing filter.
    :param radius:     x, y radius of min-max clipping (i.e. repair) to remove artifacts.
    :param limit:      If specified, temporal limiting is used, where the changes by crossfieldrepair
                       are limited to this times the difference between the current frame and its neighbours.

    :return:           Clip with cross-field noise reduced.
    """

    def crossfield_repair(clip: vs.VideoNode, bobbed: vs.VideoNode) -> vs.VideoNode:
        even, odd = bobbed[::2], bobbed[1::2]

        if sw == 1 and sh == 1:
            repair_even, repair_odd = repair(clip, even, 1), repair(clip, odd, 1)
        else:
            inpand_even, expand_even = Morpho.inpand(even, sw, sh), Morpho.expand(even, sw, sh)
            inpand_odd, expand_odd = Morpho.inpand(odd, sw, sh), Morpho.expand(odd, sw, sh)

            repair_even, repair_odd = (
                MeanMode.MEDIAN([clip, inpand_even, expand_even]),
                MeanMode.MEDIAN([clip, inpand_odd, expand_odd])
            )

        repaired = core.std.Interleave([repair_even, repair_odd]).std.SeparateFields(True)

        return repaired.std.SelectEvery(4, (2, 1)).std.DoubleWeave()[::2]

    def temporal_limit(src: vs.VideoNode, flt: vs.VideoNode) -> vs.VideoNode:
        if limit is None:
            return flt

        diff = norm_expr([core.std.Interleave([src] * 2), adj], 'x y - abs').std.SeparateFields(True)
        diff = norm_expr([diff.std.SelectEvery(4, (0, 1)), diff.std.SelectEvery(4, (2, 3))], 'x y min')
        diff = Morpho.expand(diff, sw=2, sh=1).std.DoubleWeave()[::2]

        return norm_expr([flt, src, diff], 'x y z {limit} * - y z {limit} * + clip', limit=limit)

    def default_bob(clip: vs.VideoNode) -> vs.VideoNode:
        bobbed = Nnedi3(field=3).interpolate(clip, double_y=False)
        return clip.bwdif.Bwdif(field=3, edeint=bobbed)

    if (fb := FieldBased.from_video(clip, False, mpeg2stinx)).is_inter:
        raise UnsupportedFieldBasedError('Interlaced input is not supported!', mpeg2stinx, fb)

    sw, sh = normalize_seq(radius, 2)

    if not bobber:
        bobber = default_bob

    if limit is not None:
        adj = shift_clip_multi(clip)
        adj.pop(1)
        adj = core.std.Interleave(adj)

    fixed1 = temporal_limit(clip, crossfield_repair(clip, bobber(clip)))
    fixed2 = temporal_limit(fixed1, crossfield_repair(fixed1, bobber(fixed1)))

    return fixed1.std.Merge(fixed2).std.SetFieldBased(0)