Skip to content

debanders

Functions:

  • f3k_deband

    Debanding filter wrapper using the vszip.Deband plugin.

  • mdb_bilateral

    Multi stage debanding, bilateral-esque filter.

  • pfdeband

    Prefilter and deband a clip.

  • placebo_deband

    Debanding wrapper around the placebo.Deband filter from the VapourSynth vs-placebo plugin.

logger module-attribute

logger = getLogger(__name__)

F3KDeband

F3KDeband(f3k_deband: Callable[P, R])

Class decorator that wraps the f3k_deband function and extends its functionality.

It is not meant to be used directly.

Classes:

  • RandomAlgo

    Random number generation algorithm used for reference positions or grain patterns.

  • SampleMode

    Enum that determines how reference pixels are sampled for debanding.

Methods:

Source code in vsdeband/debanders.py
29
30
def __init__(self, f3k_deband: Callable[P, R]) -> None:
    self._func = f3k_deband

RandomAlgo

RandomAlgo(value: int, sigma: float | None = None)

Bases: CustomIntEnum

Random number generation algorithm used for reference positions or grain patterns.

Methods:

  • __call__

    Configure the standard deviation for the GAUSSIAN algorithm.

  • from_param

    Return the enum value from a parameter.

  • value

Attributes:

  • GAUSSIAN

    Gaussian distribution. Supports custom standard deviation via __call__.

  • OLD

    Legacy algorithm from older versions.

  • UNIFORM

    Uniform distribution for randomization.

  • sigma (float | None) –

    Standard deviation value used only for GAUSSIAN.

Source code in vsdeband/debanders.py
173
174
175
def __init__(self, value: int, sigma: float | None = None) -> None:
    self._value_ = value
    self.sigma = sigma

GAUSSIAN class-attribute instance-attribute

GAUSSIAN = 2

Gaussian distribution. Supports custom standard deviation via __call__.

OLD class-attribute instance-attribute

OLD = 0

Legacy algorithm from older versions.

UNIFORM class-attribute instance-attribute

UNIFORM = 1

Uniform distribution for randomization.

sigma instance-attribute

sigma: float | None = sigma

Standard deviation value used only for GAUSSIAN.

__call__

__call__(sigma: float) -> Literal[GAUSSIAN]

Configure the standard deviation for the GAUSSIAN algorithm.

Only values in the range [-1.0, 1.0] are considered valid and used as multipliers. Values outside this range are ignored.

Parameters:

  • sigma
    (float) –

    Standard deviation used for the Gaussian distribution.

Returns:

Source code in vsdeband/debanders.py
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
def __call__(  # type: ignore[misc]
    self: Literal[F3KDeband.RandomAlgo.GAUSSIAN],  # pyright: ignore[reportGeneralTypeIssues]
    sigma: float,
    /,
) -> Literal[F3KDeband.RandomAlgo.GAUSSIAN]:
    """
    Configure the standard deviation for the GAUSSIAN algorithm.

    Only values in the range `[-1.0, 1.0]` are considered valid and used as multipliers.
    Values outside this range are ignored.

    Args:
        sigma: Standard deviation used for the Gaussian distribution.

    Returns:
        A new instance of GAUSSIAN with the given `sigma`.
    """
    assert self is F3KDeband.RandomAlgo.GAUSSIAN

    new_enum = CustomIntEnum(self.__class__.__name__, F3KDeband.RandomAlgo.__members__)  # type: ignore
    member = getattr(new_enum, self.name)
    member.sigma = sigma

    return member

from_param classmethod

from_param(value: Any, func_except: FuncExcept | None = None) -> Self

Return the enum value from a parameter.

Parameters:

  • value
    (Any) –

    Value to instantiate the enum class.

  • func_except
    (FuncExcept | None, default: None ) –

    Exception function.

Returns:

  • Self

    Enum value.

Raises:

