Faza 04 · lecția 26
Adâncimea monoculară și estimarea geometriei
Scopul lecției: O hartă de adâncime este o imagine cu un singur canal, în care fiecare pixel reprezintă o distanță față de cameră. Predicția ei dintr-un singur cadru RGB era imposibilă fără stereo sau LiDAR. În 2026, un encoder ViT înghețat plus un cap…
Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.
Cuprinsul lecției
- Obiective de învățare
- Problema
- Conceptul
- Adâncime relativă versus metrică
- Tiparul encoder–decoder
- De ce produce adâncime o singură imagine
- Ce nu poate face adâncimea monoculară
- Depth Anything V3 în 2026
- Marigold — difuzie pentru adâncime
- Intrinsecele și camera pinhole
- Evaluare
- Construiți
- Pasul 1: metrici de adâncime
- Pasul 2: alinierea scării și a translației
- Pasul 3: ridicați adâncimea într-un nor de puncte
- Pasul 4: test rapid cu o scenă sintetică de adâncime
- Pasul 5: folosirea Depth Anything V3 (referință)
- Utilizați
- Livrați
- Exerciții
- Termeni-cheie
- Lecturi suplimentare
O hartă de adâncime este o imagine cu un singur canal, în care fiecare pixel reprezintă o distanță față de cameră. Predicția ei dintr-un singur cadru RGB era imposibilă fără stereo sau LiDAR. În 2026, un encoder ViT înghețat plus un cap ușor ajung la câteva procente de adevărul de referință.
Tip: Construiți + utilizați Limbaje: Python Cerințe prealabile: Faza 4 Lecția 14 (ViT), Faza 4 Lecția 17 (Viziune auto-supervizată), Faza 4 Lecția 07 (U-Net) Timp: ~60 de minute
Obiective de învățare
- Deosebiți adâncimea relativă de cea metrică și precizați ce rezolvă fiecare model de producție (MiDaS, Marigold, Depth Anything V3, ZoeDepth)
- Utilizați Depth Anything V3 (backbone DINOv2) pentru a prezice adâncimea unor imagini individuale arbitrare, fără calibrare
- Explicați de ce adâncimea monoculară funcționează dintr-o singură imagine (indicii de perspectivă, gradienți de textură, priori învățate) și ce nu poate recupera (scara absolută, geometria ocluzată)
- Ridicați detecțiile 2D în puncte 3D folosind o hartă de adâncime și intrinsecele unei camere pinhole
Problema
Adâncimea este axa care lipsește din viziunea computerizată 2D. Dat RGB, se știe unde apar lucrurile în planul imaginii, însă nu și cât de departe sunt. Senzorii de adâncime (configurații stereo, LiDAR, time-of-flight) rezolvă aceasta direct, dar sunt costisitori, fragili și limitați ca rază.
Estimarea monoculară a adâncimii — predicția adâncimii dintr-un singur cadru RGB — producea ieșiri neclare și nesigure. Până în 2026, encoderele preantrenate mari au schimbat situația: Depth Anything V3 utilizează un backbone DINOv2 înghețat și produce hărți de adâncime care se generalizează pentru domenii de interior, exterior, medicale și satelitare. Marigold reformulează adâncimea ca problemă de difuzie condiționată. ZoeDepth estimează distanțe metrice reale.
Adâncimea este și puntea dintre detectarea 2D și înțelegerea 3D: înmulțiți pixelii unei casete detectate cu adâncimea și ridicați obiectul 2D într-un nor de puncte 3D. Aceasta este baza fiecărui sistem de ocluzie AR, a fiecărui flux de evitare a obstacolelor și a fiecărui robot care „ridică cana”.
Notă tehnică a traducerii: O casetă de detecție nu furnizează singură un punct 3D: selectați pixeli ai obiectului cu adâncime validă, stabiliți convenția lui
z, apoi retroproiectați-i cu intrinsecele și scara adecvate. O casetă poate include fundal și ocluzii; pentru poziția obiectului este necesar un agregat robust al pixelilor obiectului, ideal după segmentare.
Notă tehnică a traducerii: Depth Anything 3 (DA3) nu este descris corect ca un simplu DINOv2 ViT-L/14 înghețat cu decoder DPT. Documentația și raportul său tehnic îl prezintă ca un Transformer simplu pentru geometrie coerentă dintr-un număr arbitrar de intrări vizuale, cu sau fără poziții cunoscute ale camerelor; familia include și variante metrice. Adresa originală
https://depth-anything.github.io/este pagina proiectului Depth Anything din CVPR 2024, nu pagina DA3. Folosiți o versiune și un checkpoint explicit, deoarece Depth Anything V1, V2 și DA3 au API-uri, obiective și capabilități diferite.
Conceptul
Adâncime relativă versus metrică
- Adâncime relativă — valori
zordonate, fără unitate din lumea reală. „Pixelul A este mai aproape decât pixelul B, însă raportul distanțelor nu este ancorat în metri.” - Adâncime metrică — distanța absolută în metri față de cameră. Necesită ca modelul să fi învățat relația statistică dintre indicii imaginii și distanța reală.
MiDaS și Depth Anything V3 produc adâncime relativă. Marigold produce adâncime relativă. ZoeDepth, UniDepth și Metric3D produc adâncime metrică. Modelele metrice sunt sensibile la intrinsecele camerei; cele relative nu sunt.
Notă tehnică a traducerii: Dihotomia de mai sus simplifică excesiv familiile de modele. Depth Anything oferă variante relative și variante ajustate pentru adâncime metrică, iar UniDepth își estimează reprezentarea camerei din imagine la inferență. Intrinsecele, distribuția datelor și protocolul de calibrare pot influența orice predicție geometrică; adâncimea relativă nu devine automat independentă de cameră în toate condițiile. În plus, „adâncime” poate desemna adâncimea axială
Z, adâncimea inversă sau disparitatea; conversiile, alinierea și retroproiecția depind de convenția aleasă.
Tiparul encoder–decoder
Depth Anything V3 îngheață encoderul și antrenează numai decoderul în stil DPT. Encoderul oferă caracteristici bogate; decoderul le interpolează înapoi la rezoluția imaginii și estimează adâncimea prin regresie.
Notă tehnică a traducerii: Această diagramă este un tipar util, nu arhitectura completă și invariabilă a DA3. În special, descrierea „îngheață encoderul și antrenează numai decoderul DPT” nu trebuie aplicată fără verificarea checkpointului și a codului folosite; DA3 extinde problema către geometrie din mai multe vederi, nu doar către o hartă monoculară produsă de un decoder DPT.
De ce produce adâncime o singură imagine
O imagine 2D conține multe indicii monoculare corelate cu adâncimea:
- Perspectivă — liniile paralele în 3D converg în 2D.
- Gradient de textură — suprafețele îndepărtate au textură mai mică și mai densă.
- Ordinea ocluziei — obiectele mai apropiate le ocluzează pe cele mai îndepărtate.
- Constanța dimensiunii — obiectele cunoscute (mașini, oameni) oferă o scară aproximativă.
- Perspectivă atmosferică — obiectele îndepărtate par mai cețoase și mai albăstrui în scene exterioare.
Un ViT antrenat pe miliarde de imagini interiorizează aceste indicii. Cu suficiente date și un backbone puternic, adâncimea monoculară atinge o acuratețe rezonabilă fără supraveghere 3D explicită.
Notă tehnică a traducerii: Adâncimea monoculară este geometric subdeterminată: o rețea poate folosi priori statistici pentru a aproxima scara metrică, dar o singură imagine nu determină în general unic geometria și scara absolută. Afirmațiile despre numărul de imagini, supraveghere și generalizare trebuie raportate la rețeta concretă de antrenare, datele și benchmarkul modelului.
Ce nu poate face adâncimea monoculară
- Scară metrică absolută fără intrinsece sau un obiect cunoscut în scenă. Rețeaua poate prezice „cana este de două ori mai departe decât lingura” fără să știe dacă cana se află la 1 m sau la 10 m.
- Geometrie ocluzată — spatele unui scaun nu este vizibil și nu poate fi dedus fiabil.
- Suprafețe cu adevărat netexturate / reflectorizante — oglinzi, sticlă, pereți uniformi. Rețeaua raportează o adâncime plauzibilă, dar greșită.
Depth Anything V3 în 2026
- ViT-L/14 DINOv2 simplu drept encoder (înghețat).
- Decoder DPT.
- Antrenat pe perechi de imagini cu poziții cunoscute din surse diverse (nu este necesară supraveghere explicită de adâncime, dincolo de consistența fotometrică).
- Prezice geometrie coerentă spațial din un număr arbitrar de intrări vizuale, cu sau fără poziții cunoscute ale camerelor.
- SOTA pentru adâncime monoculară, geometrie din orice număr de vederi, redare vizuală și estimarea poziției camerei.
Acesta este modelul plug-and-play de apelat când este necesară adâncime în 2026.
Notă tehnică a traducerii: DA3 poate fi folosit pentru sarcini de geometrie, însă „SOTA” și „modelul implicit” sunt afirmații dependente de task și benchmark. Raportul DA3 descrie un model antrenat exclusiv pe seturi publice academice și compară rezultatele în propriul protocol; el nu justifică afirmații universale despre domenii medicale sau satelitare. Alegeți checkpointul relativ sau metric conform ieșirii cerute și validați-l pe datele de implementare.
Marigold — difuzie pentru adâncime
Marigold (Ke et al., CVPR 2024) reformulează estimarea adâncimii ca difuzie condiționată imagine-la-imagine. Condiționare: RGB. Țintă: hartă de adâncime. Utilizează drept backbone un U-Net Stable Diffusion 2 preantrenat. Hărțile de adâncime rezultate sunt excepțional de clare la marginile obiectelor. Compromisul: inferență mai lentă decât modelele feed-forward (10–50 de pași de denoising).
Notă tehnică a traducerii: Marigold original este un estimator monocular de adâncime invariant la transformări afine, derivat din Stable Diffusion. Numărul de pași de denoising, claritatea frontierelor și viteza depind de scheduler, rezoluție, ensemble și implementare; comparați pe același protocol cu estimatorul feed-forward ales.
Intrinsecele și camera pinhole
Pentru a ridica un pixel (u, v) cu adâncimea d într-un punct 3D (X, Y, Z) în coordonate de cameră:
fx, fy, cx, cy = intrinsecele camerei
X = (u - cx) * d / fx
Y = (v - cy) * d / fy
Z = d
Intrinsecele provin din metadate EXIF, un tipar de calibrare sau un estimator monocular de intrinsece (Perspective Fields, UniDepth). Fără intrinsece, se poate reda totuși un nor de puncte presupunând un FOV de 60–70° și punct principal la rezoluție moderată — utilizabil pentru vizualizare, nu pentru măsurare.
Notă tehnică a traducerii: Formula presupune convenția pinhole și faptul că
deste adâncimea axială în sistemul camerei, în aceleași unități ca rezultatul dorit. O adâncime relativă sau o adâncime radială nu poate produce direct măsurători metrice prin această formulă. EXIF-ul de consum nu conține de regulă toate intrinsecele calibrate; punctul principal este un parametru intrinsec și nu este garantat în centrul imaginii. FOV-ul presupus trebuie folosit numai pentru o vizualizare explicit aproximativă.
Evaluare
Două metrici standard:
- AbsRel (eroare relativă absolută):
mean(|d_pred - d_gt| / d_gt). Mai mic este mai bun. 0.05–0.1 pentru modele de producție. - delta < 1.25 (acuratețe de prag): fracția pixelilor pentru care
max(d_pred/d_gt, d_gt/d_pred) < 1.25. Mai mare este mai bun. 0.9+ pentru SOTA.
Pentru adâncime relativă (Depth Anything V3, MiDaS), evaluarea folosește versiuni invariante la scalare și translație ale ambelor metrici.
Notă tehnică a traducerii: Valorile AbsRel și delta nu sunt praguri universale de producție sau SOTA: ele depind puternic de setul de date, intervalul de adâncime, mască, crop, aliniere și protocol. Mai mult, protocoalele de evaluare pentru adâncime relativă nu sunt identice între benchmarkuri; aplicați exact alinierea și masca prescrise de reperul de evaluare ales.
Construiți
Pasul 1: metrici de adâncime
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()
Mascați întotdeauna pixelii de adâncime nevalizi (zero, NaN, saturați) înainte de evaluare.
Notă tehnică a traducerii: În plus față de mascare, validați că valorile rămase sunt pozitive și finite înainte de împărțire.
clamp(min=1e-6)evită împărțirea la zero, dar transformă valori invalide nemascate într-o eroare artificială foarte mare; nu înlocuiește masca de evaluare a setului de date. Opriți calculul dacă masca finală este goală.
Pasul 2: alinierea scării și a translației
Pentru modelele cu adâncime relativă, aliniați predicția la adevărul de referință înainte de calcularea metricilor. Ajustare prin cele mai mici pătrate pentru 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
Rulați align_scale_shift înainte de abs_rel_error atunci când evaluați MiDaS / Depth Anything.
Notă tehnică a traducerii: Această aliniere este adecvată numai când protocolul o permite și masca exclude pixelii nevalizi. Ea poate ascunde eroarea de scară a unui model și, în cazuri degenerescente, poate produce o scală negativă; nu o utilizați pentru a declara metrică o predicție relativă sau pentru o evaluare metrică absolută. Înainte de
lstsq, verificați că masca selectează suficienți pixeli cu variație; o problemă de rang deficient poate da o soluție instabilă sau lipsită de sens.
Pasul 3: ridicați adâncimea într-un nor de puncte
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)")
O funcție, pentru fiecare aplicație cu ridicare 3D. Exportați norul de puncte în .ply și deschideți-l în MeshLab sau CloudCompare.
Notă tehnică a traducerii:
depth_to_point_cloudîntoarce o grilăH × W × 3, nu un fișier PLY gata de export. Înainte de export, aplatizați grila, eliminați punctele cu adâncime nevalidă și atașați eventualele culori sau atribute în formatul PLY cerut de instrumentul folosit.
Pasul 4: test rapid cu o scenă sintetică de adâncime
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}")
Notă tehnică a traducerii: Scena sintetică folosește o „podea” a cărei adâncime crește de sus în jos, o alegere convenabilă pentru test, nu o proiecție fizică generală a unei podele într-o cameră pinhole. Testul verifică doar funcțiile demonstrative și nu evaluează generalizarea unui estimator monocular.
Pasul 5: folosirea Depth Anything V3 (referință)
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"])
Trei linii. out["depth"] este un PIL în tonuri de gri; convertiți-l în numpy pentru calcule. Pentru Depth Anything V3 în mod specific, înlocuiți identificatorul modelului după lansare; API-ul rămâne neschimbat.
Notă tehnică a traducerii: Fragmentul încarcă explicit
LiheYoung/depth-anything-v2-large, deci demonstrează Depth Anything V2, nu DA3. O imagine PIL de adâncime poate fi o vizualizare normalizată și nu trebuie confundată cu o hartă metrică pentru măsurători; verificați câmpurile de ieșire și preprocesarea checkpointului. DA3 are propriul cod și propriile variante de checkpoint, iar compatibilitatea cupipeline("depth-estimation")nu trebuie presupusă fără documentația versiunii instalate. Linianp.array(...)presupune importulnumpy as npdin fragmentul anterior; executată izolat, nu este completă.
Utilizați
- Depth Anything V3 (Meta AI / ByteDance, 2024–2026) — opțiunea implicită pentru adâncime relativă. Cel mai rapid model cu backbone ViT-large în producție.
- Marigold (ETH, 2024) — cea mai bună calitate vizuală, inferență lentă.
- UniDepth (ETH, 2024) — adâncime metrică cu estimarea intrinsecilor camerei.
- ZoeDepth (Intel, 2023) — adâncime metrică; mai vechi, încă fiabil.
- MiDaS v3.1 — moștenit, dar stabil; bază de comparație bună.
Tipar tipic de integrare:
- Sosește cadrul RGB.
- Modelul de adâncime produce harta de adâncime.
- Detectorul produce casete.
- Ridicați centroizii casetelor prin adâncime în 3D; îmbinați cu norul de puncte dacă este disponibil.
- În aval: ocluzie AR, planificarea traseului, estimarea dimensiunii obiectelor, înlocuirea stereo.
Pentru utilizare în timp real, Depth Anything V2 Small cuantizat INT8 atinge ~30 fps pe un GPU de consum la 518x518.
Notă tehnică a traducerii: Afirmațiile „opțiunea implicită”, „cea mai bună calitate” și „cel mai rapid” nu sunt clasamente universale. Performanța în timp real depinde de checkpoint, runtime, cuantizare, rezoluție, lot și hardware; măsurați latența completă și calitatea pe scenele proprii. În particular, cifra de aproximativ 30 fps pentru V2 Small INT8 la 518×518 descrie numai configurația măsurată, nu toate modelele sau GPU-urile. O hartă de adâncime monoculară nu înlocuiește un sistem stereo pentru aplicații de siguranță fără validarea incertitudinii, a scării și a cazurilor de eșec.
Livrați
Această lecție produce:
outputs/prompt-depth-model-picker.md— alege între Depth Anything V3, Marigold, UniDepth, MiDaS în funcție de latență, necesitatea metrică versus relativă și tipul scenei.outputs/skill-depth-to-pointcloud.md— o competență care construiește nori de puncte din hărți de adâncime, cu gestionarea corectă a intrinsecilor și export în.ply.
Exerciții
- (Ușor) Rulați Depth Anything V2 pe oricare 10 imagini ale biroului dumneavoastră. Salvați adâncimea ca PNG-uri în tonuri de gri și inspectați-le. Identificați un obiect a cărui adâncime prezisă pare greșită și explicați de ce indicii monoculari au eșuat.
- (Mediu) Dat RGB + adâncime de la Depth Anything V2, ridicați-le într-un nor de puncte și redați-l cu
open3d. Comparați două scene (interior / exterior) și notați care pare mai credibilă. - (Dificil) Luați cinci perechi de imagini care diferă numai prin poziția unui obiect cunoscut (de exemplu, o sticlă mutată cu 30 cm mai aproape). Utilizați UniDepth pentru a prezice adâncimea metrică pentru ambele. Raportați delta de distanță prezisă față de cei 30 cm reali.
Termeni-cheie
| Termen | Cum este numit în practică | Ce înseamnă de fapt |
|---|---|---|
| Adâncime monoculară | „Adâncime dintr-o singură imagine” | Estimarea adâncimii dintr-un cadru RGB, fără stereo sau LiDAR |
| Adâncime relativă | „Adâncime ordonată” | Valori z ordonate, fără unități din lumea reală |
| Adâncime metrică | „Distanță absolută” | Adâncime în metri; necesită calibrare sau un model antrenat cu supraveghere metrică |
| AbsRel | „Eroare relativă absolută” | Media lui |
| Acuratețe delta | „delta < 1.25” | Fracția pixelilor cu predicția la cel mult 25% de adevărul de referință |
| Cameră pinhole | „fx, fy, cx, cy” | Modelul de cameră folosit pentru a ridica (u, v, d) în (X, Y, Z) |
| DPT | „Dense Prediction Transformer” | Decoderul convoluțional utilizat peste encodere ViT înghețate pentru adâncime |
| Backbone DINOv2 | „Motivul pentru care funcționează” | Caracteristici auto-supervizate care se generalizează între domenii fără etichete de adâncime |
Lecturi suplimentare
- Pagina lucrării Depth Anything V3 — adâncime monoculară SOTA cu encoder DINOv2
- Marigold (Ke et al., CVPR 2024) — estimarea adâncimii bazată pe difuzie
- UniDepth (Piccinelli et al., 2024) — adâncime metrică cu intrinsece
- MiDaS v3.1 (Intel ISL) — baza de referință canonică pentru adâncime relativă
- Articolul de blog DINOv3 (Meta) — familia de encodere care crește acuratețea adâncimii
Sursă: Originalul în limba engleză
Navigare: ← Lecția 04.25 — Modele viziune–limbaj — tiparul ViT-MLP-LLM · Faza 4 — Viziune computerizată · Lecția 04.27 — Urmărirea mai multor obiecte și memoria video → · Catalog complet