Skip to content

enum

Classes:

  • BlurMatrix

    Enum for predefined 1D and 2D blur kernel generators.

  • BlurMatrixBase

    Represents a convolution kernel (matrix) for spatial or temporal filtering.

BlurMatrix

Bases: CustomEnum

Enum for predefined 1D and 2D blur kernel generators.

Provides commonly used blur kernels (e.g., mean, binomial, Gaussian) for convolution-based filtering.

Each kernel is returned as a BlurMatrixBase object.

Methods:

  • __call__

    Generate the blur kernel based on the enum variant.

  • custom

    Create a custom BlurMatrixBase kernel with explicit values and mode.

  • from_radius

    Generate a Gaussian blur kernel from an intuitive radius.

  • get_taps

    Compute the number of taps required for a given sigma value.

Attributes:

  • BINOMIAL

    Pascal triangle coefficients approximating Gaussian blur.

  • BOX_BLUR
  • BOX_BLUR_NO_CENTER
  • GAUSS

    Proper Gaussian kernel defined by sigma.

  • MEAN

    Standard mean/box blur kernel including the center pixel. Aliased as BOX_BLUR.

  • MEAN_NO_CENTER

    Mean kernel excluding the center pixel. Also aliased as BOX_BLUR_NO_CENTER.

BINOMIAL class-attribute instance-attribute

BINOMIAL = auto()

Pascal triangle coefficients approximating Gaussian blur.

BOX_BLUR class-attribute instance-attribute

BOX_BLUR = MEAN

BOX_BLUR_NO_CENTER class-attribute instance-attribute

BOX_BLUR_NO_CENTER = MEAN_NO_CENTER

GAUSS class-attribute instance-attribute

GAUSS = auto()

Proper Gaussian kernel defined by sigma.

MEAN class-attribute instance-attribute

MEAN = auto()

Standard mean/box blur kernel including the center pixel. Aliased as BOX_BLUR.

MEAN_NO_CENTER class-attribute instance-attribute

MEAN_NO_CENTER = auto()

Mean kernel excluding the center pixel. Also aliased as BOX_BLUR_NO_CENTER.

__call__

__call__(taps: int = 1, *, mode: ConvMode = SQUARE) -> BlurMatrixBase[int]
__call__(taps: int = 1, *, mode: ConvMode = SQUARE) -> BlurMatrixBase[int]
__call__(taps: int = 1, *, mode: ConvMode = HV) -> BlurMatrixBase[int]
__call__(
    taps: int | None = None,
    *,
    sigma: float = 0.5,
    mode: ConvMode = HV,
    **kwargs: Any
) -> BlurMatrixBase[float]
__call__(taps: int | None = None, **kwargs: Any) -> Any
__call__(taps: int | None = None, **kwargs: Any) -> Any

Generate the blur kernel based on the enum variant.

Parameters:

  • taps

    (int | None, default: None ) –

    Size of the kernel in each direction.

  • sigma

    [GAUSS only] Standard deviation of the Gaussian kernel.

  • mode

    Convolution mode. Default depends on kernel.

Returns:

  • Any

    A BlurMatrixBase instance representing the kernel.