Source code in jetpytools/enums/base.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@classmethod
def from_param(cls, value: Any, func_except: FuncExcept | None = None) -> Self:
    """
    Return the enum value from a parameter.

    Args:
        value: Value to instantiate the enum class.
        func_except: Exception function.

    Returns:
        Enum value.

    Raises:
        NotFoundEnumValue: Variable not found in the given enum.
    """
    func_except = func_except or cls.from_param

    try:
        return cls(value)
    except (ValueError, TypeError):
        pass

    if isinstance(func_except, tuple):
        func_name, var_name = func_except
    else:
        func_name, var_name = func_except, repr(cls)

    raise NotFoundEnumValueError(
        'The given value for "{var_name}" argument must be a valid {enum_name}, not "{value}"!\n'
        "Valid values are: [{readable_enum}].",
        func_name,
        var_name=var_name,
        enum_name=cls,
        value=value,
        readable_enum=(f"{name} ({value!r})" for name, value in cls.__members__.items()),
        reason=value,
    ) from None

value

value() -> int
Source code in jetpytools/enums/base.py
86
87
@enum_property
def value(self) -> int: ...

SampleMode

SampleMode(value: int, **kwargs: Any)

Bases: CustomIntEnum

Enum that determines how reference pixels are sampled for debanding.

Methods:

  • __call__

    Configure MEAN_DIFF with either individual values or sequences.

  • from_param

    Return the enum value from a parameter.

  • value

Attributes:

  • COLUMN

    Column references (vertical pair).

  • COL_ROW_MEAN

    Average of modes COLUMN and ROW.

  • MEAN_DIFF_FLOAT

    Similar to COL_ROW_MEAN but uses multiple thresholds for detail preservation.

  • MEAN_DIFF_GRADIENT

    An extension of MEAN_DIFF_FLOAT that adds a gradient angle check for more intelligent detail preservation.

  • MEAN_DIFF_INT

    Detail-preserving mode using additional thresholds (thr1, thr2).

  • ROW

    Row references (horizontal pair).

  • SQUARE

    Square references (four points).

  • kwargs (dict[str, Any]) –

    Additional keyword arguments.

Source code in vsdeband/debanders.py
43
44
45
def __init__(self, value: int, **kwargs: Any) -> None:
    self._value_ = value
    self.kwargs = kwargs

COLUMN class-attribute instance-attribute

COLUMN = 1

Column references (vertical pair).

COL_ROW_MEAN class-attribute instance-attribute

COL_ROW_MEAN = 4

Average of modes COLUMN and ROW.

MEAN_DIFF_FLOAT class-attribute instance-attribute

MEAN_DIFF_FLOAT = 6

Similar to COL_ROW_MEAN but uses multiple thresholds for detail preservation.

MEAN_DIFF_GRADIENT class-attribute instance-attribute

MEAN_DIFF_GRADIENT = 7

An extension of MEAN_DIFF_FLOAT that adds a gradient angle check for more intelligent detail preservation.

MEAN_DIFF_INT class-attribute instance-attribute

MEAN_DIFF_INT = 5

Detail-preserving mode using additional thresholds (thr1, thr2).

ROW class-attribute instance-attribute

ROW = 3

Row references (horizontal pair).

SQUARE class-attribute instance-attribute

SQUARE = 2

Square references (four points).

kwargs instance-attribute

kwargs: dict[str, Any] = kwargs

Additional keyword arguments.

__call__

__call__(
    thr_max: float | Sequence[float] | None = None,
    thr_mid: float | Sequence[float] | None = None,
) -> MeanDiffT
__call__(
    thr_max: float | Sequence[float] | None = None,
    thr_mid: float | Sequence[float] | None = None,
    angle_boost: float | None = None,
    max_angle: float | None = None,
) -> Literal[MEAN_DIFF_GRADIENT]
__call__(
    thr_max: float | Sequence[float] | None = None,
    thr_mid: float | Sequence[float] | None = None,
    angle_boost: float | None = None,
    max_angle: float | None = None,
) -> Any

Configure MEAN_DIFF with either individual values or sequences.

thr_max or thr1 in vszip

These are detail protection thresholds (max difference).

This threshold applies to the maxDif check. maxDif is the largest absolute difference found between the current pixel and any of its four individual cross-shaped reference pixels. If this maxDif is greater than or equal to any of the thresholds, the pixel is considered detail.

It helps protect sharp edges and fine details from being blurred by the debanding process.

thr_mid or thr2 in vszip

These are gradient / texture protection thresholds (mid-pair difference).

