☰
单目深度估计新标杆:Depth-Anything-V2原理、部署与工程落地
2026/10/14 3:43:46 网站建设 项目流程

简介:Depth-Anything-V2 是面向单目深度估计的开源项目资源,适合计算机视觉算法研究与工程落地,可仅凭单张 RGB 图像输出逐像素深度,用于机器人导航、三维重建、增强现实等场景。压缩包共 99 个文件,以 Python 源码(38 个 py)为主,同时包含示例图片、sample 样本、md/txt 说明文档、mp4 演示视频、训练配置与许可证文件,总大小约 89.99MB,目录结构完整,便于按模块定位查阅。核心模块包括 dpt.py、dinov2 层、深度转点云工具、视频深度估计示例、训练与推理入口,配合 README 与 DA-2K.md 可快速理解整体流程。已有 238 人浏览学习,对需要复现 Depth-Anything-V2 结果、做消融实验或将模型集成到三维视觉项目的开发者,这份资源能直接提供可运行的代码、示例数据和离线文档,减少环境搭建与数据处理时间。

1. 深度估计的新标尺:Depth-Anything-V2 凭什么把「单张图出深度」变成可靠工程

做过 3D 重建的工程师,多半被单目深度估计坑过:输入一张 RGB 图,模型输出一张灰度图,看着像模像样,拿去生成点云却糊成一团;换个场景,深度值分布完全变了。Depth-Anything-V2 是当前少有的、能在精度和速度两条线同时打动人心的方案:它用 DINOv2 的自监督特征做教师信号,用细粒度匹配损失训练解码器,边缘细节比第一代锐利得多,而推理耗时只有上一代的十分之一左右。如果你正在做 AR 遮挡、虚拟背景替换、室内三维重建或机器人视觉避障,这个模型是目前单目深度估计最值得先跑通的方向。下面按「模型为什么这样改 → 最小推理怎么跑 → 常见故障怎么排 → 深度图怎么用 → 进阶怎么调」的顺序讲,每一步都落在具体命令和参数上。

2. 从 V1 到 V2:Depth-Anything 到底改了什么,为什么效果差这么多

2.1 单目深度估计的核心问题:没有视差,深度从哪来

传统立体视觉需要两个相机在不同位置拍摄同一场景,通过视差三角化得到深度;结构光方案需要投射已知图案,在室外强光下基本失效。单目深度估计只有一张图,几何上不存在唯一解,它本质上是在靠先验「猜」——模型在大规模数据上学到了「远处的物体更小」「地面向下延伸」「桌子是水平的板」这类统计规律,再用这些规律反推每个像素的深度。

正因为没有真实的物理尺度约束,单目模型输出的通常是相对深度:它反映的是「A 比 B 远多少」的比例关系,而不是「A 离相机 3.2 米」的绝对值。这对很多下游任务已经够用——AR 遮挡只需要前后关系,背景虚化只需要远近分布;但若要转成真实尺寸的点云,就需要额外标定一个尺度因子。

这也是 Depth-Anything 系列在设计时的关键取舍:模型回归的目标是相对深度,训练时用 scale-shift 不变性损失,允许预测在缩放和平移上自由变化,只惩罚相对关系错误。这种设计让模型对相机内参、图像风格、场景类型都不敏感,泛化能力比直接回归绝对深度的方案强很多。理解这一点,才能解释后面会出现的大部分异常现象:深度分布不是「错」,而是「没有绑定真实尺度」。

单目深度估计的难点不止尺度。同一张 2D 图可以对应无数种 3D 解释,比如一个巴掌大的玩具车和一辆真车,只要距离和大小成比例,在图像上可能完全一样。模型要打破这种歧义,唯一能依赖的是语义——认得出那是车、那是路,然后按「车比路小很多」的先验来分配深度。所以单目深度模型的效果上限,很大程度上取决于编码器对场景语义的捕捉能力,这也是 V2 换用更强编码器的根本原因。

2.2 骨干网络的更换:用 DINOv2 做教师,学生解码器学深度

V1 的编码器是自研的 ViT,用大规模分类或自监督任务做预训练,特征表达已经不错,但离「深度友好」还有距离。V2 最核心的改动,是把编码器换成了 DINOv2 这个在更大规模自然图像上自监督训练的特征提取器。具体做法是教师-学生蒸馏:DINOv2 作为教师,对同一张图提取特征;学生网络在预测深度的同时,让中间层特征与教师特征对齐。

