Skip to main content

mitsuba-oidn

This package provides unofficial Python bindings for Intel Open Image Denoise (OIDN) for use with Dr.Jit and the Mitsuba renderer.

import mitsuba as mi
import mitsuba_oidn as oidn

mi.set_variant("cuda_ad_rgb")
scene = mi.load_dict(mi.cornell_box())
color = mi.render(scene, spp=16)                   # mi.TensorXf of shape (H, W, 3)
denoised = oidn.denoise(color, hdr=True)           # also an mi.TensorXf, on the GPU

The color argument can be any array type that supports DLPack or the buffer protocol, and the result uses the same type and device.

The package runs on Intel/ARM CPUs, CUDA, and on Apple Metal. It exchanges tensors via the buffer protocol and DLPack for compatibility with Dr.Jit, NumPy, PyTorch, JAX, MLX, etc., and it accesses their memory directly whenever the target device can.

Why another binding?

Several unofficial bindings of OIDN already exist (e.g., pyoidn, which uses cffi to expose the C API directly). This project uses nanobind to create bindings that feel more natural in Python. They automatically commit and release resources and raise errors as Python exceptions. Pixel formats and dimensions are inferred from nd-array signatures.

The bindings are designed to interoperate with Dr.Jit and Mitsuba 3. The copy of OIDN bundled here is modified to use Dr.Jit's nanothread thread pool instead of spinning up another redundant thread pool via oneTBB. For this reason, the package depends on Dr.Jit.

Installation

pip install mitsuba-oidn

Wheels are available for Linux (x86_64, aarch64), Windows (x86_64), and macOS (arm64), matching the platforms supported by Dr.Jit. The Linux x86_64 and Windows wheels include the CUDA device, which activates when an NVIDIA driver is present. The macOS wheel includes the Metal device.

The denoise() function

oidn.denoise(color, albedo=None, normal=None, *, hdr=False, srgb=False,
             clean_aux=False, quality=oidn.Quality.High, input_scale=None,
             filter="RT", device=None, output=None)

Images are arrays of shape (H, W) or (H, W, C) with C <= 4 and dtype float32 or float16. A fourth channel is ignored on input. The result has the same framework and lives on the same device as color: a NumPy array yields a NumPy array, a CUDA tensor yields a CUDA tensor. Its shape is (H, W, min(C, 3)), or (H, W) for two-dimensional input.

  • hdr, srgb, clean_aux, quality, and input_scale map to the parameters of the OIDN RT filter. Set hdr=True for linear radiance values without an upper bound, and clean_aux=True when the albedo and normal images are noise-free. See the OIDN documentation for details.
  • device selects the device. By default, CUDA arrays use a CUDA device with the matching ordinal, and host arrays use the fastest physical device in the system, which can be overridden with the OIDN_DEFAULT_DEVICE environment variable (cpu, cuda, metal, or a physical device ID).
  • output supplies a preallocated array that is filled in place and returned. With an RGBA output array, OIDN writes the RGB channels and leaves alpha untouched.
  • Filters are expensive to create, so denoise() caches a few of them, keyed on image size, format, feature set, and parameters. Repeated calls at the same resolution pay only for the actual filtering.

When the device cannot access an input array directly, for example a NumPy array passed to a CUDA device, denoise() copies it into a device buffer. Otherwise no copies are made.

import numpy as np
import torch
import mitsuba_oidn as oidn

# NumPy, CPU or Metal depending on the fastest available device
out = oidn.denoise(np.asarray(color, dtype=np.float32), hdr=True)

# PyTorch on the GPU: zero-copy in and out
color = torch.rand(1080, 1920, 3, device="cuda")
out = oidn.denoise(color, quality=oidn.Quality.Balanced)
assert out.device == color.device

The object API

The denoise() function covers the common case. The classes below mirror the OIDN object model for applications that need control over devices, memory, and filter lifetime, for instance when denoising many frames or several AOVs that share auxiliary images.

Devices

oidn.physical_devices()               # list of PhysicalDevice: id, name, type, uuid, ...

dev = oidn.Device()                   # fastest physical device
dev = oidn.Device(oidn.DeviceType.CPU)
dev = oidn.Device.from_physical(id)   # also from_uuid(), from_luid(), from_pci_address()
dev = oidn.Device.cuda(device_id=0, stream=torch.cuda.current_stream().cuda_stream)
dev = oidn.Device.metal(command_queue)  # raw id<MTLCommandQueue> pointer

dev.num_threads = 4                   # CPU only: 0 shares the Dr.Jit pool (default),
                                      # a positive value creates a private pool
dev.verbose = 1
dev.type, dev.version, dev.system_memory_supported, dev.managed_memory_supported
dev.sync()                            # wait for asynchronous work

A device commits itself when the first buffer or filter is created. Parameters such as num_threads must be set before that point.

Filters

flt = dev.new_filter("RT")            # or "RTLightmap"

flt.set_image("color", color)         # arrays: layout inferred, zero-copy when possible
flt.set_image("albedo", albedo)
flt.set_image("normal", normal)
flt.set_image("output", output)       # must be writable
flt.hdr = True
flt.clean_aux = True
flt.quality = oidn.Quality.High
flt.input_scale = 0.5                 # None selects automatic scaling
flt.max_memory_mb = 2048
flt.set("cleanAux", True)             # generic access by OIDN parameter name
flt.set_data("weights", blob)         # user-trained weights (bytes or uint8 array)
flt.set_progress_monitor(lambda p: True)  # return False to cancel

flt.execute()                         # commits pending changes, runs, and waits
flt.execute_async(); dev.sync()