This threshold applies to the midDif checks. midDif measures how much the current pixel deviates from the midpoint of a pair of opposing reference pixels (one check for the vertical pair, one for the horizontal pair). If the current pixel is far from this midpoint (i.e., midDif is greater than or equal to any of the thresholds), it might indicate a texture.

This helps distinguish true banding in gradients from textured areas or complex details.

Parameters:

  • thr_max
    (float | Sequence[float] | None, default: None ) –

    Detail protection threshold (thr1 in vszip) for respective planes. Applies to the max difference check.

  • thr_mid
    (float | Sequence[float] | None, default: None ) –

    Gradient/Texture protection threshold (thr2 in vszip) for respective planes. Applies to the midpoint difference check.

  • angle_boost
    (float | None, default: None ) –

    Multiplier to increase the debanding strength on consistent gradients.

  • max_angle
    (float | None, default: None ) –

    Threshold for the gradient angle check.

Returns:

  • Any

    The configured enum.

Source code in vsdeband/debanders.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
def __call__(
    self,
    thr_max: float | Sequence[float] | None = None,
    thr_mid: float | Sequence[float] | None = None,
    angle_boost: float | None = None,
    max_angle: float | None = None,
) -> Any:
    """
    Configure `MEAN_DIFF` with either individual values or sequences.

    ## `thr_max` or `thr1` in vszip
    These are detail protection thresholds (max difference).

    This threshold applies to the maxDif check.
    maxDif is the largest absolute difference found between the current pixel
    and any of its four individual cross-shaped reference pixels.
    If this maxDif is greater than or equal to any of the thresholds, the pixel is considered detail.

    It helps protect sharp edges and fine details from being blurred by the debanding process.

    ## `thr_mid` or `thr2` in vszip
    These are gradient / texture protection thresholds (mid-pair difference).

    This threshold applies to the midDif checks.
    midDif measures how much the current pixel deviates from the midpoint of a pair of opposing reference pixels
    (one check for the vertical pair, one for the horizontal pair).
    If the current pixel is far from this midpoint (i.e., midDif is greater than or equal
    to any of the thresholds), it might indicate a texture.

    This helps distinguish true banding in gradients from textured areas or complex details.

    Args:
        thr_max: Detail protection threshold (`thr1` in vszip) for respective planes.
            Applies to the max difference check.
        thr_mid: Gradient/Texture protection threshold (`thr2` in vszip) for respective planes.
            Applies to the midpoint difference check.
        angle_boost: Multiplier to increase the debanding strength on consistent gradients.
        max_angle: Threshold for the gradient angle check.

    Returns:
        The configured enum.
    """
    assert self >= 5

    new_enum = CustomIntEnum(self.__class__.__name__, F3KDeband.SampleMode.__members__)  # type: ignore
    member = getattr(new_enum, self.name)
    member.kwargs = dict[str, Any](thr1=thr_max, thr2=thr_mid)

    if self is F3KDeband.SampleMode.MEAN_DIFF_GRADIENT:
        member.kwargs.update(angle_boost=angle_boost, max_angle=max_angle)

    return member

from_param classmethod

from_param(value: Any, func_except: FuncExcept | None = None) -> Self

Return the enum value from a parameter.

Parameters:

  • value
    (Any) –

    Value to instantiate the enum class.

  • func_except
    (FuncExcept | None, default: None ) –

    Exception function.

Returns:

  • Self

    Enum value.

Raises:

Source code in jetpytools/enums/base.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@classmethod
def from_param(cls, value: Any, func_except: FuncExcept | None = None) -> Self:
    """
    Return the enum value from a parameter.

    Args:
        value: Value to instantiate the enum class.
        func_except: Exception function.

    Returns:
        Enum value.

    Raises:
        NotFoundEnumValue: Variable not found in the given enum.
    """
    func_except = func_except or cls.from_param

    try:
        return cls(value)
    except (ValueError, TypeError):
        pass

    if isinstance(func_except, tuple):
        func_name, var_name = func_except
    else:
        func_name, var_name = func_except, repr(cls)

    raise NotFoundEnumValueError(
        'The given value for "{var_name}" argument must be a valid {enum_name}, not "{value}"!\n'
        "Valid values are: [{readable_enum}].",
        func_name,
        var_name=var_name,
        enum_name=cls,
        value=value,
        readable_enum=(f"{name} ({value!r})" for name, value in cls.__members__.items()),
        reason=value,
    ) from None

