Spaces:
Running on Zero
Running on Zero
| #!/usr/bin/env python3 | |
| """ | |
| MagicDrive-V2 推理脚本(纯推理,不包含任何下载/安装逻辑) | |
| 前提:已运行 scripts/setup_space.py 完成环境搭建 | |
| 用法: | |
| # 224x400 快速预览(17帧,~22GB 显存) | |
| python scripts/infer.py --scene s8 --fast | |
| # 424x800 正式生成(129帧=10.75s,~44GB 显存) | |
| python scripts/infer.py --scene s8 | |
| # 指定输出路径 | |
| python scripts/infer.py --scene s25 --output outputs/my_video | |
| 场景: | |
| s8 停车场 21车 (车在正前方) | |
| s25 停车场+天桥 25车 (车最近) | |
| """ | |
| import argparse | |
| import os | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parent.parent | |
| # 场景配置 | |
| SCENES = { | |
| "s8": { | |
| "pkl": "data/nuscenes_mmdet3d-12Hz/ghost_peek_s8.pkl", | |
| "desc": "停车场 21车 (车在正前方 -20m)", | |
| }, | |
| "s25": { | |
| "pkl": "data/nuscenes_mmdet3d-12Hz/ghost_peek_s25.pkl", | |
| "desc": "停车场+天桥 25车 (车最近 6.9m)", | |
| }, | |
| } | |
| # 分辨率配置 | |
| PRESETS = { | |
| "fast": { | |
| "config": "fullx224x400_stdit3_CogVAE_boxTDS_wCT_xCE_wSST", | |
| "num_frames": 17, | |
| "desc": "低分辨率预览 (224x400, 17帧, ~22GB)", | |
| }, | |
| "full": { | |
| "config": "fullx424x800_stdit3_CogVAE_boxTDS_wCT_xCE_wSST", | |
| "num_frames": 129, | |
| "desc": "正式生成 (424x800, 129帧=10.75s, ~44GB)", | |
| }, | |
| } | |
| def check_ready() -> bool: | |
| """检查环境是否就绪""" | |
| required = [ | |
| ROOT / "pretrained" / "CogVideoX-2b" / "vae", | |
| ROOT / "pretrained" / "t5-v1_1-xxl", | |
| ROOT / "ckpts" / "MagicDriveDiT-stage3-40k-ft", | |
| ] | |
| all_ok = True | |
| for p in required: | |
| if not p.exists(): | |
| print(f"[MISS] {p.relative_to(ROOT)}") | |
| all_ok = False | |
| if not all_ok: | |
| print("\n请先运行: python scripts/setup_space.py") | |
| return all_ok | |
| def main(): | |
| parser = argparse.ArgumentParser(description="MagicDrive-V2 推理") | |
| parser.add_argument("--scene", choices=list(SCENES.keys()), default="s8", | |
| help="选择场景") | |
| parser.add_argument("--fast", action="store_true", | |
| help="低分辨率快速预览 (224x400, 17帧)") | |
| parser.add_argument("--num_frames", type=int, default=None, | |
| help="自定义帧数 (覆盖预设)") | |
| parser.add_argument("--output", type=str, default=None, | |
| help="输出目录") | |
| parser.add_argument("--cpu_offload", action="store_true", default=True, | |
| help="CPU offload (省显存)") | |
| parser.add_argument("--seed", type=int, default=42, | |
| help="随机种子") | |
| args = parser.parse_args() | |
| os.chdir(str(ROOT)) | |
| sys.path.insert(0, str(ROOT)) | |
| if not check_ready(): | |
| sys.exit(1) | |
| scene = SCENES[args.scene] | |
| preset = PRESETS["fast"] if args.fast else PRESETS["full"] | |
| num_frames = args.num_frames or preset["num_frames"] | |
| print("=" * 60) | |
| print(f"场景: {args.scene} - {scene['desc']}") | |
| print(f"配置: {preset['desc']}") | |
| print(f"帧数: {num_frames}") | |
| print(f"输出: {args.output or 'auto'}") | |
| print("=" * 60) | |
| # 构建推理命令 | |
| # 注意: parse_args 需要的是配置文件路径(位置参数)+ --cfg-options key=val ... | |
| config_path = str(ROOT / "configs" / "magicdrive" / "inference" / f"{preset['config']}.py") | |
| cmd = [ | |
| "torchrun", "--standalone", "--nproc_per_node=1", | |
| str(ROOT / "scripts" / "inference_magicdrive.py"), | |
| config_path, | |
| "--cfg-options", | |
| f"num_frames={num_frames}", | |
| f"seed={args.seed}", | |
| ] | |
| if args.cpu_offload: | |
| cmd.append("cpu_offload=true") | |
| # 用 dataset_cfg_overrides 切换 PKL | |
| override = f"dataset_cfg_overrides=[('dataset.data.val.ann_file', '{scene['pkl']}')]" | |
| cmd.append(override) | |
| if args.output: | |
| cmd.append(f"outputs={args.output}") | |
| print(f"\n运行: {' '.join(cmd)}") | |
| print("-" * 60) | |
| result = subprocess.run( | |
| cmd, | |
| cwd=str(ROOT), | |
| env={**os.environ, "PYTHONPATH": str(ROOT)}, | |
| ) | |
| if result.returncode == 0: | |
| print("\n推理完成!输出在 outputs/ 目录下") | |
| else: | |
| print(f"\n推理失败 (exit code: {result.returncode})") | |
| sys.exit(result.returncode) | |
| if __name__ == "__main__": | |
| main() | |