Downloads · 30 days
0
zerochocobo/NVDS_onnx
NVDS_onnx is a machine learning model from zerochocobo. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
This document describes the NVDS (Neural Video Depth Stabilizer) ONNX export used by PTMediaServer as an optional temporal depth stabilizer in the offline 2D-to-3D/VR pipeline.
Downloads · 30 days
0
Access
Public
Updated Jun 20, 2026
Repo size
717 MB
Likes
0
Public
Click a slice to open those files.
.onnx717 MB · 100%
From the Hugging Face model README
This document describes the NVDS (Neural Video Depth Stabilizer) ONNX export used by PTMediaServer as an optional temporal depth stabilizer in the offline 2D-to-3D/VR pipeline.
The exporter is examples/export_nvds_onnx.py. It converts the NVDS PyTorch checkpoint into fixed-resolution ONNX Runtime graphs so inference does not need PyTorch at runtime. NVDS smooths the per-frame depth that DA3 produces, removing the temporal "depth swimming" that causes discomfort when the stereo output is viewed.
NVDS_Stabilizer.pth checkpoint (a SegFormer
MiT-B5 backbone plus a focal cross-attention stabilizer head).examples/export_nvds_onnx.py
examples/nvds_README.md
models/NVDS/NVDS_Stabilizer.pth (input checkpoint, ~354 MB)
models/NVDS/NVDS_Stabilizer_672x384.onnx (monolithic export)
models/NVDS/NVDS_Backbone_512x288.onnx (split: per-frame backbone)
models/NVDS/NVDS_Head_512x288.onnx (split: cross-frame head)
models/NVDS/NVDS_Backbone_672x384.onnx
models/NVDS/NVDS_Head_672x384.onnx
The conversion script defaults are currently:
| Purpose | Default |
|---|---|
| NVDS source tree | reference/NVDS in this repository |
| PyTorch checkpoint | models/NVDS/NVDS_Stabilizer.pth |
| ONNX output | models/NVDS in this repository |
Resolution tiers PTMediaServer uses (both 16:9):
| Tier | Width x Height | Notes |
|---|---|---|
| Fast (default) | 512 x 288 | ~1.76x faster than 672x384; the UI default. |
| High quality | 672 x 384 | Sharper depth boundaries; reachable via --nvds-res 672x384. |
The exporter has two modes.
--width/--height, no --split)A single graph that takes the whole 4-frame window and runs the backbone on all
4 frames internally. Output name NVDS_Stabilizer_{w}x{h}.onnx.
--split, recommended)Two graphs that let the runtime run the heavy backbone once per frame and cache the last 4 results, instead of recomputing 3/4 of it for every sliding window:
| File | Role |
|---|---|
NVDS_Backbone_{w}x{h}.onnx | Single RGBD frame -> 4 multi-scale feature maps. Run once per frame and cached. |
NVDS_Head_{w}x{h}.onnx | The 4 window frames' features (stacked) + last-frame RGB -> stabilized depth. |
Both modes are numerically identical (the backbone has no cross-frame ops, so its
features are batch-independent). Measured max_abs_diff between split and
monolith is about 3e-05.
Note on performance: the focal cross-attention head, not the backbone, dominates
NVDS cost, so the split's main practical benefit is enabling the lower-resolution
tier (the head cost scales with input pixel count). See
summary/summary_20260620_NVDS_INTEGRATION_EXTERNAL_REVIEW_CN.md for the
measurements.
Each ONNX file is exported at a fixed input resolution.
Rules:
--width and --height must each be a multiple of 32.512 x 288 and 672 x 384 (16:9). Re-export to add
another size.input name : rgbd_seq
input dtype: float32
input shape: [1, 4, 4, height, width] (batch, time=4, channels=RGB+near, H, W)
output name : stabilized_depth
output dtype: float32
output shape: [1, 1, height, width]
Backbone:
input name : frame_rgbd
input shape: [1, 4, height, width] (one RGBD frame: RGB + near)
output names: feat0, feat1, feat2, feat3 (multi-scale features, batch 1)
Head:
input names: feat0..feat3 (each [4, C, h, w] = the 4 window frames stacked)
last_rgb ([1, 3, height, width], the current frame's RGB)
output name : stabilized_depth
output shape: [1, 1, height, width]
The output is a stabilized normalized near/disparity map (larger = nearer),
already temporally smoothed. Unlike raw DA3 depth, it must NOT be reciprocated or
percentile-normalized again at render time; PTMediaServer feeds it through the
dedicated render_near(...) path.
For every frame, the runtime wrapper builds a 4-channel RGBD frame at the export resolution:
[width, height].0.0 .. 1.0 and apply ImageNet normalization with mean
[0.485, 0.456, 0.406] and std [0.229, 0.224, 0.225]; transpose to CHW.[width, height].[4, height, width] frame.For the monolithic graph the wrapper keeps the last 4 such frames, padding the
first frames by repetition, and stacks them into [1, 4, 4, H, W]. For the split
graphs it runs the backbone on each frame, caches the last 4 feature tuples,
stacks them on the batch axis, and passes the current frame's RGB as last_rgb.
PTMediaServer's offline.nvds_stabilizer.NvdsDepthStabilizer performs all of
this and auto-selects the split graphs when they are present.
CPU:
pip install onnxruntime numpy opencv-python
GPU:
pip install onnxruntime-gpu numpy opencv-python
TensorRT is not usable for NVDS (see Notes); the runtime uses the CUDA execution provider with a bounded GPU memory arena.
This example runs the split graphs over a 4-frame window. frame_rgbd_t is a
preprocessed [1, 4, H, W] float32 frame as described in Preprocessing.
import numpy as np
import onnxruntime as ort
W, H = 512, 288
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
backbone = ort.InferenceSession("models/NVDS/NVDS_Backbone_512x288.onnx", providers=providers)
head = ort.InferenceSession("models/NVDS/NVDS_Head_512x288.onnx", providers=providers)
bb_out = [o.name for o in backbone.get_outputs()] # feat0..feat3
window = [] # last 4 feature tuples
for frame_rgbd_t in stream: # each [1, 4, H, W] float32
feats = backbone.run(bb_out, {"frame_rgbd": frame_rgbd_t})
window.append(feats)
window = window[-4:]
pad = [window[0]] * (4 - len(window)) + window # causal padding
feeds = {f"feat{s}": np.concatenate([pad[t][s] for t in range(4)], axis=0)
for s in range(4)}
feeds["last_rgb"] = np.ascontiguousarray(frame_rgbd_t[:, 0:3])
stable_near = head.run(["stabilized_depth"], feeds)[0][0, 0] # [H, W]
Run the exporter from this repository root. The VR_Video_Toolbox_NE virtual environment already contains the PyTorch dependencies (the runtime venv is ONNX-only and has no torch):
G:/GIT/debug/VR_Video_Toolbox_NE/.venv/Scripts/python.exe \
examples/export_nvds_onnx.py --split --width 512 --height 288 --device cuda
Export the high-quality tier:
python examples/export_nvds_onnx.py --split --width 672 --height 384 --device cuda
Export the monolithic graph instead of the split pair:
python examples/export_nvds_onnx.py --width 672 --height 384 --device cuda
Useful options:
--split Export backbone + head graphs instead of the monolith.
--width 672 Input width. Must be a multiple of 32.
--height 384 Input height. Must be a multiple of 32.
--source-root PATH Vendored NVDS source root (contains full_model.py).
--checkpoint PATH NVDS_Stabilizer.pth.
--output PATH Output path for the monolithic export.
--opset 17 ONNX opset version.
--device cpu|cuda Device used for tracing.
--dynamic-batch Mark only the batch axis dynamic (monolithic only).
--skip-ort-check Skip the ONNX Runtime comparison.
Expected checkpoint layout:
NVDS/
NVDS_Stabilizer.pth
The exporter compares outputs with ONNX Runtime and reports a max/mean absolute
difference. In --split mode it runs the per-frame backbone plus head over a
4-frame window and compares against the monolithic PyTorch forward, so a single
run verifies that the split is equivalent to the original model.
ScatterND / dynamic ops. The runtime treats
a trt request for NVDS as CUDA and bounds the CUDA arena with gpu_mem_limit
(DA3 still uses TensorRT normally).render_near(...) path, not the raw-depth path.If you use NVDS or ONNX exports derived from it, cite the upstream work (verify against the upstream repository for the authoritative entry):
@InProceedings{Wang_2023_ICCV,
author = {Wang, Yiran and Pan, Zhiyu and Li, Xingyi and Cao, Zhiguo and Xian, Ke and Zhang, Jianming},
title = {Neural Video Depth Stabilizer},
booktitle = {Proceedings of the IEEE/CVF International Conference on Computer Vision (ICCV)},
year = {2023}
}