value

value() -> int
Source code in jetpytools/enums/base.py
86
87
@enum_property
def value(self) -> int: ...

__call__

__call__(*args: P.args, **kwargs: P.kwargs) -> R
Source code in vsdeband/debanders.py
32
33
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
    return self._func(*args, **kwargs)

f3k_deband

f3k_deband(
    clip: VideoNode,
    radius: int = 16,
    thr: float | Sequence[float] = 96,
    grain: float | Sequence[float] = 0,
    planes: Planes = None,
    *,
    sample_mode: SampleMode = SQUARE,
    dynamic_grain: bool = False,
    blur_first: bool = True,
    seed: int | None = None,
    random: RandomAlgo | tuple[RandomAlgo, RandomAlgo] = UNIFORM,
    **kwargs: Any
) -> VideoNode

Debanding filter wrapper using the vszip.Deband plugin.

More information

https://github.com/dnjulek/vapoursynth-zip/wiki/Deband https://github.com/HomeOfAviSynthPlusEvolution/neo_f3kdb

Parameters:

  • clip

    (VideoNode) –

    Input clip.

  • radius

    (int, default: 16 ) –

    Radius used for banding detection. Valid range is [1, 255].

  • thr

    (float | Sequence[float], default: 96 ) –

    Banding detection threshold(s) for each plane. A pixel is considered banded if the difference with its reference pixel(s) is less than the corresponding threshold.

  • grain

    (float | Sequence[float], default: 0 ) –

    Amount of grain to add after debanding.

  • planes

    (Planes, default: None ) –

    Specifies which planes to process. Default is all planes.

  • sample_mode

    (SampleMode, default: SQUARE ) –

    Strategy used to sample reference pixels. See SampleMode.

  • dynamic_grain

    (bool, default: False ) –

    If True, generates a unique grain pattern for each frame.

  • blur_first

    (bool, default: True ) –

    If True, compares current pixel to the mean of surrounding pixels. If False, compares directly to all reference pixels. A pixel is marked as banded only if all pixel-wise differences are below threshold.

  • seed

    (int | None, default: None ) –

    Random seed for grain generation.

  • random

    (RandomAlgo | tuple[RandomAlgo, RandomAlgo], default: UNIFORM ) –

    Random number generation strategy. Can be a single value for both reference and grain, or a tuple specifying separate algorithms. See RandomAlgo.

  • **kwargs

    (Any, default: {} ) –

    Additional keyword arguments passed directly to the vszip.Deband plugin.

Returns:

  • VideoNode

    Debanded and optionally grained clip.

