Фаза 04 · урок 26
Монокулярная оценка глубины и геометрии
Цель урока: Глубина — недостающая ось двумерного компьютерного зрения. По RGB вы знаете, где объекты расположены в плоскости изображения, но не знаете, насколько они далеко. Датчики глубины (стереосистемы, LiDAR, time-of-flight) решают это…
Текущий релиз AlexBred.com: первые 100 уроков русскоязычной программы.
Содержание урока
- Цели обучения
- Проблема
- Концепция
- Относительная и метрическая глубина
- Паттерн «энкодер—декодер»
- Почему одно изображение вообще даёт глубину
- Чего монокулярная глубина не может
- Depth Anything V3 в 2026 году
- Marigold — диффузия для глубины
- Внутренние параметры и камера-обскура
- Оценка качества
- Соберите
- Шаг 1: Метрики глубины
- Шаг 2: Выравнивание масштаба и сдвига
- Шаг 3: Поднимите глубину в облако точек
- Шаг 4: Smoke-тест на синтетической сцене глубины
- Шаг 5: Использование Depth Anything V3 (справка)
- Используйте
- Поставьте в продакшен
- Упражнения
- Ключевые термины
- Дополнительные материалы
Карта глубины — это одноканальное изображение, где каждый пиксель содержит расстояние до камеры. Раньше предсказать её по одному RGB-кадру было невозможно без стереозрения или LiDAR. В 2026 году замороженный ViT-энкодер вместе с лёгкой головой укладывается в несколько процентов от эталонных значений.
Тип: Соберите + используйте Языки: Python Предварительные требования: Фаза 4, урок 14 (ViT), фаза 4, урок 17 (самообучаемое компьютерное зрение), фаза 4, урок 07 (U-Net) Время: ~60 минут
Цели обучения
- Различать относительную и метрическую глубину и указывать, какую задачу решает каждая производственная модель (MiDaS, Marigold, Depth Anything V3, ZoeDepth)
- Использовать Depth Anything V3 (backbone DINOv2) для предсказания глубины произвольных одиночных изображений без калибровки
- Объяснять, почему монокулярная оценка глубины вообще работает по одному изображению (перспективные признаки, текстурные градиенты, выученные априорные знания) и чего она восстановить не может (абсолютный масштаб, закрытая геометрия)
- Поднимать 2D-детекции в 3D-точки с помощью карты глубины и внутренних параметров камеры модели камеры-обскуры
Проблема
Глубина — недостающая ось двумерного компьютерного зрения. По RGB вы знаете, где объекты расположены в плоскости изображения, но не знаете, насколько они далеко. Датчики глубины (стереосистемы, LiDAR, time-of-flight) решают это напрямую, однако они дороги, хрупки и ограничены по дальности.
Монокулярная оценка глубины — предсказание глубины по одному RGB-кадру — раньше давала размытый и ненадёжный результат. К 2026 году крупные предобученные энкодеры изменили ситуацию: Depth Anything V3 использует замороженный backbone DINOv2 и строит карты глубины, обобщающиеся на помещения, улицы, медицину и спутниковые данные. Marigold формулирует глубину как задачу условной диффузии. ZoeDepth регрессирует настоящие метрические расстояния.
Глубина также служит мостом между 2D-детекцией и 3D-пониманием: умножьте пиксели обнаруженной рамки на глубину — и вы поднимете 2D-объект в облако 3D-точек. Это основа каждой системы окклюзии в AR, каждого конвейера обхода препятствий и каждого робота, которому говорят «возьми чашку».
Концепция
Относительная и метрическая глубина
- Относительная глубина — упорядоченные значения
zбез единицы реального мира. «Пиксель A ближе пикселя B, но отношение расстояний не привязано к метрам». - Метрическая глубина — абсолютное расстояние от камеры в метрах. Она требует, чтобы модель выучила статистическую связь между признаками изображения и реальным расстоянием.
MiDaS и Depth Anything V3 выдают относительную глубину. Marigold также выдаёт относительную глубину. ZoeDepth, UniDepth и Metric3D выдают метрическую глубину. Метрические модели чувствительны к внутренним параметрам камеры, а относительные — нет.
Паттерн «энкодер—декодер»
Depth Anything V3 замораживает энкодер и обучает только декодер в стиле DPT. Энкодер предоставляет богатые признаки; декодер интерполирует их обратно до разрешения изображения и регрессирует глубину.
Почему одно изображение вообще даёт глубину
Двумерное изображение содержит много монокулярных признаков, коррелирующих с глубиной:
- Перспектива — параллельные линии в 3D сходятся в 2D.
- Текстурный градиент — у далёких поверхностей текстура мельче и плотнее.
- Порядок перекрытия — ближние объекты закрывают дальние.
- Постоянство размера — известные объекты (автомобили, люди) дают приблизительный масштаб.
- Атмосферная перспектива — далёкие объекты на уличных сценах выглядят более дымчатыми и синими.
ViT, обученный на миллиардах изображений, усваивает эти признаки. При достаточном количестве данных и сильном backbone монокулярная глубина достигает разумной точности без явного 3D-обучения.
Чего монокулярная глубина не может
- Абсолютного метрического масштаба без внутренних параметров или известного объекта в сцене. Сеть может предсказать, что «чашка вдвое дальше ложки», не зная, находится ли чашка в 1 м или 10 м.
- Закрытой геометрии — задняя часть стула не видна, поэтому её нельзя надёжно вывести.
- По-настоящему бесфактурных / отражающих поверхностей — зеркал, стекла, однородных стен. Сеть сообщит правдоподобную, но неверную глубину.
Depth Anything V3 в 2026 году
- Vanilla DINOv2 ViT-L/14 в роли энкодера (заморожен).
- Декодер DPT.
- Обучен на позированных парах изображений из разных источников (явный supervision глубины не нужен, достаточно фотометрической согласованности).
- Предсказывает пространственно согласованную геометрию по произвольному числу визуальных входов, с известными позами камер или без них.
- SOTA для монокулярной глубины, геометрии произвольного ракурса, визуального рендеринга и оценки позы камеры.
Это готовая модель, которую стоит вызывать, когда в 2026 году нужна глубина.
Marigold — диффузия для глубины
Marigold (Ke et al., CVPR 2024) переформулирует оценку глубины как условную диффузию image-to-image. Условие: RGB. Цель: карта глубины. В качестве backbone используется предобученный U-Net Stable Diffusion 2. Карты глубины на выходе исключительно резкие по границам объектов. Компромисс: инференс медленнее, чем у feed-forward-моделей (10–50 шагов денойзинга).
Внутренние параметры и камера-обскура
Чтобы поднять пиксель (u, v) с глубиной d в 3D-точку (X, Y, Z) в координатах камеры:
fx, fy, cx, cy = camera intrinsics
X = (u - cx) * d / fx
Y = (v - cy) * d / fy
Z = d
Внутренние параметры берутся из метаданных EXIF, калибровочного шаблона или монокулярного оценщика внутренних параметров (Perspective Fields, UniDepth). Без них всё ещё можно визуализировать облако точек, приняв FOV 60–70° и главные точки умеренного разрешения: этого достаточно для визуализации, но не для измерений.
Оценка качества
Две стандартные метрики:
- AbsRel (absolute relative error, абсолютная относительная ошибка):
mean(|d_pred - d_gt| / d_gt). Меньше — лучше. Для производственных моделей это 0,05–0,1. - delta < 1.25 (точность по порогу): доля пикселей, где
max(d_pred/d_gt, d_gt/d_pred) < 1.25. Больше — лучше. Для SOTA это 0,9+.
Для относительной глубины (Depth Anything V3, MiDaS) при оценке используются варианты обеих метрик, инвариантные к масштабу и сдвигу.
Соберите
Шаг 1: Метрики глубины
import torch
def abs_rel_error(pred, target, mask=None):
if mask is not None:
pred = pred[mask]
target = target[mask]
return (torch.abs(pred - target) / target.clamp(min=1e-6)).mean().item()
def delta_accuracy(pred, target, threshold=1.25, mask=None):
if mask is not None:
pred = pred[mask]
target = target[mask]
ratio = torch.maximum(pred / target.clamp(min=1e-6), target / pred.clamp(min=1e-6))
return (ratio < threshold).float().mean().item()
Перед оценкой всегда маскируйте недопустимые пиксели глубины (нулевые, NaN, насыщенные).
Шаг 2: Выравнивание масштаба и сдвига
Для моделей относительной глубины перед вычислением метрик выровняйте предсказание по истинному значению. Выполните подгонку методом наименьших квадратов для a * pred + b = target:
def align_scale_shift(pred, target, mask=None):
if mask is not None:
p = pred[mask]
t = target[mask]
else:
p = pred.flatten()
t = target.flatten()
A = torch.stack([p, torch.ones_like(p)], dim=1)
coeffs, *_ = torch.linalg.lstsq(A, t.unsqueeze(-1))
a, b = coeffs[:2, 0]
return a * pred + b
При оценке MiDaS / Depth Anything запускайте align_scale_shift перед abs_rel_error.
Шаг 3: Поднимите глубину в облако точек
import numpy as np
def depth_to_point_cloud(depth, intrinsics):
H, W = depth.shape
fx, fy, cx, cy = intrinsics
v, u = np.meshgrid(np.arange(H), np.arange(W), indexing="ij")
z = depth
x = (u - cx) * z / fx
y = (v - cy) * z / fy
return np.stack([x, y, z], axis=-1)
depth = np.random.uniform(0.5, 4.0, (240, 320))
intr = (320.0, 320.0, 160.0, 120.0)
pc = depth_to_point_cloud(depth, intr)
print(f"point cloud shape: {pc.shape} (H, W, 3)")
Одна функция — и у вас есть каждое приложение с подъёмом в 3D. Экспортируйте облако точек в .ply и откройте его в MeshLab или CloudCompare.
Шаг 4: Smoke-тест на синтетической сцене глубины
def synthetic_depth(size=96):
yy, xx = np.meshgrid(np.arange(size), np.arange(size), indexing="ij")
# Floor: linear gradient from near (top) to far (bottom)
depth = 1.0 + (yy / size) * 4.0
# Box in the middle: closer
mask = (np.abs(xx - size / 2) < size / 6) & (np.abs(yy - size * 0.6) < size / 6)
depth[mask] = 2.0
return depth.astype(np.float32)
gt = torch.from_numpy(synthetic_depth(96))
pred = gt + 0.3 * torch.randn_like(gt) # simulated prediction
aligned = align_scale_shift(pred, gt)
print(f"before align absRel = {abs_rel_error(pred, gt):.3f}")
print(f"after align absRel = {abs_rel_error(aligned, gt):.3f}")
Шаг 5: Использование Depth Anything V3 (справка)
import torch
from transformers import pipeline
from PIL import Image
pipe = pipeline(task="depth-estimation", model="LiheYoung/depth-anything-v2-large")
image = Image.open("street.jpg").convert("RGB")
out = pipe(image)
depth_np = np.array(out["depth"])
Три строки. out["depth"] — это PIL grayscale; для вычислений преобразуйте его в numpy. Для Depth Anything V3 достаточно заменить идентификатор модели после её выпуска; API не меняется.
Используйте
- Depth Anything V3 (Meta AI / ByteDance, 2024–2026) — вариант по умолчанию для относительной глубины. Самая быстрая производственная модель с backbone ViT-large.
- Marigold (ETH, 2024) — высочайшее визуальное качество, но медленный инференс.
- UniDepth (ETH, 2024) — метрическая глубина с оценкой внутренних параметров камеры.
- ZoeDepth (Intel, 2023) — метрическая глубина; старая, но всё ещё надёжная.
- MiDaS v3.1 — устаревшая, но стабильная; хорошая базовая линия для сравнения.
Типичный паттерн интеграции:
- Приходит RGB-кадр.
- Модель глубины строит карту глубины.
- Детектор строит рамки.
- Поднимите центроиды рамок через глубину в 3D; при наличии объедините с облаком точек.
- Последующие задачи: окклюзия в AR, планирование пути, оценка размера объектов, замена стереозрения.
Для работы в реальном времени Depth Anything V2 Small (квантованная INT8) достигает ~30 fps на потребительском GPU при 518x518.
Поставьте в продакшен
Этот урок создаёт:
outputs/prompt-depth-model-picker.md— выбирает между Depth Anything V3, Marigold, UniDepth и MiDaS с учётом задержки, потребности в метрической или относительной глубине и типа сцены.outputs/skill-depth-to-pointcloud.md— навык, строящий облака точек по картам глубины с корректной обработкой внутренних параметров и экспортом в.ply.
Упражнения
- (Легко) Запустите Depth Anything V2 на любых 10 изображениях своего стола. Сохраните глубину как PNG в оттенках серого и изучите результат. Найдите один объект, для которого предсказанная глубина выглядит неверно, и объясните, почему монокулярные признаки не сработали.
- (Средне) Имея RGB + глубину от Depth Anything V2, поднимите данные в облако точек и визуализируйте с
open3d. Сравните две сцены (внутреннюю / уличную) и отметьте, какая выглядит убедительнее. - (Сложно) Возьмите пять пар изображений, отличающихся только положением известного объекта (например, бутылку передвинули на 30 см ближе). Используйте UniDepth для предсказания метрической глубины на обоих изображениях. Сообщите предсказанную разницу расстояний относительно реальных 30 см.
Ключевые термины
| Термин | Как обычно говорят | Что это на самом деле означает |
|---|---|---|
| Монокулярная глубина | «Глубина по одному изображению» | Оценка глубины по одному RGB-кадру без стереозрения или LiDAR |
| Относительная глубина | «Упорядоченная глубина» | Упорядоченные z-значения без единиц реального мира |
| Метрическая глубина | «Абсолютное расстояние» | Глубина в метрах; требует калибровки или модели, обученной с метрическим supervision |
| AbsRel | «Абсолютная относительная ошибка» | Среднее значение |d_pred - d_gt| / d_gt; стандартная метрика глубины |
| Delta accuracy | «delta < 1.25» | Доля пикселей, чьё предсказание находится в пределах 25% от истинного значения |
| Камера-обскура | «fx, fy, cx, cy» | Модель камеры, используемая для подъёма (u, v, d) в (X, Y, Z) |
| DPT | «Dense Prediction Transformer» | Свёрточный декодер поверх замороженных ViT-энкодеров для глубины |
| Backbone DINOv2 | «Причина, почему это работает» | Самообучаемые признаки, обобщающиеся между доменами без меток глубины |
Дополнительные материалы
- Страница статьи Depth Anything V3 — SOTA монокулярной глубины с энкодером DINOv2
- Marigold (Ke et al., CVPR 2024) — оценка глубины на основе диффузии
- UniDepth (Piccinelli et al., 2024) — метрическая глубина с внутренними параметрами камеры
- MiDaS v3.1 (Intel ISL) — каноническая базовая линия относительной глубины
- Пост в блоге о DINOv3 (Meta) — семейство энкодеров, повышающее точность оценки глубины
Источник: Monocular Depth & Geometry Estimation 04.25 — Модели «зрение—язык» · Фаза 04 — Компьютерное зрение · 04.27 — Отслеживание нескольких объектов · Полный каталог