Source code in vsrgtools/enum.py
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
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
def __call__(self, taps: int | None = None, **kwargs: Any) -> Any:
    """
    Generate the blur kernel based on the enum variant.

    Args:
        taps: Size of the kernel in each direction.
        sigma: [GAUSS only] Standard deviation of the Gaussian kernel.
        mode: Convolution mode. Default depends on kernel.

    Returns:
        A `BlurMatrixBase` instance representing the kernel.
    """
    kernel: BlurMatrixBase[Any]

    match self:
        case BlurMatrix.MEAN_NO_CENTER:
            taps = fallback(taps, 1)
            mode = kwargs.pop("mode", ConvMode.SQUARE)

            matrix = [1 for _ in range(((2 * taps + 1) ** (2 if mode == ConvMode.SQUARE else 1)) - 1)]
            matrix.insert(len(matrix) // 2, 0)

            return self.custom(matrix, mode)

        case BlurMatrix.MEAN:
            taps = fallback(taps, 1)
            mode = kwargs.pop("mode", ConvMode.SQUARE)

            kernel = self.custom((1 for _ in range((2 * taps + 1))), mode)

        case BlurMatrix.BINOMIAL:
            taps = fallback(taps, 1)
            mode = kwargs.pop("mode", ConvMode.HV)

            c = 1
            n = taps * 2 + 1

            matrix = list[int]()

            for i in range(1, taps + 2):
                matrix.append(c)
                c = c * (n - i) // i

            kernel = self.custom(matrix[:-1] + matrix[::-1], mode)

        case BlurMatrix.GAUSS:
            taps = fallback(taps, 1)
            sigma = kwargs.pop("sigma", 0.5)
            mode = kwargs.pop("mode", ConvMode.HV)
            scale_value = kwargs.pop("scale_value", 1023)

            if mode == ConvMode.SQUARE:
                scale_value = sqrt(scale_value)

            taps = self.get_taps(sigma, taps)

            if taps < 0:
                raise CustomValueError("Taps must be >= 0!")

            if sigma > 0.0:
                half_pisqrt = 1.0 / sqrt(2.0 * pi) * sigma
                doub_qsigma = 2 * sigma**2

                high, *mat = [half_pisqrt * exp(-(x**2) / doub_qsigma) for x in range(taps + 1)]

                mat = [x * scale_value / high for x in mat]
                mat = [*mat[::-1], scale_value, *mat]
            else:
                mat = [scale_value]

            kernel = self.custom(mat, mode)

        case _:
            raise CustomNotImplementedError("Unsupported blur matrix enum!", self, self)

    if mode == ConvMode.SQUARE:
        kernel = kernel.outer()

    return kernel

custom classmethod

custom(values: Iterable[_Nb], mode: ConvMode = SQUARE) -> BlurMatrixBase[_Nb]

Create a custom BlurMatrixBase kernel with explicit values and mode.

Parameters:

Returns:

Source code in vsrgtools/enum.py
417
418
419
420
421
422
423
424
425
426
427
428
429
@classmethod
def custom(cls, values: Iterable[_Nb], mode: ConvMode = ConvMode.SQUARE) -> BlurMatrixBase[_Nb]:
    """
    Create a custom BlurMatrixBase kernel with explicit values and mode.

    Args:
        values: The kernel coefficients.
        mode: Convolution mode to use.

    Returns:
        A BlurMatrixBase instance.
    """
    return BlurMatrixBase(values, mode=mode)

from_radius

from_radius(radius: int) -> BlurMatrixBase[float]

Generate a Gaussian blur kernel from an intuitive radius.

This is a shortcut that converts a blur radius to a corresponding sigma value.

Parameters:

  • radius

    (int) –

    Blur radius.

Returns:

Source code in vsrgtools/enum.py
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
def from_radius(self: Literal[BlurMatrix.GAUSS], radius: int) -> BlurMatrixBase[float]:  # type: ignore[misc]
    """
    Generate a Gaussian blur kernel from an intuitive radius.

    This is a shortcut that converts a blur radius to a corresponding sigma value.

    Args:
        radius: Blur radius.

    Returns:
        Gaussian blur matrix.
    """
    assert self is BlurMatrix.GAUSS

    return BlurMatrix.GAUSS(None, sigma=(radius + 1.0) / 3)

get_taps

get_taps(sigma: float, taps: int | None = None) -> int

Compute the number of taps required for a given sigma value.

Parameters:

  • sigma

    (float) –

    Gaussian sigma value.

  • taps

    (int | None, default: None ) –

    Optional manual override; if not provided, it's computed from sigma.

Returns:

  • int

    Number of taps.

Source code in vsrgtools/enum.py
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
def get_taps(self: Literal[BlurMatrix.GAUSS], sigma: float, taps: int | None = None) -> int:  # type: ignore[misc]
    """
    Compute the number of taps required for a given sigma value.

    Args:
        sigma: Gaussian sigma value.
        taps: Optional manual override; if not provided, it's computed from sigma.

    Returns:
        Number of taps.
    """
    assert self is BlurMatrix.GAUSS

    if taps is None:
        taps = ceil(abs(sigma) * 8 + 1) // 2

    return taps

BlurMatrixBase

BlurMatrixBase(iterable: Iterable[_Nb], /, mode: ConvMode = SQUARE)

Bases: list[_Nb]

Represents a convolution kernel (matrix) for spatial or temporal filtering.

This class is typically constructed via the BlurMatrix enum, and encapsulates both the filter values and the intended convolution mode (e.g., horizontal, vertical, square, temporal).

When called, it applies the convolution to a clip using the appropriate method (std.Convolution, std.AverageFrames, or a custom ExprOp expression), depending on the kernel's properties and context.

Example
kernel = BlurMatrix.BINOMIAL(taps=2)
blurred = kernel(clip)

Parameters:

  • iterable

    (Iterable[_Nb]) –

    Iterable of kernel coefficients.

  • mode

    (ConvMode, default: SQUARE ) –

    Convolution mode to use. Default is SQUARE.

Methods:

  • __call__

    Apply the blur kernel to the given clip via spatial or temporal convolution.

  • outer

    Convert a 1D kernel into a 2D square kernel by computing the outer product.

Attributes:

Source code in vsrgtools/enum.py
48
49
50
51
52
53
54
55
def __init__(self, iterable: Iterable[_Nb], /, mode: ConvMode = ConvMode.SQUARE) -> None:
    """
    Args:
        iterable: Iterable of kernel coefficients.
        mode: Convolution mode to use. Default is SQUARE.
    """
    self.mode = mode
    super().__init__(iterable)

mode instance-attribute

mode = mode

__call__

__call__(
    clip: VideoNode | Iterable[VideoNode],
    planes: PlanesT = None,
    bias: float | None = None,
    divisor: float | None = None,
    saturate: bool = True,
    passes: int = 1,
    func: FuncExceptT | None = None,
    expr_kwargs: KwargsT | None = None,
    **conv_kwargs: Any
) -> ConstantFormatVideoNode

Apply the blur kernel to the given clip via spatial or temporal convolution.

Chooses the appropriate backend (std.Convolution, std.AverageFrames, or ExprOp.convolution) depending on kernel size, mode, format, and other constraints.

Parameters:

  • clip

    (VideoNode | Iterable[VideoNode]) –

    Source clip.

  • planes

    (PlanesT, default: None ) –

    Planes to process. Defaults to all.

  • bias

    (float | None, default: None ) –

    Value added to result before clamping.

  • divisor

    (float | None, default: None ) –

    Divides the result of the convolution (before adding bias). Defaults to sum of kernel values.

  • saturate

    (bool, default: True ) –

    If True, negative values are clamped to zero. If False, absolute values are returned.

  • passes

    (int, default: 1 ) –

    Number of convolution passes to apply.

  • func

    (FuncExceptT | None, default: None ) –

    Function returned for custom error handling. This should only be set by VS package developers.

  • expr_kwargs

    (KwargsT | None, default: None ) –

    Extra kwargs passed to ExprOp.convolution when used.

  • **conv_kwargs

    (Any, default: {} ) –

    Any other args passed to the underlying VapourSynth function.

Returns:

  • ConstantFormatVideoNode

    Processed (blurred) video clip.

Source code in vsrgtools/enum.py
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
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
def __call__(
    self,
    clip: vs.VideoNode | Iterable[vs.VideoNode],
    planes: PlanesT = None,
    bias: float | None = None,
    divisor: float | None = None,
    saturate: bool = True,
    passes: int = 1,
    func: FuncExceptT | None = None,
    expr_kwargs: KwargsT | None = None,
    **conv_kwargs: Any,
) -> ConstantFormatVideoNode:
    """
    Apply the blur kernel to the given clip via spatial or temporal convolution.

    Chooses the appropriate backend (`std.Convolution`, `std.AverageFrames`, or `ExprOp.convolution`)
    depending on kernel size, mode, format, and other constraints.

    Args:
        clip: Source clip.
        planes: Planes to process. Defaults to all.
        bias: Value added to result before clamping.
        divisor: Divides the result of the convolution (before adding bias). Defaults to sum of kernel values.
        saturate: If True, negative values are clamped to zero. If False, absolute values are returned.
        passes: Number of convolution passes to apply.
        func: Function returned for custom error handling. This should only be set by VS package developers.
        expr_kwargs: Extra kwargs passed to ExprOp.convolution when used.
        **conv_kwargs: Any other args passed to the underlying VapourSynth function.

    Returns:
        Processed (blurred) video clip.
    """
    clip = to_arr(clip)

    func = func or self

    assert check_variable_format(clip, func)

    if len(self) <= 1:
        return clip[0]

    expr_kwargs = expr_kwargs or {}

    fp16 = clip[0].format.sample_type == vs.FLOAT and clip[0].format.bits_per_sample == 16

    # Spatial mode
    if self.mode.is_spatial:
        if len(clip) > 1:
            raise CustomValueError("You can't pass multiple clips when using a spatial mode.", func)

        # TODO: https://github.com/vapoursynth/vapoursynth/issues/1101
        if all([not fp16, len(self) <= 25, all(-1023 <= x <= 1023 for x in self), self.mode != ConvMode.SQUARE]):
            return iterate(clip[0], core.std.Convolution, passes, self, bias, divisor, planes, saturate, self.mode)

        return iterate(
            clip[0],
            ExprOp.convolution("x", self, bias, fallback(divisor, True), saturate, self.mode, **expr_kwargs),
            passes,
            planes=planes,
            **conv_kwargs,
        )

    # Temporal mode
    use_std = all(
        [
            not fp16,
            len(self) <= 31,
            all(-1023 <= x <= 1023 for x in self),
            not bias,
            saturate,
        ]
    )

    if len(clip) > 1:
        if passes != 1:
            raise CustomValueError(
                "`passes` are not supported when passing multiple clips in temporal mode", func, passes
            )

        if use_std:
            return core.std.AverageFrames(clip, self, divisor, planes=planes)

        return ExprOp.convolution(
            ExprVars(len(clip)), self, bias, fallback(divisor, True), saturate, self.mode, **expr_kwargs
        )(clip, planes=planes, **conv_kwargs)

    # std.AverageFrames doesn't support premultiply, multiply and clamp from ExprOp.convolution
    if use_std and conv_kwargs.keys() <= {"scenechange"}:
        return iterate(clip[0], core.std.AverageFrames, passes, self, divisor, planes=planes, **conv_kwargs)

    return self._averageframes_akarin(clip[0], planes, bias, divisor, saturate, passes, expr_kwargs, **conv_kwargs)

outer

outer() -> Self

Convert a 1D kernel into a 2D square kernel by computing the outer product.

Returns:

  • Self

    New BlurMatrixBase instance with 2D kernel and same mode.

Source code in vsrgtools/enum.py
230
231
232
233
234
235
236
237
238
239
def outer(self) -> Self:
    """
    Convert a 1D kernel into a 2D square kernel by computing the outer product.

    Returns:
        New `BlurMatrixBase` instance with 2D kernel and same mode.
    """
    from numpy import outer

    return self.__class__(list[_Nb](outer(self, self).flatten()), self.mode)  # pyright: ignore[reportArgumentType]