Source code in vsdeband/debanders.py
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
@F3KDeband
def f3k_deband(
    clip: vs.VideoNode,
    radius: int = 16,
    thr: float | Sequence[float] = 96,
    grain: float | Sequence[float] = 0,
    planes: Planes = None,
    *,
    sample_mode: F3KDeband.SampleMode = F3KDeband.SampleMode.SQUARE,
    dynamic_grain: bool = False,
    blur_first: bool = True,
    seed: int | None = None,
    random: F3KDeband.RandomAlgo | tuple[F3KDeband.RandomAlgo, F3KDeband.RandomAlgo] = F3KDeband.RandomAlgo.UNIFORM,
    **kwargs: Any,
) -> vs.VideoNode:
    """
    Debanding filter wrapper using the `vszip.Deband` plugin.

    More information:
        <https://github.com/dnjulek/vapoursynth-zip/wiki/Deband>
        <https://github.com/HomeOfAviSynthPlusEvolution/neo_f3kdb>

    Args:
        clip: Input clip.
        radius: Radius used for banding detection. Valid range is [1, 255].
        thr: Banding detection threshold(s) for each plane. A pixel is considered banded if the difference
            with its reference pixel(s) is less than the corresponding threshold.
        grain: Amount of grain to add after debanding.
        planes: Specifies which planes to process. Default is all planes.
        sample_mode: Strategy used to sample reference pixels.
            See [SampleMode][vsdeband.debanders.F3KDeband.SampleMode].
        dynamic_grain: If True, generates a unique grain pattern for each frame.
        blur_first: If True, compares current pixel to the mean of surrounding pixels. If False, compares directly to
            all reference pixels. A pixel is marked as banded only if all pixel-wise differences are below threshold.
        seed: Random seed for grain generation.
        random: Random number generation strategy. Can be a single value for both reference and grain, or a tuple
            specifying separate algorithms. See [RandomAlgo][vsdeband.debanders.F3KDeband.RandomAlgo].
        **kwargs: Additional keyword arguments passed directly to the `vszip.Deband` plugin.

    Returns:
        Debanded and optionally grained clip.
    """

    # Simulate scale=True like the default we had when wrapping neo_f3kdb
    scale = kwargs.pop("scale", True)
    thr = [t * 255 / ((1 << (16 if scale else 14)) - 1) for t in to_arr(thr)]
    grain = [g * 255 / ((1 << 14) - 1) for g in to_arr(grain)]

    thr = normalize_param_planes(clip, thr, planes, 0)
    grain = normalize_param_planes(clip, grain, planes, 0)

    random_ref, random_grain = normalize_seq(random, 2)

    kwargs = (
        sample_mode.kwargs
        | {
            "random_algo_ref": random_ref,
            "random_algo_grain": random_ref.sigma,
            "random_param_ref": random_grain,
            "random_param_grain": random_grain.sigma,
        }
        | kwargs
    )

    logger.debug("vszip.Deband params: thr=%s, grain=%s %s", thr, grain, kwargs)

    return core.vszip.Deband(
        clip,
        radius,
        thr,
        grain[:2],
        sample_mode,
        seed,
        blur_first,
        dynamic_grain,
        **kwargs,
    )

mdb_bilateral

mdb_bilateral(
    clip: VideoNode,
    radius: int = 16,
    thr: float = 260,
    debander: _DebanderFunc[Any] = f3k_deband,
    dark_thr: float | Sequence[float] = 0.6,
    bright_thr: float | Sequence[float] = 0.6,
    elast: float | Sequence[float] = 3.0,
    planes: Planes = None,
) -> VideoNode

Multi stage debanding, bilateral-esque filter.

This function is more of a last resort for extreme banding.

Example usage
from vsdeband import mdb_bilateral

debanded = mdb_bilateral(clip, 22, 320)

Parameters:

  • clip

    (VideoNode) –

    Input clip.

  • radius

    (int, default: 16 ) –

    Banding detection range.

  • thr

    (float, default: 260 ) –

    Banding detection thr(s) for planes.

  • debander

    (_DebanderFunc[Any], default: f3k_deband ) –

    Specifies what debander callable to use.

  • dark_thr

    (float | Sequence[float], default: 0.6 ) –

    LimitFilter parameter. Threshold (8-bit scale) to limit dark filtering diff.

  • bright_thr

    (float | Sequence[float], default: 0.6 ) –

    LimitFilter parameter. Threshold (8-bit scale) to limit bright filtering diff.

  • elast

    (float | Sequence[float], default: 3.0 ) –

    LimitFilter parameter. Elasticity of the soft threshold.

  • planes

    (Planes, default: None ) –

    Which planes to process.

Returns:

  • VideoNode

    Debanded clip.

