- 人工智能
- 深度学习
- 计算机视觉
- 图形学
【免费下载链接】pytorch3d
PyTorch3D is FAIR's library of reusable components for deep learning with 3D data
导读
render_flyaround是 PyTorch3D Implicitron 中负责"场景环绕渲染"的核心可视化函数:它读取一个训练/测试序列的全部帧数据,围绕场景生成一条相机飞行轨迹,逐帧调用训练好的模型进行渲染,最终合成一个 mp4 视频,输出该场景从多视角观测的重建结果(RGB 图、掩码、深度图)。本文以 render_flyaround.rst 为主线,完整讲解该函数的全部 22 个参数、四种相机轨迹类型、从数据加载到视频导出的完整工作流,并结合源码、CLI 脚本与测试用例,给出可直接运行的实战方案。
一、函数定位与文档来源
docs/modules/implicitron/models/visualization/render_flyaround.rst本身是一个 Sphinx 文档占位文件,通过automodule指令自动抽取源码中的 docstring 生成 API 文档:
.. automodule:: pytorch3d.implicitron.models.visualization.render_flyaround :members: :undoc-members: :show-inheritance:因此该文档的"正体"是 render_flyaround.py 中的render_flyaround函数(定义于第 49 行)及其完整的参数文档。该函数处于 Implicitron 可视化工具链的顶层,向下依次依赖:
- eval_video_trajectory.py 中的
generate_eval_video_cameras:负责生成相机轨迹; - video_writer.py 中的
VideoWriter:负责把渲染帧编码为视频; - vis_utils.py 中的
get_visdom_connection、make_depth_image:负责 visdom 可视化与深度图伪彩色化。
从源码结构看,render_flyaround是 Implicitron 模型评估与结果展示的重要出口:训练好的 NeRF、NeRFormer、SRN 等通用模型(GenericModel 体系)都可以直接接入该函数完成环绕视频导出。
二、函数签名与全部参数详解
def render_flyaround( dataset: DatasetBase, sequence_name: str, model: torch.nn.Module, output_video_path: str, n_flyaround_poses: int = 40, fps: int = 20, trajectory_type: str = "circular_lsq_fit", max_angle: float = 2 * math.pi, trajectory_scale: float = 1.1, scene_center: Tuple[float, float, float] = (0.0, 0.0, 0.0), up: Tuple[float, float, float] = (0.0, -1.0, 0.0), traj_offset: float = 0.0, n_source_views: int = 9, visdom_show_preds: bool = False, visdom_environment: str = "render_flyaround", visdom_server: str = "http://127.0.0.1", visdom_port: int = 8097, num_workers: int = 10, device: Union[str, torch.device] = "cuda", seed: Optional[int] = None, video_resize: Optional[Tuple[int, int]] = None, output_video_frames_dir: Optional[str] = None, visualize_preds_keys: Sequence[str] = ( "images_render", "masks_render", "depths_render", "_all_source_images", ), ) -> None:各参数按职责可分为四组:
1. 输入与输出核心参数
| 参数 | 默认值 | 说明 |
|---|---|---|
dataset | 必填 | 包含sequence_name场景全部帧的DatasetBase数据集对象(Implicitron 的 dataset_base.py 体系) |
sequence_name | 必填 | 要可视化的场景在dataset中的名称 |
model | 必填 | 用于预测的模型(torch.nn.Module),其输出字典需包含visualize_preds_keys指定的键 |
output_video_path | 必填 | 输出视频的文件路径(实际产出为{output_video_path}_{sequence_name}_{key}.mp4多个文件) |
2. 相机轨迹参数
| 参数 | 默认值 | 说明 |
|---|---|---|
n_flyaround_poses | 40 | 环绕轨迹上的相机位姿数量,即视频总帧数 |
fps | 20 | 输出视频帧率 |
trajectory_type | "circular_lsq_fit" | 轨迹类型,支持四种,详见下文"四种相机轨迹"小节 |
max_angle | 2π | 轨迹总长度。所有轨迹都以time == 2π为周期,例如circular_lsq_fit配合time=4π会让相机绕物体旋转 720° |
trajectory_scale | 1.1 | 轨迹的尺度(半径/幅度缩放因子) |
scene_center | (0.0, 0.0, 0.0) | 场景中心的世界坐标,轨迹上所有相机都看向该点 |
up | (0.0, -1.0, 0.0) | 场景的"上"向量(即场景地面的法线),对circular_lsq_fit轨迹生效 |
traj_offset | 0.0 | 加到轨迹每个点上的 3D 偏移向量(注:源码中作为traj_offset_canonical=(0.0, 0.0, traj_offset)传入,即作用于轨迹局部坐标系的 z 轴) |
3. 模型输入与批处理参数
| 参数 | 默认值 | 说明 |
|---|---|---|
n_source_views | 9 | 从训练序列已知视角中采样、加入每个评估批次的源视角数量。这类源视角是 NeRFormer、NeRF-WCE 等模型的必需输入(见 visualize_reconstruction.py 第 59-60 行注释) |
num_workers | 10 | 加载训练数据的 DataLoader worker 数量 |
device | "cuda" | 模型推理设备 |
seed | None | 源视角可复现采样的随机种子;为None时使用hash(sequence_name)(源码第 138-139 行) |
4. 可视化与输出格式参数
| 参数 | 默认值 | 说明 |
|---|---|---|
visdom_show_preds | False | 为True时将预测结果同步导出到 visdom |
visdom_environment | "render_flyaround" | visdom 环境名 |
visdom_server | "http://127.0.0.1" | visdom 服务器地址 |
visdom_port | 8097 | visdom 端口 |
video_resize | None | 可选,定义输出视频尺寸(H, W) |
output_video_frames_dir | None | 若指定,视频的逐帧图像会永久存储到该目录(否则使用临时目录) |
visualize_preds_keys | 见上 | 要可视化的模型预测键名序列,默认包含渲染图、掩码、深度图和源视角拼图 |
三、四种相机轨迹类型
trajectory_type支持四种轨迹(源码 eval_video_trajectory.py 第 84-163 行):
circular_lsq_fit(默认):对训练相机的光心进行 3D 圆拟合,相机中心沿拟合出的圆运动,所有相机始终看向scene_center。拟合逻辑由 circle_fitting.py 的fit_circle_in_3d实现,拟合后轨迹还会以trajectory_scale缩放(源码第 154-155 行)。figure_eight:围绕训练数据集"中心相机"(离所有相机光心均值最近的相机)画 8 字轨迹,参数方程为(源码第 266-269 行):x = t.cos() y = (2 * t).sin() / 2 z = t.sin() * z_scaletrefoil_knot:三叶结轨迹,参数方程为(源码第 259-263 行):x = t.sin() + 2 * (2 * t).sin() y = t.cos() - 2 * (2 * t).cos() z = -(3 * t).sin() * z_scalefigure_eight_knot:八字结轨迹,参数方程为(源码第 252-256 行):x = (2 + (2 * t).cos()) * (3 * t).cos() y = (2 + (2 * t).cos()) * (3 * t).sin() z = (4 * t).sin() * z_scale
对于三种结轨迹(figure_eight/trefoil_knot/figure_eight_knot),其参数曲线先生成于规范坐标系,再通过Scale(cam_centers.std(dim=0).mean() * trajectory_scale)与中心相机的世界到视图变换逆矩阵转换到场景坐标系(源码第 109-124 行),并以infer_up_as_plane_normal=True自动把up向量推断为相机光心拟合平面的法线(源码第 126-128 行)。最终所有轨迹都会经过look_at_view_transform(见 cameras.py)统一看向scene_center,且若focal_length/principal_point未指定,会取训练相机相应参数的平均值构造PerspectiveCameras(源码第 177-190 行)。
trajectory_type还有两个隐藏的净化开关:remove_outliers_rate在大于 0 时可移除训练相机中的离群光心(按每个维度上下各裁掉指定比例),使轨迹拟合更稳健(源码第 81-82 行、第 200-214 行)。
四、完整工作流程解析
render_flyaround的执行过程可以拆解为六个阶段(对照源码 render_flyaround.py 第 138-222 行):
阶段 1:加载整条序列
通过sequence_indices_in_order(sequence_name)拿到序列帧索引,用_load_whole_dataset(源码第 225-235 行)构造一个batch_size=len(idx)的 DataLoader 一次性加载全部帧,并以FrameData.collate整理为FrameData批次。随后用is_train_frame判断该序列属于 train 还是 test 集合(源码第 151 行)。
阶段 2:生成环绕相机轨迹
time = torch.linspace(0, max_angle, n_flyaround_poses + 1)[:n_flyaround_poses] test_cameras = generate_eval_video_cameras( train_cameras, time=time, n_eval_cams=n_flyaround_poses, trajectory_type=trajectory_type, trajectory_scale=trajectory_scale, scene_center=scene_center, up=up, focal_length=None, principal_point=torch.zeros(n_flyaround_poses, 2), traj_offset_canonical=(0.0, 0.0, traj_offset), )time在[0, max_angle]上均匀取n_flyaround_poses个采样点,作为轨迹参数方程的输入(源码第 154 行)。注意这里principal_point被显式置零,而focal_length取None以使用训练相机的平均焦距。
阶段 3:可复现地采样源视角
with torch.random.fork_rng(): torch.manual_seed(seed) source_views_i = torch.randperm(len(seq_idx))[:n_source_views]使用fork_rng隔离随机状态,保证源视角采样不污染全局随机数生成器;随后在批次头部pad一个占位视图,该视图会被逐帧替换为目标相机(源码第 169-175 行)。
阶段 4:逐帧渲染
对n_flyaround_poses中的每一帧:
- 把
test_cameras[n]的R、T、focal_length、principal_point写入批次首个相机(源码第 182-183 行); - 将整个批次搬到
device,在torch.no_grad()下以EvaluationMode.EVALUATION调用模型(源码第 186-188 行); - 将模型预测与网络输入合并为一个大字典,调用
_images_from_preds按visualize_preds_keys抽取并预处理成可视化图像(源码第 191-196 行); - 若开启 visdom,每 5% 的迭代(
n % max(n_flyaround_poses // 20, 1) == 0)调用_show_predictions推送一次中间结果(源码第 199-209 行)。
_images_from_preds(源码第 238-271 行)内部做了三类关键处理:
- 对
depth开头的键,用masks_render作掩码插值后调用make_depth_image生成伪彩色深度图; - 对
_all_source_images特殊键,从preds["image_rgb"][1:]取源视角并用_stack_images拼成网格图(源码第 274-286 行); - 对单通道图自动
repeat(1, 3, 1, 1)扩成 RGB。
阶段 5:生成视频
_generate_prediction_videos(源码第 335-393 行)为每个预测键创建一个VideoWriter:
vws[k] = VideoWriter( fps=fps, out_path=f"{video_path}_{sequence_name}_{k}.mp4", cache_dir=cache_dir, )随后逐帧写入并调用get_video()编码。VideoWriter(video_writer.py 第 34-214 行)默认调用系统ffmpeg(可用环境变量FFMPEG覆盖,_DEFAULT_FFMPEG = os.environ.get("FFMPEG", "ffmpeg")),使用h264编码、crf=18、b=2000k、pix_fmt=yuv420p参数;也可设置use_torchvision_video_writer=True改用torchvision.io.write_video。帧尺寸会被强制调整为偶数(resize[i] + resize[i] % 2)。
阶段 6:visdom 推送
若viz非空,把每个生成的视频文件通过viz.video(...)推送到 visdom 指定环境,窗口名复用预测键名(源码第 387-392 行)。
五、实战:从训练好的模型一键导出环绕视频
方式一:使用官方 CLI 脚本
Implicitron 训练工程提供了封装好的可视化入口 visualize_reconstruction.py,其模块 docstring 给出了典型命令行调用:
pytorch3d_implicitron_visualizer \ exp_dir='./exps/checkpoint_dir' visdom_show_preds=True visdom_port=8097 \ n_eval_cameras=40 render_size="[64,64]" video_size="[256,256]"该脚本的核心参数包括:
| 参数 | 默认值 | 说明 |
|---|---|---|
exp_dir | "" | 存放已训练模型与expconfig.yaml的实验目录 |
restrict_sequence_name | None | 若设置,仅可视化指定场景序列 |
output_directory | None | 自定义输出目录;默认输出到{exp_dir}/vis |
render_size | (512, 512) | 生成渲染的分辨率,会覆盖模型配置中的render_image_width/height(源码第 98-99 行) |
video_size | None | 输出视频尺寸,透传给video_resize |
split | "train" | 数据集划分,可选"train"/"val"/"test" |
n_source_views | 9 | 每个批次附加的源视角数量 |
n_eval_cameras | 40 | 每条环绕轨迹的相机数量,映射为n_flyaround_poses |
visdom_* | — | visdom 开关、服务器、端口与环境名 |
脚本会从实验目录加载expconfig.yaml,用force_resume=True恢复模型权重,遍历数据集中的每个序列,在torch.no_grad()下逐序列调用render_flyaround(源码第 121-139 行)。注意第 85-92 行的关键行为:为确保 CO3D 数据集全量加载,脚本会强制test_on_train=False,并支持通过restrict_sequence_name过滤序列。
方式二:在代码中直接调用
测试用例 test_model_visualize.py 第 82-110 行展示了一个完整的直接调用示例:
render_flyaround( train_dataset, show_sequence_name, model, video_path, n_flyaround_poses=10, fps=5, max_angle=2 * math.pi, trajectory_type="circular_lsq_fit", trajectory_scale=1.1, scene_center=(0.0, 0.0, 0.0), up=(0.0, 1.0, 0.0), traj_offset=1.0, n_source_views=1, visdom_show_preds=visdom_show_preds, visdom_environment="test_model_visalize", visdom_server="http://127.0.0.1", visdom_port=8097, num_workers=10, seed=None, video_resize=None, visualize_preds_keys=[ "images_render", "depths_render", "masks_render", "_all_source_images", ], output_video_frames_dir=output_video_frames_dir, )该测试还展示了自定义模型的最低要求:模型只需在forward中接受camera等 Implicitron 批次字段,并返回包含images_render、masks_render、depths_render的字典(见_PointcloudRenderingModel,第 113-153 行),即可被render_flyaround驱动。同时测试验证了output_video_frames_dir为None或指定目录两种模式均可工作。
运行前提
- 视频导出依赖系统安装
ffmpeg(或通过环境变量FFMPEG指定可执行文件路径); - visdom 功能需要在环境中安装
visdom并启动 visdom 服务(默认http://127.0.0.1:8097);get_visdom_connection在visdom不可导入时会静默返回None(vis_utils.py 第 58-62 行),不影响视频生成; - 默认
device="cuda",需要可用 GPU;纯 CPU 环境需显式传入device="cpu"; - 该测试用例本身需要
interactive_testing_requested()与 visdom 连接才执行,属于交互式/人工验收类测试(第 31-32 行、第 64 行)。
六、可视化内容与输出物约定
visualize_preds_keys默认输出四类内容,每类对应一个独立 mp4:
images_render:模型渲染的 RGB 重建图;masks_render:前景掩码;depths_render:经make_depth_image伪彩色化的深度图(渲染前会用masks_render做最近邻插值作为深度掩码,源码第 260-266 行);_all_source_images:当前批次所用源视角的网格拼图,用于对照"模型看到了哪些输入"。
输出文件命名规则为{output_video_path}_{sequence_name}_{key}.mp4。若指定了output_video_frames_dir,逐帧 PNG(frame_%08d.png)会持久保存在{output_video_frames_dir}/{sequence_name}_{key}目录下,便于逐帧检查或二次剪辑。
七、小结
render_flyaround是 PyTorch3D Implicitron 面向"多视角重建结果展示"的标准可视化组件,它将"数据集加载 → 轨迹生成 → 源视角采样 → 批量推理 → 视频编码"封装为一次调用,配合四种参数化轨迹(圆拟合、8 字、三叶结、八字结)与可配置的输出键,既能用于训练过程中的实时监控(visdom),也能用于训练完成后的离线结果交付(mp4 + 帧目录)。其完整 API 文档由 render_flyaround.rst 通过automodule自动生成,本文给出的参数语义、运行流程与调用示例均与 render_flyaround.py 源码、visualize_reconstruction.py CLI 与 test_model_visualize.py 测试逐行对应,可直接作为二次开发与排障的参考。
- 人工智能
- 深度学习
- 计算机视觉
- 图形学
【免费下载链接】pytorch3d
PyTorch3D is FAIR's library of reusable components for deep learning with 3D data
相关推荐
Netty在HuLa-Server中的应用:高性能WebSocket连接管理与消息推送
Netty在HuLa Server中的应用:高性能WebSocket连接管理与消息推送 HuLa Server是基于Spring AI、SpringCloud
人工智能深度学习计算机视觉图形学3D视觉革命:DUSt3R点云渲染与相机轨迹可视化全解析
3D视觉革命:DUSt3R点云渲染与相机轨迹可视化全解析 还在为复杂的3D重建可视化而头疼?DUSt3R让几何3D视觉变得简单直观!本文带你深入探索DUSt3R
人工智能深度学习计算机视觉预训练点云超详细!SHARP渲染视频教程:CUDA环境配置与相机轨迹生成全流程
超详细!SHARP渲染视频教程:CUDA环境配置与相机轨迹生成全流程 SHARP(Sharp Monocular View Synthesis)是一款强大的单目
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考