set_image() accepts arrays with the layout rules of denoise(). Row and pixel strides are passed to OIDN, so slices of larger arrays work as long as the channel dimension stays contiguous. Whether an array can be bound without a copy depends on the device:

Device Bound without copy
CPU any host array, including CUDA pinned and managed memory
CUDA arrays on the same CUDA device, pinned host memory, and host memory if the GPU supports pageable memory access
Metal any host array, and views of buffers created on the device

Use dev.can_share(array) to test this in advance. When binding is not possible, set_image() raises a TypeError that points at the buffer API.

Filters can also take a Buffer with an explicit description:

flt.set_image("color", buf, format=oidn.Format.Float3, width=w, height=h,
              byte_offset=0, pixel_stride=0, row_stride=0)

Buffers

Buffers are memory allocations made by a device. They are the way to work with memory that the host cannot address, such as dedicated GPU memory, and they provide zero-copy views on unified-memory systems.

buf = dev.new_buffer(nbytes)                          # host and device accessible
buf = dev.new_buffer(nbytes, oidn.Storage.Device)     # device memory only
buf = dev.new_shared_buffer(array)                    # wrap device-accessible memory

buf.size, buf.storage, buf.device, buf.data_ptr

view = buf.view("float32", (h, w, 3))     # DLPack and buffer-protocol object
img = np.from_dlpack(view)                # or torch.from_dlpack(view), ...

buf.write(host_array); buf.read(host_array)           # copies through the host
buf.write_async(src); buf.read_async(dst); dev.sync()

Arrays created from buf.view() are recognized by set_image() and bound through the underlying buffer. On Apple silicon, rendering into such a view and denoising it involves no copies at all. On a CUDA device, a device-storage buffer viewed through torch.from_dlpack() gives a tensor that OIDN wrote directly.

Errors

All OIDN errors raise oidn.Error, whose code attribute is an oidn.ErrorCode. Cancellation through a progress monitor raises oidn.Error with ErrorCode.Cancelled. An exception raised inside the progress monitor cancels the filter and propagates unchanged.

Building from source

The build needs CMake 3.21 or newer, a C++17 compiler, and a binary release of ISPC unpacked into ext/ispc, so that ext/ispc/bin/ispc exists. Metal support requires Xcode 15 or newer. CUDA support requires CUDA 12.8 or newer and is enabled automatically when the toolkit is found.

git clone --recursive https://github.com/mitsuba-renderer/mitsuba-oidn
cd mitsuba-oidn
pip install nanobind==3.0.1 scikit-build-core
pip install --no-build-isolation -ve .
pytest

The OIDN weights are stored with git-lfs, which must be installed before cloning.

License

mitsuba-oidn is licensed under the BSD 3-Clause license. It bundles Intel Open Image Denoise, which is licensed under the Apache License 2.0.

Download files

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

Source Distribution

mitsuba_oidn-0.1.0.tar.gz (47.3 MB view details)

Uploaded Source

Built Distributions

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

mitsuba_oidn-0.1.0-cp310-abi3-win_amd64.whl (47.6 MB view details)

Uploaded CPython 3.10+Windows x86-64

mitsuba_oidn-0.1.0-cp310-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (47.3 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

mitsuba_oidn-0.1.0-cp310-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (47.2 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

mitsuba_oidn-0.1.0-cp310-abi3-macosx_11_0_arm64.whl (47.6 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file mitsuba_oidn-0.1.0.tar.gz.

File metadata

  • Download URL: mitsuba_oidn-0.1.0.tar.gz
  • Upload date:
  • Size: 47.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for mitsuba_oidn-0.1.0.tar.gz
Algorithm Hash digest
SHA256 465ab721b57c4a1fe85816139f176d0a749ffa15a91c3482b9928f522e9903ca
MD5 f5be6283c7cbcdfd84c31207ddeee52a
BLAKE2b-256 4396c5b2c6c44f691d0d2e40a13b543b9ec66e9033b320bb685c7f56485c90e7

See more details on using hashes here.

File details

Details for the file mitsuba_oidn-0.1.0-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for mitsuba_oidn-0.1.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 8e75367d293d349d1acb02baef5726ed5580ffea43e5bcf616c7a4a1d4dcdcd7
MD5 51b9183f2de4393b78aa5097fab21852
BLAKE2b-256 af26b6a92876eed16512d232c3f6f28336c397fdc407a47b6bd75e41d52e5fb4

See more details on using hashes here.

File details

Details for the file mitsuba_oidn-0.1.0-cp310-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for mitsuba_oidn-0.1.0-cp310-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c591e53de0b5a475de3c150dbfb1d2512fce51b3d5e412fede8cc452668bba3b
MD5 504f68acb50c1d807817f0eb39cfa486
BLAKE2b-256 dae531e51e0f603def369ff8fc3f4c2012453ed7271d5e72e094922c3914a0a4

See more details on using hashes here.

File details

Details for the file mitsuba_oidn-0.1.0-cp310-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for mitsuba_oidn-0.1.0-cp310-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7147e515e71c1e064b66300a644c91cc661eab8630d5253a415afce3fdf83401
MD5 1fee5c97ad05eaf9bb50614bee01d919
BLAKE2b-256 77adfcde7f1c9701e813793fe663d86bcfbb6e2a2c187b8df0bba0ed15c1d0f3

See more details on using hashes here.

File details

Details for the file mitsuba_oidn-0.1.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mitsuba_oidn-0.1.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ece707935fdd643e62486f802358eb0e1542d572e10e0b4f675ae4c56fbb74cc
MD5 e7d07015c4961ddb5d205644993c4810
BLAKE2b-256 0819cf8cba9eaeebee01dda2deab153a27a9fe180eb9630cdaac880b4e5c7045

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

5 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page