Repository navigation
feat(depth): load depth maps from Inference, Ultralytics, Transformers and dataset files - #2694
Merged
Merged
Conversation
Colour any depth array over an image. Wrap a stereo disparity, metric depth or relative depth array in sv.DepthMap with the kind of value it holds, then draw it with sv.DepthAnnotator: near objects come out warm, far ones cool, and pixels without depth stay unpainted so the image shows through. It works on NumPy and Pillow images without OpenCV. - sv.DepthKind names what the values measure. NaN, infinities and values at or below 0 (below 0 for relative maps) are no depth, and valid_mask marks the rest. - sv.DepthAnnotator takes a colour table (sv.DepthColormap: Turbo, Viridis, Cividis, Inferno, Magma or grayscale), a display_range of "auto" (the map's own 2nd to 98th percentile) or a fixed (low, high) tuple, and an opacity. A metric map is coloured as inverse depth, so near detail gets most of the colours. - Reference pages, a how-to guide and a changelog entry. Closes #1313 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s and dataset files Load a depth map straight from a model result or a dataset file instead of converting it by hand. - from_inference reads a Roboflow depth model's result in every depth_map_format (JSON lists, 8- or 16-bit PNG, or the array the Inference SDK and Workflows decode), including an in-process model's response, as relative_inverse. - from_ultralytics reads YOLO26 depth results as metric depth in metres. - from_transformers reads predicted_depth from the depth-estimation pipeline or a model output; Transformers does not say what a model predicts, so the kind is required. - from_png16 loads 16-bit PNGs divided by the dataset's scale (KITTI, DrivingStereo, InStereo2K, Ultralytics depth datasets), and from_pfm loads Middlebury and SceneFlow PFM files, with unknown values as no depth. - The how-to's loading section, docstring examples and a changelog entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # docs/changelog.md
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Workflow tensors, PFM scale factors, and non-PNG payload validation are not handled correctly.
3 open findings
What changed in this PR
Adds standardized DepthMap loaders for model outputs and common depth dataset formats.
Changes:
- Adds Inference, Ultralytics, Transformers, PNG16, and PFM loaders.
- Adds offline tests for formats, validation, and byte order.
- Updates depth documentation, examples, and changelog.
Assessment: Code quality 3/5 · Testing 4/5 · Documentation 4/5
| File | Description |
|---|---|
src/supervision/depth/core.py |
Adds model and file loader APIs. |
src/supervision/depth/readers.py |
Adds PNG16 and PFM readers. |
src/supervision/depth/annotators.py |
Updates the annotator example. |
tests/depth/test_core.py |
Tests new DepthMap loaders. |
tests/depth/test_readers.py |
Tests PFM parsing and validation. |
docs/how_to/visualize_depth.md |
Documents supported loading workflows. |
docs/depth/core.md |
Updates API-page metadata. |
docs/changelog.md |
Records the new loaders. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The how-to and the DepthAnnotator example read the image through supervision._cv2, which the OpenCV migration guide marks private and not application API. They now open it with Pillow, so the examples stay OpenCV-free like the feature itself. A fixed display_range narrower than 1e-20 no longer gets stretched by a floor on its width; every range is already validated as low < high. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # docs/how_to/visualize_depth.md # src/supervision/depth/annotators.py
The six colour tables now come from matplotlib, already a dependency, instead of 140 lines of vendored hex. Colours are byte-identical to the old tables on matplotlib 3.6.3 and 3.10.3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No other annotator validates opacity, so DepthAnnotator no longer does either. Also fixes a test docstring that mentioned cameras, which this PR does not add. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The changelog says the annotator does not require OpenCV rather than that it runs without it, and uses the ([#N](...)) link style. The DepthKind docstring says relative_inverse only promises larger is nearer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # docs/changelog.md # docs/how_to/visualize_depth.md
The readers are only used by DepthMap.from_png16 and from_pfm, so they are now underscored, and _UINT16_MAX is defined once. Test helper constructors get one-line docstrings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each loading tab in the guide now runs as written: the image is opened once with Pillow before the tabs. Inference loading is described as depth models served by Roboflow Inference (Depth Anything, YOLO26 depth), from_png16 lists only sourced scales (KITTI disparity 256, Ultralytics depth datasets 1000 by default), and the DepthMap class docstring drops loader tabs that repeat each method's own example. The changelog bullet is shorter with the ([#N](...)) link style. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in the squash-merged #2691 with Jirka's follow-ups. Adaptations: - DepthMap._percentile_range stays removed (it now lives in annotators.py as _percentile_range); the loaders never called it. - visualize_depth.md: the relative-depth inversion example imports numpy itself, since the loading section now imports numpy only in the Stereo tab. - from_transformers docstring: relative_inverse is suggested for Depth Anything V1 and V2 (not V3, whose map grows with distance per DepthKind). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #2694 +/- ##
========================================
Coverage 93% 93%
========================================
Files 82 83 +1
Lines 12822 12973 +151
========================================
+ Hits 11967 12115 +148
- Misses 855 858 +3 🚀 New features to boost your workflow:
|
Tests now pin what users hit when loading depth: a transformers model output in bfloat16 that still carries grad loads like any other, and a zero from_png16 scale, an undecodable from_inference PNG and a PFM with a cut-off header each raise ValueError. The 16-bit PNG reader now always casts to uint16 instead of branching on dtype. Pillow before 10.3 opens these PNGs as int32, which the cast still handles; its 16-bit range check is gone because a PNG cannot hold more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Inference tab above loads Depth Anything V3 through from_inference, which is already larger-is-nearer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the PFM cases next to the PNG ones and drop the import of the private reader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cfviotti
marked this pull request as ready for review
October 9, 2026 05:50
…cale files from_inference now moves a tensor normalized_depth (as Workflows can return, possibly on CUDA) to a NumPy array instead of failing. A base64 JPEG or GIF is refused instead of being read as the lossless PNG the server sends. A PFM with a zero or non-finite scale is refused; the scale's sign still gives the byte order and its magnitude is not applied, as in the Middlebury reader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #2691 and #2692 (DepthClipRange) as merged, with the maintainer's edits. Adaptations: - changelog: loaders bullet (#2694) sits above the new #2692 and #2697 bullets. - visualize_depth.md front matter: description covers loading and colouring over images and video. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # docs/changelog.md # docs/depth/core.md # docs/how_to/visualize_depth.md # src/supervision/depth/core.py # tests/depth/test_core.py
- fix(depth): read the PFM scale through the guarded header loop - fix(depth): wrap Pillow decode errors in from_png16 as ValueError - docs(depth): comment the PFM header token loop [resolve group] PR #2694 — items 5 6 23 --- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Codex <codex@openai.com>
- test(depth): cover from_png16 rejection of bad files and scales - test(depth): pin from_pfm default kind, scale handling and header guards - test(depth): cover from_inference null, shape, PNG mode and base64 edges - test(depth): cover from_ultralytics batch, list, raw-array and integer inputs [resolve group] PR #2694 — items 12 13 14 16 --- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Codex <codex@openai.com>
- fix(depth): reject str, bool and out-of-range scales in from_png16 - fix(depth): reject a list of results in from_ultralytics - fix(depth): wrap invalid base64 depth in a ValueError - fix(depth): reject integer depth before the float cast in model loaders - docs(depth): note that model connectors share float32 inputs - docs(depth): list the reachable errors of each loader - docs(depth): state that from_inference maps need no inversion - docs(depth): describe from_png16 scale and Ultralytics millimetres - docs(depth): fix the from_ultralytics no-depth claim - fix(depth): divide in float32 to fix the mypy error - docs(depth): limit from_transformers to pipeline and post-processed results - feat(depth): make scale and kind keyword-only in from_png16 and from_pfm - docs(depth): state that from_png16 code 0 is no depth for every kind - docs(depth): note that only the order of relative_inverse values is meaningful [resolve group] PR #2694 — items 7 8 9 10 11 17 18 19 20 22 27 28 29 30 --- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Codex <codex@openai.com>
Borda
approved these changes
Oct 9, 2026
Borda
added a commit
to Talhax55z/supervision
that referenced
this pull request
Oct 11, 2026
Changes: - Integrate target updates for DepthMap loaders and measurement, keypoint mAP, compact-mask resizing, and mAP support with their exports, docs, and tests. - Resolve the changelog collision by preserving the PR mAR entry and target PR roboflow#2694, roboflow#2693, roboflow#2692, and roboflow#2697 entries; update date_modified. Impact: - The PR branch includes the fetched develop changes before report-item work, so follow-up validation runs against integrated code. - The changelog keeps both sets of release notes without dropping target or PR intent. Verification: - git diff --check passed after resolution. - Changelog assertions confirmed the PR and target entries and no conflict markers. - git diff --name-only --diff-filter=U returned no paths. Residual limits: - The full project gate bundle remains before remediation closure. - No source-specific regression tests have run after integration. --- Co-authored-by: Codex <codex@openai.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


One frame, three sources, one line each to load. Left: Depth Anything V3 through Roboflow's hosted API. Middle: YOLO26 depth, in metres; it sees the opening in the rock as far and everything else as close. Right: the dataset's true depth, read from its 16-bit PNG.
Description
Every depth model returns its map in its own shape and unit: a base64 16-bit PNG normalised to 0..1, a torch tensor in metres, a
predicted_depthof unknown kind. These loaders turn each into asv.DepthMapwith the right kind, the same waysv.Detections.from_ultralyticsdoes for boxes:Part 4 of 4. Needs PR 1 (#2691).
Motivation and Context
Follows #2691, where a map is built from an array by hand.
Changes Made
from_inference: everydepth_map_format(JSON lists, 8- or 16-bit PNG, and the array the SDK and Workflows decode), plus an in-process model's response, asrelative_inverse.from_ultralytics:result.depth.data, metres at the original image size.from_transformers:predicted_depthfrom thedepth-estimationpipeline or a model output. Transformers does not say what a model predicts, sokindis required.from_png16(path, scale, kind): 16-bit PNGs divided by the dataset's scale, with 0 as no depth (KITTI disparity uses 256, Ultralytics depth datasets 1000 by default).from_pfm(path, kind): Middlebury and SceneFlow PFM files, with unknown values as no depth.Testing
docs/changelog.mdunderUnreleasedfrom_inferenceon hosteddepth-anything-v3/small, in bothpng16and JSON formats: full image size, every pixel valid, near objects warm (image above)from_ultralyticsonyolo26n-depth.pt: metres at the image's exact size (image above)Additional Notes
inference,ultralytics,transformersandtorchare not imported by supervision. The loaders read the objects these libraries return.