File size: 8,253 Bytes
42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 42d5516 8259c36 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | # Depth Anything 3 ONNX
This document describes the Depth Anything 3 (DA3) ONNX export used by
PTMediaServer for image, video, and 2D-to-3D/VR depth estimation.
The exporter is [examples/da3_to_onnx.py](da3_to_onnx.py). It converts the
ONNX-friendly depth branch of DA3 Small/Base into fixed-resolution ONNX Runtime
graphs so inference does not need PyTorch at runtime.
## Upstream
- Official project: <https://github.com/ByteDance-Seed/depth-anything-3>
- This exporter targets the DA3 Main Series `DA3-SMALL` and `DA3-BASE`
checkpoints.
- The upstream model cards list `DA3-SMALL` and `DA3-BASE` as Apache 2.0.
- These ONNX files are derived from Depth Anything 3 weights and should be used
according to the upstream license, model cards, and citation requirements.
## Files And Paths
```text
examples/da3_to_onnx.py
examples/da3_README.md
models/DA3/da3_small.onnx
models/DA3/da3_base.onnx
```
The conversion script defaults are currently:
| Purpose | Default |
| --- | --- |
| DA3 source tree | `G:/GIT/debug/VR_Video_Toolbox_NE/tool_2dvr/_vendor/da3` |
| PyTorch weights | `G:/GIT/debug/VR_Video_Toolbox_NE/models/DA3/Small` and `Base` |
| ONNX output | `models/DA3` in this repository |
Canonical output names at the default size:
| File | Variant | Notes |
| --- | --- | --- |
| `da3_small.onnx` | Depth Anything 3 Small | Faster and lighter. |
| `da3_base.onnx` | Depth Anything 3 Base | Larger model, usually better depth quality. |
For non-default export sizes, the script appends the side length:
```text
models/DA3/da3_small_700.onnx
models/DA3/da3_base_1036.onnx
```
## Exported Graph
The converter wraps `DepthAnything3Net.forward(...)` with a singleton view
dimension and these fixed branch settings:
```python
skip_camera=True
skip_sky=True
infer_gs=False
use_ray_pose=False
ref_view_strategy="middle"
```
Only the depth-only sub-graph is exported:
- DINOv2 encoder, ViT-S for Small and ViT-B for Base.
- DualDPT depth head.
- Single-view input, `S=1`, one independent view per frame.
- Dynamic batch axis only.
Camera, sky, and Gaussian-splatting branches are intentionally excluded because
their `torch.quantile`, random sampling, `.item()`, and boolean-mask control
flow are not suitable for this static ONNX trace.
The script also patches DA3 RoPE's `PositionGetter` during export so
`torch.cartesian_prod` is replaced with an ONNX-exportable `meshgrid` equivalent.
## Fixed Square Input
The default input size is `518 x 518`, matching DA3's native `37 x 37` patch
grid with patch size `14`. At this size the learned positional embedding uses
the clean `npatch == N and w == h` path, avoiding bicubic position interpolation
in the exported graph.
Rules:
- Height and width are fixed in each ONNX file.
- Only the batch dimension is dynamic.
- `--size` must be a multiple of `14`.
- Re-export when you need another input side length.
## Input And Output
Default export:
```text
input name : image
input dtype: float32
input shape: [batch, 3, size, size]
layout : RGB, CHW
range : ImageNet-normalized float32
output name : depth
output dtype: float32
output shape: [batch, height, width]
```
Folded preprocessing export (`--fold-preprocess`):
```text
input name : image
input dtype: uint8
input shape: [batch, size, size, 3]
layout : RGB, HWC
range : 0..255
output name : depth
output dtype: float32
output shape: [batch, height, width]
```
The output is raw DA3 depth, which is distance-like in this project. The
2D-to-3D path treats smaller values as nearer, then resizes, inverts, clips, and
normalizes depth at runtime.
## Preprocessing
For the default float32 ONNX export:
1. Load the image or video frame as RGB.
2. Resize or letterbox to the fixed square export size.
3. Convert to float32 in the `0.0 .. 1.0` range.
4. Apply ImageNet normalization with mean `[0.485, 0.456, 0.406]` and std
`[0.229, 0.224, 0.225]`.
5. Transpose from HWC to CHW.
6. Add the batch dimension.
For `--fold-preprocess`, the ONNX graph performs steps 3 to 5 internally. The
application still needs to resize or letterbox to `[size, size]` and pass RGB
`uint8` input.
PTMediaServer's `offline.da3_depth.Da3DepthEngine` detects the ONNX input dtype
and supports both contracts. The PyNv hot path requires the folded-preprocess
model because it uploads a `uint8` letterbox canvas.
## Runtime Dependencies
CPU:
```bash
pip install onnxruntime numpy opencv-python
```
GPU:
```bash
pip install onnxruntime-gpu numpy opencv-python
```
## Quick Inference Example
This example is for the default float32 export.
```python
import cv2
import numpy as np
import onnxruntime as ort
model = "models/DA3/da3_small.onnx"
size = 518
mean = np.array([0.485, 0.456, 0.406], dtype=np.float32)
std = np.array([0.229, 0.224, 0.225], dtype=np.float32)
image_bgr = cv2.imread("input.jpg", cv2.IMREAD_COLOR)
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
resized = cv2.resize(image_rgb, (size, size), interpolation=cv2.INTER_CUBIC)
x = resized.astype(np.float32) / 255.0
x = (x - mean) / std
x = np.transpose(x, (2, 0, 1))[None, ...]
session = ort.InferenceSession(
model,
providers=["CUDAExecutionProvider", "CPUExecutionProvider"],
)
depth = session.run(["depth"], {"image": x})[0][0]
depth = cv2.resize(depth, (image_bgr.shape[1], image_bgr.shape[0]))
depth_u8 = cv2.normalize(depth, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
cv2.imwrite("depth.png", depth_u8)
```
For a folded-preprocess model, feed `resized[None, ...]` directly as `uint8`
RGB `[batch, size, size, 3]`.
## Convert From PyTorch Weights
Run the exporter from this repository root. The VR_Video_Toolbox_NE virtual
environment already contains the DA3 PyTorch dependencies:
```bash
G:/GIT/debug/VR_Video_Toolbox_NE/.venv/Scripts/python.exe \
examples/da3_to_onnx.py --variant both --validate
```
Export one variant:
```bash
python examples/da3_to_onnx.py --variant small --validate
python examples/da3_to_onnx.py --variant base --validate
```
Export folded-preprocess models for PTMediaServer's fast video paths:
```bash
python examples/da3_to_onnx.py --variant both --validate --fold-preprocess
```
Export another fixed input size:
```bash
python examples/da3_to_onnx.py --variant base --size 700 --validate --fold-preprocess
```
Useful options:
```text
--variant small|base|both
--src-root PATH Folder containing Small/ and Base/ weight directories.
--vendor PATH Vendored DA3 source root containing depth_anything_3/.
--out-dir PATH Output folder for da3_*.onnx.
--size 518 Fixed square input side. Must be a multiple of 14.
--opset 18 ONNX opset version.
--device cpu|cuda Device used for tracing. CPU is the default.
--no-validate Skip ONNX Runtime validation.
--fold-preprocess Export uint8 NHWC input with ImageNet normalize inside ONNX.
```
Expected weight layout:
```text
DA3/
Small/
model.safetensors
Base/
model.safetensors
```
## Validation
When validation is enabled, the converter compares PyTorch output with ONNX
Runtime output and reports:
- output shape
- max absolute error
- mean absolute error
- relative mean error
- active ONNX Runtime providers
The script warns if relative error is higher than `1e-2`.
## Notes
- The ONNX graph is depth-only; it does not export pose, camera, confidence,
sky segmentation, or Gaussian outputs.
- These exports are fixed-shape models. Re-export for another input side.
- Use input sizes that are multiples of `14`; `518` is the safest default.
- `--fold-preprocess` changes the ONNX input contract and overwrites the same
output filename unless you also change `--out-dir` or `--size`.
- The output is raw model depth, not metric depth.
- Smaller depth values are treated as nearer in PTMediaServer's 2D-to-3D path.
## Citation
If you use Depth Anything 3 or ONNX exports derived from it in research or a
published project, cite the upstream work:
```bibtex
@article{depthanything3,
title={Depth Anything 3: Recovering the visual space from any views},
author={Haotong Lin and Sili Chen and Jun Hao Liew and Donny Y. Chen and Zhenyu Li and Guang Shi and Jiashi Feng and Bingyi Kang},
journal={arXiv preprint arXiv:2511.10647},
year={2025}
}
```
|