Skip to main content

BM3D denoising filter for VapourSynth, implemented in Metal

Project description

VapourSynth-BM3DMETAL

Copyright© 2021 WolframRhodium

Copyright© 2025 Sunflower Dolls

BM3D denoising filter for VapourSynth, implemented in Metal.

Ported from VapourSynth-BM3DCUDA.

Description

  • Please check VapourSynth-BM3D for the original CPU implementation.

  • This Metal implementation leverages Apple's Metal API for GPU acceleration on macOS systems, providing efficient denoising on Apple Silicon and Intel Macs with Metal-capable GPUs.

Requirements

  • macOS 12.0 (Monterey) or later.

  • Metal-capable GPU:

    • Apple Silicon (M1, M2, M3, or newer)
    • Intel Mac with Metal-capable GPU (requires SIMD width/thread execution width of 32; older Intel GPUs may not be supported)
  • VapourSynth R74 or later on macOS.

Installation

For VapourSynth R74 or later, install both VapourSynth and this plugin from PyPI:

python3 -m pip install -U vapoursynth vapoursynth-bm3dmetal
vapoursynth config

The wheel installs libbm3dmetal.dylib into VapourSynth's Python package plugin directory and provides a manifest.vs for autoloading.

Parameters

bm3dmetal.BM3D(clip clip[, clip ref=None, float[] sigma=3.0, int[] block_step=8, int[] bm_range=9, int radius=0, int[] ps_num=2, int[] ps_range=4, bint chroma=False, int device_id=0, bool fast=False])
  • clip:

    The input clip. Must be of 32 bit float format. Each plane is denoised separately if chroma is set to False. Data of unprocessed planes is undefined. Frame properties of the output clip are copied from it.

  • ref:

    The reference clip. Must be of the same format, width, height, number of frames as clip.

    Used in block-matching and as the reference in empirical Wiener filtering, i.e. bm3d.Final / bm3d.VFinal:

    basic = core.bm3dmetal.BM3D(src, radius=0)
    final = core.bm3dmetal.BM3D(src, ref=basic, radius=0)
    
    vbasic = core.bm3dmetal.BM3D(src, radius=radius_nonzero).bm3d.VAggregate(radius=radius_nonzero)
    vfinal = core.bm3dmetal.BM3D(src, ref=vbasic, radius=r).bm3d.VAggregate(radius=r)
    
    # alternatively, using the v2 interface
    basic_or_vbasic = core.bm3dmetal.BM3Dv2(src, radius=r)
    final_or_vfinal = core.bm3dmetal.BM3Dv2(src, ref=basic_or_vbasic, radius=r)
    

    corresponds to the followings (ignoring color space handling and other differences in implementation), respectively

    basic = core.bm3d.Basic(clip)
    final = core.bm3d.Final(basic, ref=basic)
    
    vbasic = core.bm3d.VBasic(src, radius=r).bm3d.VAggregate(radius=r, sample=1)
    vfinal = core.bm3d.VFinal(src, ref=vbasic, radius=r).bm3d.VAggregate(radius=r)
    
  • sigma: The strength of denoising for each plane, defined as the standard deviation of the AWGN component, implying $Noise \sim \mathcal{N}(0, \sigma^2)$ on a $0\text{-}255$ scale.

    The strength is similar (but not strictly equal) as VapourSynth-BM3D due to differences in implementation. (coefficient normalization is not implemented, for example)

    Default [3,3,3].

  • block_step, bm_range, radius, ps_num, ps_range:

    Same as those in VapourSynth-BM3D.

    If chroma is set to True, only the first value is in effect.

    Otherwise an array of values may be specified for each plane (except radius).

    Note: It is generally not recommended to take a large value of ps_num as current implementations do not take duplicate block-matching candidates into account during temporary searching, which may leads to regression in denoising quality. This issue is not present in VapourSynth-BM3D.

    Note2: Lowering the value of "block_step" will be useful in reducing blocking artifacts at the cost of slower processing.

  • chroma:

    CBM3D algorithm. clip must be of YUV444PS format.

    Y channel is used in block-matching of chroma channels.

    Default False.

  • device_id:

    Set Metal GPU device to be used (for systems with multiple GPUs).

    Default 0.

  • fast:

    Enables multi-threaded copy between CPU and GPU, consuming 4x more memory.

    • Apple Silicon: Enabling this option will degrade performance. Keep it disabled.
    • Intel Mac with AMD discrete GPU: May (or may not) provide slight performance improvement.

    Default: False.

  • extractor_exp:

    Used for deterministic (bitwise) output.

    Pre-rounding is employed for associative floating-point summation.

    The value should be a positive integer not less than 3, and may need to be higher depending on the source video and filter parameters.

    Default 0. (non-determinism)

  • zero_init:

    This parameter only has an effect in temporal mode (radius > 0).

    It controls the output of planes that are not being processed (i.e., where sigma is set to 0).

    • True (default): Unprocessed planes will be filled with zeros (resulting in a black image).
    • False: Unprocessed planes will contain uninitialized data, which may appear as garbage or random noise.

    This parameter has no effect in spatial mode (radius = 0), as unprocessed planes are copied from the source clip. It also has no effect on planes that are actively being denoised.

    Default: True.

