-
Notifications
You must be signed in to change notification settings - Fork 2
Bilateral
dnjulek edited this page Jul 9, 2026
·
3 revisions
OpenCL port of VapourSynth-BilateralGPU (bilateralgpu).
The bilateral filter smooths a clip while preserving edges: each output pixel is a weighted average of a spatial window, where a neighbour's weight is the product of a spatial Gaussian (distance) and a range Gaussian (intensity difference). Large flat regions are smoothed; edges — where the range weight collapses — are kept.
vszipcl.Bilateral(vnode clip[, float[] sigma_spatial=3.0, float[] sigma_color=0.02, int[] radius, int device_id=0, int num_streams=1, int use_shared_memory=1, vnode ref, int[] tune])- clip:
Clip to process. 8/16-bit integer, 16-bit half, or 32-bit float; Gray / YUV / RGB. - sigma_spatial: (Default: 3.0)
Sigma of the spatial Gaussian (weight by pixel distance). Larger values give a larger filtering radius and stronger smoothing. Per-plane array; if the second (chroma) plane's value is omitted it is derived from the first plane's value and the sub-sampling (sigma_spatial[0] / sqrt((1<<subW)*(1<<subH))). Set a plane's value to0to copy it through untouched. - sigma_color: (Default: 0.02)
Sigma of the range Gaussian (weight by intensity difference), on the[0, 1]scale at every bit depth. Smaller values preserve edges better (weaker smoothing). Per-plane array; otherwise the same value is used for all planes. Set a plane's value to0to copy it through. - radius: (Default:
max(1, round(sigma_spatial * 3)))
Per-plane window radius in pixels. Per-plane array. Must be positive when given. - use_shared_memory: (Default: 1)
1uses the shared-memory tiled kernel (clamp-to-edge borders);0forces the global-memory kernel (out-of-frame taps skipped). The tiled kernel is faster but falls back to global automatically when the tile would exceed 48 KB (large radius). - ref: (Default: None)
Reference clip for a joint / cross bilateral: the range weights are computed fromref, but the averaged values come fromclip. Must matchclip's format and dimensions. - device_id / num_streams: see Home.
- tune: (Default: unset)
Launch-geometry override —[blk_x, blk_y, smem_kib, pinned](work-group tile + the sm→gl crossover budget + pinned staging). The ship defaults are the measured Ampere values used on every vendor, so you can retune at runtime — especially on AMD / Apple — instead of rebuilding. ⚠smem_kibchanges sm/gl border semantics (not hash-neutral); the rest is byte-identical untuned. See Tune for the full table, ranges, and vendor starting points.
out = core.vszipcl.Bilateral(src) # defaults (luma+chroma)
out = core.vszipcl.Bilateral(src, sigma_spatial=[3, 0, 0]) # luma only (chroma copied)
out = core.vszipcl.Bilateral(src, sigma_spatial=8, sigma_color=0.05)
out = core.vszipcl.Bilateral(src, ref=prefiltered) # cross bilateral-
16-bit half (
GRAYH/YUV*PH/RGBH) is supported —bilateralgpurejects it. Half is a self-defined extension (widen-to-f32, IEEE round-to-nearest-even on store).
1080p YUV420, fps (higher is better), RTX 3070 Ti — see Benchmarks for method.
sigma_spatial=3, sigma_color=0.02.
| Implementation | u16 | f16 | f32 |
|---|---|---|---|
| vszipcl (s=1) | 312.8 | 296.0 | 205.6 |
| vszipcl (s=2) | 391.1 | 391.3 | 289.9 |
| bilateralgpu (s=1) | 99.3 | — | 199.9 |
| bilateralgpu (s=2) | 181.2 | — | 244.6 |
bilateralgpu rejects f16. vszipcl is ~2.2× on u16 (it moves 1 byte/sample and converts on-device).