这样做的收益可以从两个层面理解。第一层是特征质量:DINOv2 在数十亿规模的自然图上做自监督学习,特征对物体边界、遮挡、材质转折、光照变化非常敏感,而这些恰好是深度断裂最需要的信息。第二层是训练稳定性:教师特征固定不动,学生只需要在特征空间里对齐,比从图像直接回归深度收敛更快;V2 还删掉了 V1 里的辅助语义分割分支,让解码器专心学深度,不会出现辅助任务抢梯度的问题。

我一般这样向团队解释这个改动:V1 是普通学生自己刷题,V2 是请了学霸在旁边给提示,学生不需要从零总结规律,只需要把提示翻译成深度。这也是 V2 整体参数反而更小、精度却更高的原因。需要留意的是,教师模型只在训练阶段参与,推理时 V2 只加载学生网络,所以部署时不需要 DINOv2 单独跑一遍,显存占用只取决于学生模型大小。

在工程上,换骨干带来的兼容性成本也很低:模型的输入仍然是标准 RGB 图像,接口和 V1 几乎一致。真正受影响的只是权重文件和配置文件里的 encoder 名字。如果你的项目此前用的是 V1 的 pipeline,升级到 V2 时,模型加载代码需要适配新的配置字典,但前后的预处理、后处理、可视化逻辑基本可以原样保留。

2.3 细粒度匹配损失:边缘细节不再糊的关键

V1 里的特征对齐损失是整图级别的,对齐的是特征图的整体分布。大的物体区域对得很好,但细长物体、薄片结构经常糊成一片。V2 引入细粒度匹配损失,做法是按 patch 做局部匹配:把图像切成若干小 patch,对每个 patch 分别约束学生特征与教师特征对应,而不是整张图算一个平均对齐。这相当于把「大概对齐」升级成了「逐块对齐」。

直观效果是深度图的边缘断裂明显锐利:桌腿和桌面之间从渐变过渡变成清晰边界,树叶从一片均匀的糊变成能看出簇间前后层次。对实际项目影响很大——AR 遮挡和背景替换最怕的就是半透明的深度过渡,前景物体边缘像蒙了一层纱,细粒度匹配损失正好把这个问题压住了。

细粒度匹配损失有一个附带要求:它对输入的分辨率和 patch 对齐敏感。训练时图像会被切到 14 的倍数,推理时输入尺寸最好也保持这个约束,否则边缘 patch 会被截断,深度图边缘出现一条异常亮带。所以项目仓库里的推理接口会自动做 resize 和补齐,手动写推理循环的人最容易忽略这一条。

2.4 效率与规模:从移动端到服务器的三档选择

V2 提供三个规模的模型:vits 适合移动端或嵌入式设备,vitb 是平衡档,vitl 是精度档。三者的编码器深度和通道数不同,解码器输出通道也要对应调整。官方发布的基准里,V2 在室内、室外、自动驾驶三类常见深度基准上都比 V1 有明显提升,而推理耗时接近一个数量级的下降——vits 在手机端接近实时,vitb 在中端 GPU 上可以做实时视频推理。

选型建议是先跑 vitb,确认方案可行后再按算力上下浮动。我在验证阶段都用 vitb,它处理一张 518 分辨率的图只要几十毫秒,足够交互式调参;生产环境如果对精度敏感,再评估 vitl 的显存预算。

这三档模型的权重不通用,下载和加载时必须对应。后面第三章会给出具体的配置字典和加载代码,避免配错导致 key 不匹配。

2.5 和其他单目方案对比:为什么这个方向值得投入

现阶段单目深度估计还有几个常用基线。MiDaS 系列是相对深度的老牌方案,多数据集融合训练,泛化能力不错,但边缘细节和细粒度结构弱一些。ZoeDepth 在相对深度模型之上加了一个 metric 头,可以输出绝对深度,但绝对深度的精度高度依赖训练数据里的场景分布,换到没见过的场景反而容易漂移。Depth-Anything-V2 走的是「泛化优先」路线,用相对深度作为输出,好处是跨场景稳定、不挑相机内参。

选型上我的判断是:如果下游只需要前后关系,或场景类型不固定,V2 的综合收益最高;如果必须拿到真实距离且场景分布可控(比如固定机位的室内监控),ZoeDepth 这类带 metric 头的模型值得试,但要准备足够的标定场景数据。如果只是做一个快速验证的深度效果 Demo,MiDaS 仍然是工程量最小的选择,但它的细粒度不足会在 AR 遮挡场景露馅。

