VGGT 三维重建
更新时间:2026-09-14
简介
VGGT 三维重建算子:对输入视频抽帧后一次性送入 VGGT-1B 前向,输出相机内外参、深度图与点云图。VGGT 权重与 vggt 源码必须离线预置,算子内不下载权重也不安装依赖。
功能描述
- 抽帧走
VideoFrameSampler在内存里完成、不落盘:5 种抽帧模式与时间窗口参数原样透传,默认by_count_uniform+count_k=3,另加max_frames=32兜底,VGGT 显存随帧数增长 - 预处理等价于 vggt
load_and_preprocess_images的 "crop" 模式:BGR 转 RGB,宽固定缩放到 518,高按比例缩到 14 的倍数(下限 14),高超过 518 时中心裁剪,再归一化到 [0,1];同一视频内各帧尺寸一致,直接 stack 成(S,3,H,W) - 相机内外参由
pose_encoding_to_extri_intri从模型输出的pose_enc解出;point_maps_from_unprojection由unproject_depth_map_to_point_map用深度 + 内外参反投影得到,只有同时拿到pose_enc与depth时才会填 - 每个张量统一存成
{shape, data}(形状 + 一维 float32 展平数据),而不是多层嵌套 list,arrow 侧内存可控、还原方式明确 - 四个
if_output_*开关只控制字段是否填值,关掉即为空张量{"shape": [], "data": []},不改变输出 schema point_tracks本期不实现:点跟踪要求样本自带query_points,AIHC 没有上游算子产出该字段- 精度自适应:GPU 上
bfloat16需要 compute capability >= 8,不满足自动回落float16;无 GPU 时强制float32并打 warning(CPU 上极慢)。非float32时前向包在torch.autocast("cuda", dtype=...)里 - 抽不到帧或单个视频前向抛异常时,该行所有张量为空、
status记录原因(error: no frames/error: <异常信息>),不中断整列;每个视频处理完调torch.cuda.empty_cache() - 输入支持
video_url(含 BOS 路径)、video_base64、video_binary三种形态,由video_src_type指定;后两者按video_format解析容器格式,整列抽帧失败时整列返回空帧
算子参数
输入
| 输入 | 含义 |
|---|---|
| videos | 视频列。按 video_src_type 取值分别是视频路径/URL(含 bos://)、base64 字符串或二进制内容 |
输出
输出为一个 struct 列,字段如下(tensor 均指 struct<shape: list<int32>, data: list<float32>>,data 是按行优先展平的 float32):
| 输出 | 含义 |
|---|---|
| frame_count | int32,实际进入前向的帧数(即预处理后张量的第 0 维) |
| image_size | list |
| camera_parameters.extrinsic | tensor,相机外参,形状 (1,S,3,4);if_output_camera_parameters=False 时为空 |
| camera_parameters.intrinsic | tensor,相机内参,形状 (1,S,3,3);同上开关控制 |
| depth_maps.depth_map | tensor,深度图,形状 (1,S,H,W,1);if_output_depth_maps=False 时为空 |
| depth_maps.depth_conf | tensor,深度置信度;模型未输出 depth_conf 时为空 |
| point_maps_from_projection.point_map | tensor,点云头直接预测的点云图,形状 (1,S,H,W,3);if_output_point_maps_from_projection=False 时为空 |
| point_maps_from_projection.point_conf | tensor,上述点云的置信度;模型未输出时为空 |
| point_maps_from_unprojection.point_map | tensor,由深度 + 内外参反投影得到的点云图,形状 (S,H,W,3);默认关闭 |
| status | string,success / error: no frames / error: <异常信息> |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| video_src_type | str | "video_url" | 输入视频编码形式:video_url / video_base64 / video_binary,其他取值抛 ValueError |
| model_path | str | "/opt/aihc/model" | 权重根目录 |
| model_name | str | "facebook/VGGT-1B" | 相对 model_path 的 VGGT 权重子目录;model_path/model_name 不存在时抛 FileNotFoundError |
| vggt_source_path | str 或 None | None | vggt 源码目录,给出时 append 到 sys.path(镜像内预置源码的场景);为 None 时要求 vggt 已 pip 安装 |
| dtype | str | "bfloat16" | 前向精度:bfloat16 / float16 / float32,其他取值抛 ValueError |
| sample_mode | str | "by_count_uniform" | 抽帧模式,透传 VideoFrameSampler:by_count_uniform / by_interval_time / by_interval_frames / by_fps / by_timestamps |
| start_time_sec | float | 0.0 | 抽帧起始秒 |
| end_time_sec | float 或 None | None | 抽帧结束秒,None 表示到视频末尾 |
| count_k | int 或 None | 3 | by_count_uniform 模式抽帧数 |
| interval_sec | float 或 None | None | by_interval_time 模式间隔秒 |
| interval_frames | int 或 None | None | by_interval_frames 模式间隔帧 |
| target_fps | float 或 None | None | by_fps 模式目标帧率 |
| timestamps_sec | list[float] 或 None | None | by_timestamps 模式时间戳列表 |
| max_frames | int 或 None | 32 | 抽帧上限,VGGT 显存随帧数增长,默认 32 帧兜底 |
| if_output_camera_parameters | bool | True | 是否输出相机内外参 |
| if_output_depth_maps | bool | True | 是否输出深度图与置信度 |
| if_output_point_maps_from_projection | bool | True | 是否输出点云头直接预测的点云图 |
| if_output_point_maps_from_unprojection | bool | False | 是否输出由深度反投影得到的点云图,默认关(体积大且可由深度推出) |
| video_format | str | "mp4" | 二进制 / base64 输入的容器格式 |
| rank | int | 0 | 多卡场景 worker 序号,设备取 cuda:rank % cuda_device_count |
注意事项
- 权重缺失即失败:算子在
__init__里检查权重是否存在,缺失时直接FileNotFoundError,运行期不会联网下载。 - vggt 源码不做运行时获取:算子不会下载或安装 vggt,已有源码目录可用
vggt_source_path指过去;vggt不可 import 时from vggt.models.vggt import VGGT会直接 ImportError。 - 按单卡独占起:显存与输出体积都随帧数、分辨率增长(深度
(1,S,H,W,1)、点云(1,S,H,W,3),518 宽下单帧就是 20 万像素量级)。测试与建议用法都是num_gpus=1, concurrency=1, batch_size=1,靠max_frames控上限;point_maps_from_unprojection除非下游确实要用,保持默认关闭。 - 该算子只用 PyTorch 前向,不需要自编 CUDA 扩展;Blackwell(sm_120)上已实测跑通,bf16 生效(cc=12 满足
>=8)。 count_k是上限而非保证值:短视频可能只抽到更少的帧,frame_count以实际入参为准(实测 3 帧配置在短视频上抽到 2 帧)。- CPU 上可以跑但极慢,算子会强制
float32并打 warning,生产不要这么用。
调用示例
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.embodied.perception.vggt_reconstruct import VggtReconstruct
10
11if __name__ == "__main__":
12 if os.getenv("DAFT_RUNNER", "native") == "ray":
13 import ray
14 ray.init(dashboard_host="0.0.0.0", ignore_reinit_error=True)
15 daft.set_runner_ray()
16 daft.set_execution_config(actor_udf_ready_timeout=6000, min_cpu_per_task=0)
17
18ds = daft.from_pydict({"video": ["bos://your-bucket/sample.mp4"]})
19 ds = ds.with_column(
20 "vggt",
21 aihc_udf(
22 VggtReconstruct,
23 construct_args={
24 "video_src_type": "video_url",
25 "model_path": "/path/to/models",
26 "model_name": "facebook/VGGT-1B",
27 "count_k": 3,
28 "if_output_point_maps_from_unprojection": True,
29 },
30 num_cpus=1,
31 num_gpus=1,
32 concurrency=1,
33 batch_size=1,
34 )(col("video")),
35 )
36 ds = ds.with_column("frame_count", col("vggt")["frame_count"])
37 ds = ds.with_column("status", col("vggt")["status"])
38 ds.show()
评价此篇文章
