> This is the documentation for LibreYOLO 1.6.0. Current version: https://www.libreyolo.com/docs/tasks/depth-estimation

# Depth estimation
Depth estimation predicts how far each pixel is from the camera using a single image. LibreYOLO exposes it as the depth task, which returns a dense relative inverse-depth map on the original image canvas.
Verified against LibreYOLO v1.6.0.

## Definition

The `depth` task predicts one value per pixel from a single RGB image. LibreYOLO
defines that value as relative inverse depth: higher means closer to the camera,
and the numbers carry no metric unit and no scale that holds across two images.
Comparing depth between two pixels of the same prediction is meaningful;
comparing a value to a value from another image is not.

A prediction fills `result.depth_map`, a `DepthMap` payload holding an
`(H, W)` array on the original image canvas. `.min`, `.max` and `.mean` read the
finite values, and `.normalized()` rescales the map to `[0, 1]` for display.
`result.boxes` stays empty, so `conf`, `iou` and `max_det` have no effect,
and `save=True` writes a colormapped image of the map rather than an annotated
photo.

## Models

The following families serve `depth`.

[Depth Anything V2](/docs/v1.6.0/models/depth-anything-v2) pairs a DINOv2 encoder with
a DPT decoder and is the general-purpose default here. Licensing decides the
size as much as accuracy does: the Small checkpoint is Apache-2.0 while Base and
Large are non-commercial, so check the checkpoint table on its page before
picking one.

[Depth Anything 3](/docs/v1.6.0/models/depth-anything-3) ports the DA3MONO-LARGE
checkpoint, a plain transformer with no architectural specialization for depth.

[ZipDepth](/docs/v1.6.0/models/zipdepth) is the compact tier: a reparameterizable CNN
distilled from Depth Anything V2 Large, with a second checkpoint whose decoder
avoids gather and unfold operations for NPU compilers that lack them.

[MiDaS](/docs/v1.6.0/models/midas) is the line of work that established the zero-shot
relative-depth protocol the other families are measured with. Its s and l checkpoints download from LibreYOLO mirrors under the publisher MIT grant.

[LibreMODUS](/docs/v1.6.0/models/libremodus) reaches depth as one target of an
any-to-any model rather than as a dedicated head. It needs the `modus` extra and
your own authenticated Hugging Face account, and it offers neither `val()` nor
`export()`.

[SenseNova-Vision](/docs/v1.6.0/models/sensenova-vision) generates the depth map as an
image through a diffusion decode, from the same 7B checkpoint that serves its
six other tasks. It needs the `sensenova` extra, and its weights are restricted
to non-commercial use; the license is on its page.

[Marigold V2](/docs/v1.6.0/models/marigold-v2) adds diffusion-based depth adapters with explicit depth encodings.

[GTR](/docs/v1.6.0/models/gtr) predicts metric depth and returns it as relative
inverse depth, so `1 / result.depth_map.data` recovers meters for scenes like
its training data. It runs on the base package, trains, and exports to ONNX and
TorchScript.

## Predict

Weights download on first use and are cached locally. The model pages describe authentication and runtime requirements.

**Predict a depth map**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

model = LibreYOLO("LibreDepthAnythingV2s-depth.pt")
result = model(SAMPLE_IMAGE, save=True)

depth = result.depth_map
print(depth.data.shape)              # (H, W) on the original canvas
print(depth.min, depth.max, depth.mean)
```

**Work with the values**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

model = LibreYOLO("LibreDepthAnythingV2s-depth.pt")
result = model(SAMPLE_IMAGE)

depth = result.depth_map
raw = depth.data          # higher is closer; no metric unit, no scale
gray = depth.normalized() # rescaled to [0, 1] for visualization
print(raw.shape, float(gray.max()))
```

**A compact alternative**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

# Same task contract, a much smaller network built for edge runtimes.
model = LibreYOLO("LibreZipDepthb-depth.pt")
result = model(SAMPLE_IMAGE)