这个对比不是为了踩谁,而是想说明:V2 适合的是「要拿深度做产品」的工程场景,不是「要发表论文比指标」的研究场景。它的价值在于把精度、速度、易用性这几个工程指标平衡到了一个可以直接落地的位置。

3. 本地跑通 Depth-Anything-V2:环境、权重与最小推理脚本

3.1 环境准备与 GPU/CPU 选型

依赖项不复杂:PyTorch 2.x、OpenCV、NumPy 和 einops。Python 版本建议 3.10 以上,CUDA 11.8 或更高。建议先用 conda 独立创建一个环境,避免和公司的旧项目冲突:

conda create -n da python=3.10 -y conda activate da pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install opencv-python numpy einops

cu118表示 CUDA 11.8 版本的预编译包。如果你机器上的驱动已经支持 CUDA 12.x,也可以把cu118换成对应版本,但要注意 PyTorch 和显卡驱动的兼容性。装完后用一段小代码确认 GPU 可用:

import torch print(torch.__version__) print(torch.cuda.is_available()) if torch.cuda.is_available(): print(torch.cuda.get_device_name(0))

如果你的机器没有 NVIDIA 显卡,CPU 也能跑,只是速度差很多:vitl 在 CPU 上处理一张 518 分辨率的图可能要两三秒,vitb 大约半秒,vits 在 200 毫秒以内。做视频实时推理还是需要显卡,显存 6G 以上就够 vitb,vitl 建议 12G 以上。集成显卡跑 vits 也能勉强出结果,但显存共享导致速度波动大,不适合用来调参。

3.2 下载权重与模型加载:三个尺寸怎么选

权重文件需要从项目的 Release 页面下载。下载后用 sha256 校验一下文件完整性,这一步经常被跳过,但权重文件下载中断是实际发生过的坑——模型加载时不报错,推理结果却异常,最后排查才发现权重只下了一半。校验通过后把权重放到工作目录,并定义模型配置:

from depth_anything_v2.dpt import DepthAnythingV2 model_configs = { "vits": {"encoder": "vits", "features": 64, "out_channels": [48, 96, 192, 384]}, "vitb": {"encoder": "vitb", "features": 128, "out_channels": [96, 192, 384, 768]}, "vitl": {"encoder": "vitl", "features": 256, "out_channels": [256, 512, 1024, 1024]}, } model = DepthAnythingV2(**model_configs["vitb"]) model.load_state_dict(torch.load("depth_anything_v2_vitb.pth", map_location="cpu")) model.cuda().eval()

features是解码器输入的特征维度,out_channels是解码器四个阶段输出的通道数。这三档配置之间不能混用:把 vitl 的权重加载进 vitb 的配置,load_state_dict会直接报 key 不匹配;如果报错,先检查是不是文件名和配置对不上。eval()一定要调用,不然模型里的 dropout 和归一化层会保留训练状态,输出结果会有随机性。

导入depth_anything_v2时如果报 ModuleNotFoundError,多半是项目根目录没有加进 Python 路径。最简单的办法是在脚本开头加一行sys.path.append("/path/to/Depth-Anything-V2"),或者用pip install -e .把项目安装成可导入的包。这一条看起来基础,但在多人协作的工程里经常被踩——队友 clone 了代码却没有执行安装步骤。

注意:权重文件的 sha256 校验很重要。下载完先比对哈希,避免加载中断的权重导致深层网络输出异常且难以排查。

3.3 最小推理脚本:从一张图片到深度图

推理的核心接口是模型的infer_image方法,它内部自动处理 resize、归一化、patch 对齐和后处理。直接把 OpenCV 读出的 BGR 图像传进去即可:

import cv2 raw_image = cv2.imread("input.jpg") depth = model.infer_image(raw_image) # 返回 numpy 数组,形状 (H, W) print("深度图尺寸:", depth.shape) print("深度值范围: %.3f ~ %.3f" % (depth.min(), depth.max()))

infer_image默认把图像短边 resize 到 518 像素,并保证宽和高是 14 的倍数。需要更高分辨率时可以传canvas_size参数手动指定:

depth = model.infer_image(raw_image, canvas_size=700)