Notes

  • bm3d.VAggregate should be called after temporal filtering, as in VapourSynth-BM3D. Alternatively, you may use the BM3Dv2() interface for both spatial and temporal denoising in one step.

  • The Metal implementation uses Metal Shading Language for GPU kernels, providing efficient computation on Apple platforms.

Statistics

GPU memory consumptions:

(ref ? 4 : 3) * (chroma ? 3 : 1) * (fast ? 4 : 1) * (2 * radius + 1) * size_of_a_single_frame

Compute complexity:

(chroma ? 3 : 1) * ceil((width - 8) / block_step + 1) * ceil((height - 8) / block_step + 1) * ((2 * bm_range + 1) * (2 * bm_range + 1) + 2 * radius * ps_num * (2 * ps_range + 1) * (2 * ps_range + 1)) * (ref ? 1.5 : 1) + (radius > 0 ? width * height * (chroma ? 3 : 1) * 2 * radius : 0)

Benchmarks

input: 1920x1080

  • chroma=False: GrayS
  • chroma=True: YUV444PS

data format: fps

radius chroma final M2 Pro 32GB (macOS 15.6.1) M4 16GB (macOS 26.1)
0 False False 120.31 173.74
0 False True 102.20 102.86
0 True False 56.09 71.08
0 True True 48.20 49.18
1 False False 63.20 71.56
1 False True 57.61 51.07
1 True False 29.03 24.93
1 True True 25.03 25.39
2 False False 44.35 58.43
2 False True 39.69 53.94
2 True False 20.34 16.46
2 True True 18.46 11.99

Compilation

Requires CMake 3.20 or later, Xcode Command Line Tools, and VapourSynth's Python package.

python3 -m pip install -U "VapourSynth>=74"
cmake -S . -B build -D CMAKE_BUILD_TYPE=Release

cmake --build build --config Release

The compiled dynamic library (libbm3dmetal.dylib) will be located in the build/lib directory. Copy it to your VapourSynth plugins directory.

If CMake cannot locate VapourSynth's headers from Python, pass -D VAPOURSYNTH_INCLUDE_DIRECTORY="/path/to/vapoursynth/include".

License

This project is licensed under the GNU General Public License v3.0 or later (GPLv3+).

Based on VapourSynth-BM3DCUDA by WolframRhodium, which is licensed under GPLv2 or later.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vapoursynth_bm3dmetal-4.0.0.tar.gz (33.2 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_x86_64.whl (46.5 kB view details)

Uploaded Python 3macOS 12.0+ x86-64

vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_arm64.whl (46.8 kB view details)

Uploaded Python 3macOS 12.0+ ARM64

File details

Details for the file vapoursynth_bm3dmetal-4.0.0.tar.gz.

File metadata

  • Download URL: vapoursynth_bm3dmetal-4.0.0.tar.gz
  • Upload date:
  • Size: 33.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vapoursynth_bm3dmetal-4.0.0.tar.gz
Algorithm Hash digest
SHA256 69486b6992d944d029c2268c3472f137d7183aabf0c71c387a27907a26f89de3
MD5 54add0234cccce6b4e03a99466de5d86
BLAKE2b-256 2fc0f8b1f2924cc039d6f4558de62e4a532b486a2b9beeefa649ca237c3c5403

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bm3dmetal-4.0.0.tar.gz:

Publisher: release.yml on Sunflower-Dolls/Vapoursynth-BM3DMETAL

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_x86_64.whl.

File metadata

File hashes

Hashes for vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_x86_64.whl
Algorithm Hash digest
SHA256 57bb9cb70fb3d9767b931cb59dd7d74546ba3a65c853e9c25a7a2e8135f98778
MD5 9eecc7a759653b1fdc5e86bf20567870
BLAKE2b-256 07f669558b5f20340c89803205f223a0c7a3939cc8ea0b654faac4218b603687

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_x86_64.whl:

Publisher: release.yml on Sunflower-Dolls/Vapoursynth-BM3DMETAL

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_arm64.whl.

File metadata

File hashes

Hashes for vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_arm64.whl
Algorithm Hash digest
SHA256 c332b3d1ecb7a15d8ffe4e09dd27f86bf8ec1d08eb67cd4fb42ae130e26e1b21
MD5 f9f4360f07bce98a05823866a0aee57a
BLAKE2b-256 aeaffff409c6801f9ab684bef895694ab709edfdf6a52e16b2713b4bf9104226

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bm3dmetal-4.0.0-py3-none-macosx_12_0_arm64.whl:

Publisher: release.yml on Sunflower-Dolls/Vapoursynth-BM3DMETAL

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page