跳转至

D3D-HOI 默认重建流水线

语义

默认配置:configs/methods/recon/d3dhoi_default.yaml

一次运行按以下顺序执行:

  1. 全视频预处理与 human-facing object 初始化。
  2. 一次 object_pose_recon,内部固定执行四个 phase:
  3. joint_warm_start:V27D 80 iter。
  4. joint_search:V27D full-mask grid/DP search。
  5. joint_refine:V27D 80 iter。
  6. active_part_refine:V41R 160 iter。
  7. 一次 hoi_align_chain
  8. 子阶段 1:object_only_refine,200 iter。
  9. 子阶段 2:human_only_refine,200 iter。

四个 object phase 始终固定刚体 rotation、translation 和 xyz scale,只优化 articulation。 默认链路不包含 selective q-grid seed,只对应历史 V41R 中直接沿用 V27D q 的 18 个 case。

object_only_refinehuman_only_refine 是同一次 HOI-align 的两个顺序子阶段,不是两次独立 HOI-align。生产默认 save_intermediate_results: false,因此 HOI-align 部分只保存:

  • recon/output/result_hoi_align.pt
  • recon/output/result.pt

不会保存 result_hoi_align_object_only_refine.ptresult_hoi_align_human_only_refine.pt。物体重建只保存一次 result_object_pose_recon.pt,不为内部 phase 写中间结果。

Contact 使用显式的人机两步协议:batch VLM 只生成 contact_labels_raw.npz,HTML 人工确认后写 contact_labels.npz。两者都只包含 bool[T,2] 左右手语义标签。HOI-align 只读取 final,并在 loader 内存中确定性展开为同侧五指 mano_fingertip10、构造 palmar k16 顶点;磁盘上没有 converted contact NPZ。

Contact 标注:只需两个脚本

Contact preprocess 的正式用户接口只有以下两个脚本:

  1. infer_contact_labels_batch.py:批量运行 VLM,生成不可修改的 raw。
  2. serve_contact_review_editor.py:启动 HTML editor,人工检查并确认 final。

不需要运行 binary-to-fingertip conversion、materialize、install-reviewed 或其他 contact 脚本。

Canonical contact 使用 DashScope OpenAI-compatible endpoint 与 qwen-vl-max。运行 VLM 前必须在当前 shell 提供凭据;配置优先读取 OPENAI_VLM_API_KEY,其次读取 DASHSCOPE_API_KEY

export DASHSCOPE_API_KEY='<your key>'

可通过 OPENAI_VLM_BASE_URL 覆盖默认 endpoint。qwen-vl-max 不发送 reasoning_effort;该字段在默认配置中显式置空。

每个 case 内部的 interval 请求最多使用 64 个 worker。当前 256-case inventory 最长视频为 302 帧,即最多 38 个 interval,因此实际并发不会超过 38。case 之间仍按 顺序执行,避免在未知 API 配额下叠加两层并发。VLM 服务即使在 temperature: 0 下也不是逐字节确定性的;每个响应始终按唯一 interval_idx 写回,最终仍必须经过 HTML 人工 review。

大规模预处理:推荐入口

Full20 或全 benchmark 不要逐个手动运行 run_default_pipeline.py。推荐用统一调度器:

/DATA/intern/hoi4d/miniconda3/envs/arthoi4d/bin/python \
  scripts/run/d3dhoi/run_default_preprocess_parallel.py \
  --gpus 0,1,2,3,4,5,6,7 \
  --case-list-file configs/case_lists/d3dhoi_full20.txt \
  --run-contact

不传 --case-list--case-list-file 时,脚本处理 full.json 中的全部 case。也可以显式传入:

--case-list b001-0010_cad12561,b004-0032_cad7221,b005-0001_cad10900

调度器的行为是:

  • 自动检查每个 case 的预处理产物,完整 case 默认跳过,不重复计算。
  • 先探测视频帧数与分辨率,默认按预计耗时从长到短排队,减少尾部长任务。
  • 每张 GPU 同时只运行一个 case;某个 case 完成后,立即把该 GPU 分配给下一个 case。
  • 启动 worker 前默认要求该卡至少有 30,000 MiB 空闲显存;共享服务器上的忙卡会等待,不会直接叠加任务。可用 --min-free-memory-mib 调整,传 0 才会关闭保护。
  • GPU worker 使用 preprocess-auto,只延后网络 VLM contact;其他 canonical preprocess 模块全部执行。
  • --run-contact 在全部 GPU worker 释放显存后统一调用 infer_contact_labels_batch.py
  • 日志默认写入 <cases-root>/logs/preprocess_parallel/<UTC run id>/,其中 summary.json 原子更新,逐 case 日志可单独排错。
  • 任一进程退出非零,或返回后缺少必要产物,整批任务最终返回非零。