canvas_size表示短边目标长度。调大这个值会保留更多细节,但显存占用和耗时接近线性增长。做精度验证时我会从 518 往上试,找到一个边缘清晰且显存不崩的临界值;做批量处理反而会降到 350~400 来提速。这里有个容易被忽视的细节:infer_image返回的深度图尺寸与输入图像保持一致,因为内部做了缩放,不需要你手动 resize 回去。

3.4 深度图可视化与 16bit 保存

模型输出是 float32 的单通道数组,范围不固定。直接用cv2.imshow会得到一张几乎全黑的图,必须归一化后再映射:

import numpy as np import cv2 depth_norm = (depth - depth.min()) / (depth.max() - depth.min()) depth_uint8 = (depth_norm * 255.0).astype(np.uint8) colored = cv2.applyColorMap(depth_uint8, cv2.COLORMAP_INFERNO) cv2.imwrite("depth_colored.jpg", colored)

min-max 归一化是必须的。如果不做,直接用原始深度值转 uint8,大值区域会截断成纯白,小值区域挤在黑色里,整张图的层次全部丢失。COLORMAP_INFERNO是深度可视化常用的伪彩色,暗色近、亮色远,比灰度图更直观。

如果是给后续算法用而不是给人看,建议保存 16bit PNG,保留深度值的精度:

depth_16bit = (depth - depth.min()) / (depth.max() - depth.min()) * 65535.0 depth_16bit = depth_16bit.astype(np.uint16) cv2.imwrite("depth_raw_16bit.png", depth_16bit)

16bit PNG 的好处是深度范围被线性拉伸到 0~65535,后续读取时知道这个映射关系就能还原相对比例。要注意的是,这里保存的是相对深度,不是真实距离;如果下游需要真实距离,要在保存前先乘尺度因子。

4. Depth-Anything-V2 的五个常见故障与排查思路:现象、原因、解法

下面这五个问题在深度估计落地时最容易撞上,按现象、原因、解决三个步骤整理。大多数情况下不用改模型,修一下前后处理就能解决。

4.1 深度图整体发灰,看不出远近层次

现象:输出的深度图经过 colormap 后整张灰蒙蒙一片,只有极少数的亮斑,层次感几乎为零。

原因:这是最常见的可视化问题。模型的输出是相对深度,数值分布可能非常集中(比如所有值都在 0.4 到 0.6 之间),直接用固定的 0~1 映射到 0~255,中间值全落在灰色区域,对比度自然上不去。

解决:先看原始深度值的 min 和 max,确认分布范围;再做百分位裁剪,把 2% 和 98% 分位之外的值截断,然后再做 min-max 归一化:

lo, hi = np.percentile(depth, 2), np.percentile(depth, 98) depth_clipped = np.clip(depth, lo, hi) depth_norm = (depth_clipped - lo) / (hi - lo)

如果裁剪后发现某一侧细节丢失,说明场景里有极远或极近的异常点,可以把 2% 和 98% 改到 1% 和 99%,给异常值留更多余量。如果深度直方图显示多峰分布(比如近处桌子、远处墙壁各占一簇),可以考虑用聚类做分段拉伸,效果比全局归一化更细腻。

4.2 细长物体边缘出现毛刺或孔洞

现象:电线杆、桌腿、植物枝条这些细长结构,在深度图上边缘不连续,出现锯齿状的毛刺或者内部小孔洞。

原因:细粒度匹配损失提升了边缘锐度,但代价是对输入分辨率敏感。当图像的短边被缩到 518 时,一个只占 4~5 像素的细物体在 patch 切分时可能落在两个 patch 的边界上,模型难以给它一致的深度。此外,编码器的 patch size 固定,细物体本身可用的 token 太少。

解决:提高canvas_size,让细物体在图像中占据更多像素;如果模型是 vitb,可以换 vitl 试一下,更大的模型对细结构的容忍度更高。还有一种工程技巧:对深度图做一次 3x3 的中值滤波,把孤立的毛刺噪声去掉,代价是边缘轻微变钝。

depth_filtered = cv2.medianBlur(depth.astype(np.float32), 3)

中值滤波对椒盐式的毛刺很有效,但如果你的场景里有很多真实细结构,滤波窗口不要超过 5,否则桌腿和电线的深度会被周边背景带偏。

4.3 场景切换时深度尺度发生跳变

现象:同一个模型,在室内预测的深度范围是 0~1,切到室外后变成了 0~2.5;或者同一张图换一个亮度稍有不同的版本,深度整体偏移明显。