Source code in vsdeband/debanders.py
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
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
def mdb_bilateral(
    clip: vs.VideoNode,
    radius: int = 16,
    thr: float = 260,
    debander: _DebanderFunc[Any] = f3k_deband,
    dark_thr: float | Sequence[float] = 0.6,
    bright_thr: float | Sequence[float] = 0.6,
    elast: float | Sequence[float] = 3.0,
    planes: Planes = None,
) -> vs.VideoNode:
    """
    Multi stage debanding, bilateral-esque filter.

    This function is more of a last resort for extreme banding.

    Example usage:
        ```py
        from vsdeband import mdb_bilateral

        debanded = mdb_bilateral(clip, 22, 320)
        ```

    Args:
        clip: Input clip.
        radius: Banding detection range.
        thr: Banding detection thr(s) for planes.
        debander: Specifies what debander callable to use.
        dark_thr: LimitFilter parameter. Threshold (8-bit scale) to limit dark filtering diff.
        bright_thr: LimitFilter parameter. Threshold (8-bit scale) to limit bright filtering diff.
        elast: LimitFilter parameter. Elasticity of the soft threshold.
        planes: Which planes to process.

    Returns:
        Debanded clip.
    """
    clip, bits = expect_bits(clip, 16)

    rad1, rad2, rad3 = round(radius * 4 / 3), round(radius * 2 / 3), round(radius / 3)

    db1 = debander(clip, rad1, [max(1, th // 2) for th in to_arr(thr)], 0, planes)
    db2 = debander(db1, rad2, thr, 0, planes)
    db3 = debander(db2, rad3, thr, 0, planes)

    limit = core.vszip.LimitFilter(db3, clip, db1, dark_thr, bright_thr, elast, planes)

    return depth(limit, bits)

pfdeband

pfdeband(
    clip: VideoNode,
    radius: int = 16,
    thr: float | Sequence[float] = 96,
    prefilter: PrefilterLike | _SupportPlanesParam = gauss_blur,
    debander: _DebanderFunc[Any] = f3k_deband,
    ref: VideoNode | None = None,
    dark_thr: float | Sequence[float] = 0.3,
    bright_thr: float | Sequence[float] = 0.3,
    elast: float | Sequence[float] = 2.5,
    planes: Planes = None,
) -> VideoNode

Prefilter and deband a clip.

Parameters:

  • clip

    (VideoNode) –

    Input clip.

  • radius

    (int, default: 16 ) –

    Banding detection range.

  • thr

    (float | Sequence[float], default: 96 ) –

    Banding detection thr(s) for planes.

  • prefilter

    (PrefilterLike | _SupportPlanesParam, default: gauss_blur ) –

    Prefilter used to blur the clip before debanding.

  • debander

    (_DebanderFunc[Any], default: f3k_deband ) –

    Specifies what debander callable to use.

  • planes

    (Planes, default: None ) –

    Planes to process

  • ref

    (VideoNode | None, default: None ) –

    LimitFilter parameter. Reference clip, to compute the weight to be applied on filtering diff.

  • dark_thr

    (float | Sequence[float], default: 0.3 ) –

    LimitFilter parameter. Threshold (8-bit scale) to limit dark filtering diff.

  • bright_thr

    (float | Sequence[float], default: 0.3 ) –

    LimitFilter parameter. Threshold (8-bit scale) to limit bright filtering diff.

  • elast

    (float | Sequence[float], default: 2.5 ) –

    LimitFilter parameter. Elasticity of the soft threshold.

Returns:

  • VideoNode

    Debanded clip.

Source code in vsdeband/debanders.py
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 pfdeband(
    clip: vs.VideoNode,
    radius: int = 16,
    thr: float | Sequence[float] = 96,
    prefilter: PrefilterLike | _SupportPlanesParam = gauss_blur,
    debander: _DebanderFunc[Any] = f3k_deband,
    ref: vs.VideoNode | None = None,
    dark_thr: float | Sequence[float] = 0.3,
    bright_thr: float | Sequence[float] = 0.3,
    elast: float | Sequence[float] = 2.5,
    planes: Planes = None,
) -> vs.VideoNode:
    """
    Prefilter and deband a clip.

    Args:
        clip: Input clip.
        radius: Banding detection range.
        thr: Banding detection thr(s) for planes.
        prefilter: Prefilter used to blur the clip before debanding.
        debander: Specifies what debander callable to use.
        planes: Planes to process
        ref: LimitFilter parameter. Reference clip, to compute the weight to be applied on filtering diff.
        dark_thr: LimitFilter parameter. Threshold (8-bit scale) to limit dark filtering diff.
        bright_thr: LimitFilter parameter. Threshold (8-bit scale) to limit bright filtering diff.
        elast: LimitFilter parameter. Elasticity of the soft threshold.

    Returns:
        Debanded clip.
    """
    clip, bits = expect_bits(clip, 16)

    blur = prefilter(clip, planes=planes)
    smooth = debander(blur, radius, thr, planes=planes)
    limit = core.vszip.LimitFilter(smooth, blur, ref, dark_thr, bright_thr, elast, planes)
    merge = norm_expr([clip, blur, limit], "z x y - +", planes, func=pfdeband)

    return depth(merge, bits)

placebo_deband

placebo_deband(
    clip: VideoNode,
    radius: float = 16.0,
    thr: float | Sequence[float] = 3.0,
    grain: float | Sequence[float] = 0.0,
    planes: Planes = None,
    *,
    iterations: int = 4,
    **kwargs: Any
) -> VideoNode

Debanding wrapper around the placebo.Deband filter from the VapourSynth vs-placebo plugin.

For full plugin documentation, see: https://github.com/sgt0/vs-placebo?tab=readme-ov-file#deband

Parameters:

  • clip

    (VideoNode) –

    Input clip.

  • radius

    (float, default: 16.0 ) –

    Initial debanding radius. The radius increases linearly with each iteration. A higher radius will find more gradients, but a lower radius will smooth more aggressively.

  • thr

    (float | Sequence[float], default: 3.0 ) –

    Cut-off threshold(s) for each plane. Higher values increase debanding strength but may remove fine details. Accepts a single float or a sequence per plane.

  • grain

    (float | Sequence[float], default: 0.0 ) –

    Amount of grain/noise to add after debanding. Helps mask residual artifacts. Accepts a float or a sequence per plane. Note: For HDR content, grain can significantly affect brightness. Consider reducing or disabling.

  • planes

    (Planes, default: None ) –

    Which planes to process. Defaults to all planes.

  • iterations

    (int, default: 4 ) –

    Number of debanding steps to perform per sample. More iterations yield stronger effect but quickly lose efficiency beyond 4.

Returns:

  • VideoNode

    Debanded and optionally grained clip.

Source code in vsdeband/debanders.py
297
298
299
300
301
302
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
328
329
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
def placebo_deband(
    clip: vs.VideoNode,
    radius: float = 16.0,
    thr: float | Sequence[float] = 3.0,
    grain: float | Sequence[float] = 0.0,
    planes: Planes = None,
    *,
    iterations: int = 4,
    **kwargs: Any,
) -> vs.VideoNode:
    """
    Debanding wrapper around the `placebo.Deband` filter from the VapourSynth `vs-placebo` plugin.

    For full plugin documentation, see:
    <https://github.com/sgt0/vs-placebo?tab=readme-ov-file#deband>

    Args:
        clip: Input clip.
        radius: Initial debanding radius. The radius increases linearly with each iteration. A higher radius will find
            more gradients, but a lower radius will smooth more aggressively.
        thr: Cut-off threshold(s) for each plane. Higher values increase debanding strength but may remove fine details.
            Accepts a single float or a sequence per plane.
        grain: Amount of grain/noise to add after debanding. Helps mask residual artifacts. Accepts a float or a
            sequence per plane. Note: For HDR content, grain can significantly affect brightness. Consider reducing or
            disabling.
        planes: Which planes to process. Defaults to all planes.
        iterations: Number of debanding steps to perform per sample. More iterations yield stronger effect but quickly
            lose efficiency beyond 4.

    Returns:
        Debanded and optionally grained clip.
    """
    thr = normalize_param_planes(clip, thr, planes, 0)
    ngrain = normalize_param_planes(clip, grain, planes, 0)

    def _placebo(clip: vs.VideoNode, threshold: float, grain_val: float, planes: Sequence[int]) -> vs.VideoNode:
        plane = 0

        if threshold == grain_val == 0:
            return clip

        for p in planes:
            plane |= pow(2, p)

        return clip.placebo.Deband(plane, iterations, threshold, radius, grain_val, **kwargs)

    set_grn = set(ngrain)

    if set_grn == {0} or clip.format.num_planes == 1:
        debs = [_placebo(p, t, ngrain[0], [0]) for p, t in zip(split(clip), thr)]

        if len(debs) == 1:
            return debs[0]

        return join(debs, clip.format.color_family)

    plane_map = {tuple(i for i in range(clip.format.num_planes) if ngrain[i] == x): x for x in set_grn - {0}}

    debanded = clip

    for planes, grain_val in plane_map.items():
        if len({thr[p] for p in planes}) == 1:
            debanded = _placebo(debanded, thr[planes[0]], grain_val, planes)
        else:
            for p in planes:
                debanded = _placebo(debanded, thr[p], grain_val, planes)

    return debanded