先只核对选择、排序和命令,不启动模型:

/DATA/intern/hoi4d/miniconda3/envs/arthoi4d/bin/python \
  scripts/run/d3dhoi/run_default_preprocess_parallel.py \
  --gpus 0,1,2,3,4,5,6,7 \
  --case-list-file configs/case_lists/d3dhoi_full20.txt \
  --dry-run

已有完整缓存但确实需要重跑时使用 --rerun-complete;需要删除并重建目标 preprocess 时才使用 --overwrite-preprocess。后者是破坏性操作,不应作为常规 scale-up 参数。

当前 V100S 32 GB 环境的实测峰值约为 25.7–27.3 GB/case,因此正式策略是“跨 GPU 并行 case”,不在同一张 GPU 上并行 SAM2、SAM3、DA3、SAM3D body 或 CoTracker 等重模块。依赖关系和优化验证见 D3D-HOI 预处理性能审计

1. Batch VLM

为已准备的 case 批量生成 raw:

/DATA/intern/hoi4d/miniconda3/envs/arthoi4d/bin/python \
  scripts/run/d3dhoi/infer_contact_labels_batch.py \
  --cases-root output/runs/<run>/cases \
  --config configs/methods/recon/d3dhoi_default.yaml

默认扫描 --cases-root 下的全部 case,也可以传入逗号分隔的 case IDs:

--case-list b001-0010_cad12561,b004-0013_cad7221

大规模任务建议传入每行一个 case ID 的文本文件:

--case-list-file configs/case_lists/my_cases.txt

batch 脚本不内置 failure5/full20 等实验集合,也不隐式选择配置;--config 始终必须显式传入。

每个 case 只生成:

<case>/recon/preprocess/contact/contact_labels_raw.npz

该文件只包含 labels: bool[T,2],两列固定表示 left/right。raw 已存在时默认跳过;HTML sidecar 永远不会修改 raw。

2. HTML sidecar

启动人工检查服务:

/DATA/intern/hoi4d/miniconda3/envs/arthoi4d/bin/python \
  scripts/run/d3dhoi/serve_contact_review_editor.py \
  --cases-root output/runs/<run>/cases \
  --host 0.0.0.0 \
  --port 8035

浏览器打开:

http://<服务器IP>:8035/

每个 interval 可以选择 left / right / both / none。点击这些按钮只修改浏览器中的临时状态,不会立即写磁盘。必须点击“确认该 case”或“保存并确认该 case”,服务端才会原子写入:

<case>/recon/preprocess/contact/contact_labels.npz

使用规则:

  • 未修改的 case 也必须点击确认。
  • final 存在表示该 case 已确认。
  • 已确认 case 可以重新修改;再次确认会覆盖 final,但 raw 始终不变。
  • “恢复 VLM 原始结果”只恢复浏览器状态,恢复后仍需点击确认。
  • final 缺失时 HOI-align 会 fail fast,不读取 raw。
  • HOI-align 在内存中完成 T×2 → mano_fingertip10 和 MANO 顶点采样,不产生额外 converted NPZ。

3. 运行主流水线

完整重建仍统一使用 arthoi4d 环境:

/DATA/intern/hoi4d/miniconda3/envs/arthoi4d/bin/python \
  scripts/run/d3dhoi/run_default_pipeline.py \
  --seq-id b001-0010 \
  --cad-id 12561

默认输出到:

output/runs/d3dhoi_default/<seq-id>_cad<cad-id>/

只检查配置和最终命令、不运行模型:

/DATA/intern/hoi4d/miniconda3/envs/arthoi4d/bin/python \
  scripts/run/d3dhoi/run_default_pipeline.py \
  --seq-id b001-0010 \
  --cad-id 12561 \
  --dry-run

脚本从 configs/datasets/d3dhoi_partnet/full.json 严格选择唯一的 (seq_id, cad_id) case,生成完整 runtime config,然后只调用一次 recon.py --stage all。配置和运行代码不依赖历史实验名或历史结果路径。

当前默认 HOI-align 目标

两个子阶段都使用经验证的 HOI-FHLI-style contact/grasp 组合:contact 8000,grasp dis/fc/pen/prior/spen = 800/0.2/720/0.01/1,object-local contact 20000,temporal velocity/acceleration 5000/50000,且不使用 contact top-k。object_only_refine 的 articulation smooth weight 为 90000