原因:这是相对深度的特性,不是 bug。模型学到的是场景内的比例关系,不承诺跨场景的绝对尺度。室内场景远近跨度小,室外场景跨度大,模型输出的归一化深度自然不同。

解决:如果下游需要稳定尺度,需要做「尺度锚定」。常见做法是:在场景中选择一个已知距离的参考点(比如相机到地板的距离),用模型在该点的深度值和真实距离算一个缩放因子,把它作用到整张深度图上。对视频序列,用第一帧的参考点做一次标定,后续帧沿用同一因子,就可以明显减弱尺度跳变。

这一步的工程细节是:参考点不要选在运动物体上,也不要在画面边缘(边缘深度误差通常更大)。选画面中心附近、结构明确的静态点,标定结果更稳。

4.4 显存不足或推理速度赶不上实时

现象:vitl 模型在 8G 显存上直接 OOM,或者 vitb 在 518 分辨率下帧率只有十几帧,达不到视频实时的要求。

原因:模型尺寸和输入分辨率是吃掉显存的大头。vitl 的参数量是 vitb 的几倍,前向计算时的中间特征也更多;分辨率越高,patch 数量越多,Transformer 的自注意力计算量呈平方增长。

解决:优先把canvas_size降到 400 左右,这一步通常能省下超过一半的显存;还不行就换 vits。另外,PyTorch 可以用半精度推理:

with torch.autocast(device_type="cuda", dtype=torch.float16): depth = model.infer_image(raw_image, canvas_size=518)

半精度在 vitb 上能显著提速,但对个别场景可能出现数值溢出,务必在可视化时确认深度范围是否正常。如果跑视频流,还可以考虑把推理放到单独的线程里,用队列缓存帧,避免图像读取和模型计算互相阻塞。

4.5 深度图方向反了:近处反而暗,远处反而亮

现象:输出的深度图经过 colormap 后,明显的近处物体是暗色,远处背景是亮色,和可视化时的方向预期相反。

原因:严格来说这不一定是错误。Depth-Anything 系列的输出惯例通常是「深度值越大,距离越远」,所以 colormap 中远处更亮。但很多从传统深度相机(如 Kinect、激光雷达)切过来的工程师习惯的是「深度值越大,距离越近」的惯例,于是产生了反转的错觉。

解决:先确认你要对接的下游模块用的是哪个约定。如果下游按激光雷达的习惯处理,直接把深度取反即可:

depth_inv = depth.max() - depth # 近处值大、远处值小

不过反转之后,模型的相对比例关系仍然成立,只是符号变了。最稳妥的做法是在代码里写一个标志位表示深度方向,避免后期接到不同下游时来回改。

5. 把深度图用起来:从单张图到 3D 点云与下游应用

5.1 相机内参换算:深度值到 3D 坐标的数学

深度图要变成 3D 坐标,必须知道相机的内参。对针孔相机模型,像素 (u, v) 对应的三维坐标是:

X = (u - cx) * Z / fx Y = (v - cy) * Z / fy Z = depth_value

其中 fx、fy 是焦距(像素单位),cx、cy 是主点坐标。这些参数可以从相机标定获得。手机照片通常没有内参,可以用 EXIF 里的焦距信息和传感器尺寸估算,但精度有限;严谨的做法是拍一张标定板做一次标定。

如果模型输出的是相对深度,还需要一个尺度因子 s 将深度值还原为真实距离:真实距离 = 相对深度 × s。s 的获取方式在 4.3 里讲过——用场景中已知距离的参考点反推。这里补充一个细节:如果只是做可视化预览,不需要真实尺度,可以直接用归一化深度生成点云,但长宽比会被拉伸,看起来像浮雕而不是真实场景。

5.2 用 Open3D 生成可交互查看的点云

下面这段代码把深度图和相机内参转成 ply 点云文件,用 Open3D 可以直接打开查看:

import numpy as np import cv2 import open3d as o3d fx, fy = 1000.0, 1000.0 # 从相机标定获得 cx, cy = depth.shape[1] / 2, depth.shape[0] / 2 h, w = depth.shape u, v = np.meshgrid(np.arange(w), np.arange(h)) Z = depth.astype(np.float32) X = (u - cx) * Z / fx Y = (v - cy) * Z / fy points = np.stack([X, -Y, Z], axis=-1).reshape(-1, 3) colors = cv2.cvtColor(raw_image, cv2.COLOR_BGR2RGB).reshape(-1, 3).astype(np.float32) / 255.0 pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(points) pcd.colors = o3d.utility.Vector3dVector(colors) pcd = pcd.uniform_down_sample(every_k_points=50) o3d.io.write_point_cloud("output.ply", pcd)

