视频深度估计
更新时间:2026-09-14
简介
视频逐帧深度估计算子:抽帧后逐帧过 Depth-Anything V2 得到相对深度图,输出逐帧深度统计量,可选把原始深度图落盘成 .npz。模型用 transformers 内置的 Depth-Anything V2 做逐帧推理,权重全部本地加载,算子内不做网络请求与安装。
功能描述
- 抽帧走 OpenCV(
cv2.VideoCapture按帧号 seek),两种口径:sample_fps > 0且源 fps 可读时按round(src_fps / sample_fps)的步长等间隔抽(产出时间轴上的深度曲线);否则按frame_num均匀抽(frame_num=1取中间帧,否则在[0, 总帧数-1]上linspace) - 源 fps 读不到时即便设了
sample_fps也会回落到frame_num口径 - 长边超过
max_res的帧先按INTER_AREA等比缩小(max_res默认 1280) - 抽出的帧 BGR 转 RGB 后逐帧推理,
predicted_depth用 bicubic 插值回该帧原尺寸 - 输出是 struct:逐帧的
depth_min/depth_max/depth_mean与frame_indices等长、逐帧对应;默认只出统计量,因为整段逐帧 float32 深度图在列式场景下会是 GB 级的列,需要原始深度图请开save_depth落盘 save_depth=True时把逐帧深度堆成一个数组存进{output_dir}/{视频文件名}_depth.npz(含depth、frame_indices两个数组),列里返回该路径;save_depth=False时depth_npz为空串- 远端路径(BOS / HTTP)经
run_on_local_path先下载到临时目录再处理,函数返回后临时文件即清理 - 输入为 None、解不出任何帧、或该行处理异常时返回全空 struct(
num_frames=0、fps=-1.0、三个列表为空、depth_npz=""),异常只记日志不打断整列 - CPU 上
dtype="float16"自动回退float32 - 权重只从
model_path/model_name本地目录加载,初始化时校验目录存在,不联网下载
算子参数
输入
| 输入 | 含义 |
|---|---|
| video | 视频列,支持本地路径、BOS、HTTP;远端路径先落地到临时文件再解码 |
输出
| 输出 | 含义 |
|---|---|
| depth | struct,字段见下 |
| depth.num_frames | int32,实际完成推理的帧数 |
| depth.fps | float64,sample_fps > 0 时为 sample_fps,否则为源视频 fps;失败为 -1.0 |
| depth.frame_indices | list |
| depth.depth_min | list |
| depth.depth_max | list |
| depth.depth_mean | list |
| depth.depth_npz | large_string,逐帧深度图的 npz 路径,仅 save_depth=True 时非空 |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| model_path | str | "/opt/aihc/model" | 权重根目录 |
| model_name | str | "depth-anything/Depth-Anything-V2-Small-hf" | 相对 model_path 的 Depth-Anything V2 权重子目录 |
| dtype | str | "float16" | 推理精度:float16 / float32 / bfloat16;CPU 上 float16 自动回退 float32 |
| frame_num | int | 8 | 均匀采样帧数,必须 >=1;sample_fps > 0 时本参数被忽略 |
| sample_fps | float | 0.0 | 按固定时间间隔采样的频率(帧/秒),>0 时优先于 frame_num |
| max_res | int | 1280 | 长边超过该阈值的帧先等比缩小,必须 >=64 |
| save_depth | bool | False | 是否把逐帧深度图存成 npz 并在列里返回路径 |
| output_dir | str | "/tmp/aihc_video_depth" | npz 输出目录,仅 save_depth=True 时使用 |
| rank | int | 0 | 多卡场景 worker 序号,设备取 cuda:(rank % 可见卡数) |
注意事项
- 本算子是逐帧独立推理,没有 Video-Depth-Anything 的时序模块,长视频上帧间深度可能有轻微闪烁;需要严格时序一致的场景请走离线 VDA 流程。
- 输出是相对深度,没有物理尺度,不同帧、不同视频之间的数值不保证同一尺度,不要直接当米制距离比较。本算子也不提供 metric 深度模式(点云 ply + open3d),那需要 metric 权重。
- npz 文件名只取视频文件名的 stem:同一
output_dir下不同目录的同名视频会互相覆盖,批量落盘时要按数据源分开output_dir。
调用示例
Python
1from __future__ import annotations
2
3import os
4
5import daft
6from daft import col
7
8from daft.aihc.common.udf import aihc_udf
9from daft.aihc.functions.video.video_depth_estimation import VideoDepthEstimation
10
11os.environ.setdefault("BOS_ENDPOINT", "http://bj.bcebos.com")
12os.environ.setdefault("BOS_REGION", "bj")
13
14if __name__ == "__main__":
15 if os.getenv("DAFT_RUNNER", "native") == "ray":
16 import ray
17 ray.init(dashboard_host="0.0.0.0", ignore_reinit_error=True)
18 daft.set_runner_ray()
19 daft.set_execution_config(actor_udf_ready_timeout=6000, min_cpu_per_task=0)
20
21ds = daft.from_pydict({"video": ["bos://your-bucket/sample.mp4"]})
22 ds = ds.with_column(
23 "depth",
24 aihc_udf(
25 VideoDepthEstimation,
26 construct_args={
27 "model_path": "/path/to/models",
28 "model_name": "depth-anything/Depth-Anything-V2-Small-hf",
29 "frame_num": 4,
30 "max_res": 640,
31 "save_depth": True,
32 "output_dir": "/tmp/aihc_video_depth",
33 },
34 num_cpus=1,
35 num_gpus=1,
36 concurrency=1,
37 batch_size=1,
38 )(col("video")),
39 )
40 ds = ds.with_column("depth_mean", col("depth")["depth_mean"])
41 ds = ds.with_column("depth_npz", col("depth")["depth_npz"])
42 ds.show()
评价此篇文章