print(result.depth_map.data.shape)
```

Input resolution is constrained per family. Depth Anything V2 and Depth Anything
3 build on a DINOv2 patch grid, so `imgsz` must divide evenly by 14, which
LibreYOLO checks before running. `Results.plot()` renders depth results. See [prediction](/docs/v1.6.0/predict)
for sources, streaming and result handling.

`DepthMap.encoding` is `inverse_depth` by default and may be `depth` or `log_depth`. Validation interprets the encoding before affine alignment. The encoding does not give relative predictions a metric scale.

## Dataset format

Depth validation pairs each image with a dense single-channel depth map that has
the same resolution, found by substituting the depth directory into the image
path.

```text
dataset/
  data.yaml
  images/
    val/room.jpg
  depths/
    val/room.png
```

```yaml
path: dataset
val: images/val
depths_dir: depths
nc: 1
names: {0: depth}
```

Maps are single-channel PNG or TIF, or `.npy`. Values are plain depth in a unit
the dataset keeps consistent, and `0`, negative, NaN and infinite pixels mark
invalid samples that are excluded from the metrics. Integer maps are divided by
`depth_scale`, which defaults to `256.0`, the 16-bit PNG convention; float
`.npy` maps are used as they are. `depth_stem_suffix` and `depth_mask_suffix`
cover datasets that name their depth files or validity masks differently. See
[dataset formats](/docs/v1.6.0/reference/dataset-formats) for the full contract.

## Train

[GTR](/docs/v1.6.0/models/gtr) is the one depth family that trains: `train()` on a
`-depth` checkpoint runs its upstream recipe, which its model page describes. On
the other families `train()` raises `NotImplementedError`. Each model page names
the conversion script that turns a checkpoint trained upstream into one LibreYOLO
can load.

## Validate

`val()` runs the shared depth validator. Relative depth has no absolute scale,
so each prediction is first fitted to the inverse of its ground truth with a
per-image least-squares scale and shift, then inverted back to depth. Every
metric below is computed per image on that aligned map and averaged over the
dataset, counting only pixels the dataset marks valid.

**Validate and read the metric keys**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreDepthAnythingV2s-depth.pt")
metrics = model.val(data="my-dataset.yaml")

print(metrics["metrics/abs_rel"])
print(metrics["metrics/rmse"])
print(metrics["metrics/delta1"])   # fitness
print(metrics["metrics/delta2"], metrics["metrics/delta3"])
```

`metrics/abs_rel` is the mean absolute relative error, the residual divided by
the ground-truth depth, and lower is better. `metrics/rmse` is the root mean
squared error in the dataset's own depth unit, also lower is better.
`metrics/delta1`, `metrics/delta2` and `metrics/delta3` are the threshold
accuracies: the fraction of valid pixels whose ratio to ground truth, taken in
whichever direction is larger, falls under 1.25, 1.25 squared and 1.25 cubed, so
higher is better. `metrics/delta1` is also `fitness`, the number
best-checkpoint selection reads.

## Export

An exported depth model loads back through `LibreYOLO()` on its file suffix, so
a `.onnx` or `.engine` file behaves like a checkpoint and returns the same
`Results`, with `depth_map` in place of boxes.

**Export**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreDepthAnythingV2s-depth.pt")
model.export(format="onnx")
```

**Run the exported file**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

# The factory routes on the file suffix, so an exported artifact loads
# like any checkpoint and returns the same Results object.
model = LibreYOLO("LibreDepthAnythingV2s-depth.onnx")
result = model(SAMPLE_IMAGE)

print(result.depth_map.data.shape)
```

Coverage differs per family, and Depth Anything 3 rejects any format outside its
validated set rather than attempting an unvalidated conversion. Check the model
page and the [full export matrix](/docs/v1.6.0/reference/export-matrix) before
committing to a target. LibreMODUS and SenseNova-Vision do not export at all.
[Export](/docs/v1.6.0/export) lists the arguments every format accepts.