Y 轴取负是因为图像坐标系和三维坐标系的方向约定不同——图像 v 轴向下,三维 Y 通常向上。uniform_down_sample(every_k_points=50)的作用是每隔 50 个点采样一个,把密集点云减到可交互的规模;如果点云过稀,把 50 改成 20 即可。

生成的点云如果看起来像被压扁的纸片,说明尺度因子 s 没设对;如果点云有倒影或空洞,多半是深度图在镜面、高光或透明区域不可靠,需要用 5.4 的后处理先修一遍。

5.3 下游场景对接:AR 遮挡、背景虚化、机器人避障

点云和深度图对接下游有很多成熟路径。AR 场景里,深度图可以直接用于遮挡渲染——虚拟物体应该被真实前景遮住时,比较虚拟物体的深度和真实场景深度即可决定是否渲染该像素。背景虚化则更简单:用深度图生成模糊权重图,远处用高斯模糊,近处保持清晰,就能得到一个类似人像模式的效果。

机器人避障是相对深度的直接受益者:不需要绝对尺度也能判断「前方有障碍物、距离在减小」。实际使用时把深度图缩放到一个固定分辨率(比如 640x480),用阈值分割出近距离障碍物的连通域,再计算障碍物的面积和位置,就可以驱动避障逻辑。

这些下游开发的共同点是:第一步永远是把模型输出和可视化做对,先确保你在屏幕上看到的深度和真实世界一致,再谈算法对接。不要跳过 3.4 的可视化步骤直接接下游,否则出问题时很难判断是模型的问题还是下游算法的问题。

5.4 深度图后处理:空洞填充与平滑

镜面、高光、透明物体和黑色吸光表面,会让深度图出现局部空洞或异常跳变。这些区域的模型输出不可靠,最常见的表现是:亮度极高的窗户被预测成很远的深度,或者黑色皮椅的深度像被「吸」进椅背。

对于小空洞,可以用图像修复的思路处理:

mask = (depth <= 0) | (depth > np.percentile(depth, 99)) depth_uint8 = ((depth - depth.min()) / (depth.max() - depth.min()) * 255).astype(np.uint8) filled = cv2.inpaint(depth_uint8, mask.astype(np.uint8), 3, cv2.INPAINT_TELEA)

mask把深度值为 0 或超过 99 分位的像素标记为无效,cv2.inpaint用周围的有效像素填充空洞,3是修复半径。修复后建议再做一次小半径的双边滤波,既能保留边缘,又能去掉填充带来的块状感。

6. 进阶技巧:视频深度一致性与 3D 重建的尺度恢复

视频场景和单张图像不同,逐帧推理会让深度在时间维度上抖动:同一面墙,这一帧预测是 0.55,下一帧变成 0.61,三维重建时墙面就变成了波浪面。一个实用的技巧是加时间滤波——用相邻帧的光流把当前帧的深度图对齐到上一帧的坐标系,再做指数移动平均:

depth_smooth = alpha * depth_warped + (1 - alpha) * depth_current

alpha取 0.3~0.5 比较合适,太小没有平滑效果,太大则会引入残影。如果没有光流条件,退而求其次的做法是只对深度图做时间上的中值滤波——每 N 帧取一次中值,代价是输出延迟 N/2 帧。

另一个进阶点是尺度恢复。做 3D 重建时,相对深度没法直接作为测量数据,需要把整张深度图乘一个 s 并加一个偏移 b。如果你能拿到少量已知深度点(比如标定板上几个点在相机坐标系下的真实距离),可以用最小二乘一次性拟合 s 和 b,让模型输出对齐到真实距离。这个操作在项目里一般写成一个几十行的脚本,跑一次就能把后续帧都换算成真实距离。

我在实际项目里养成的习惯是:先把深度方向和尺度约定写进配置常量,再写可视化,最后才接下游模块。顺序反了的话,每个下游都会来问你「为什么你的深度是反的」,一次一次解释很浪费时间。先定约定、再可视化、再接下游,这套顺序能省掉大部分返工。希望这个习惯也能帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询