ae28d55f81
Source: RGB-D -> Dyn-HaMR -> L20 retargeting -> FoundationPose -> reference repair -> SPIDER, documented in docs/PIPELINE_LATEST.md and docs/SETUP_AND_WEIGHTS.md. Adds FoundationPose and nvdiffrast upstream snapshots, requirements/pipeline_venv.txt and the FoundationPose weight manifest/downloader. Assets (Git LFS): weights/ (WiLoR detector, HandFlow denoiser, UniDepth-L), FoundationPose checkpoints, HaMeR checkpoint, Dyn-HaMR HMP model and BMC constraints, L20 URDF/meshes, the 20260915_171525 D405 recording and the two box CADs. MANO models are not redistributed (third_party/hamer/_DATA/data/mano/README.txt). Environments, caches and run outputs excluded. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
50 lines
2.6 KiB
Python
50 lines
2.6 KiB
Python
"""Run both-hand Dyn-HaMR with measured intrinsics and RGB-D odometry."""
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import time
|
|
import numpy as np
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
OUT = ROOT / 'output/20260915_171525_dynhamr'
|
|
OUT.mkdir(parents=True, exist_ok=True)
|
|
SEQ = '20260915_171525'
|
|
dataset = OUT / 'dataset'
|
|
(dataset / 'videos').mkdir(parents=True, exist_ok=True)
|
|
video = dataset / 'videos' / (SEQ + '.mp4')
|
|
if not video.exists():
|
|
video.symlink_to(ROOT / 'docs' / SEQ / 'color.mp4')
|
|
camera = np.load(ROOT / 'output' / SEQ / 'rgbd_camera.npz')
|
|
assert camera['c2w'].shape == (352, 4, 4)
|
|
for kind, data in [('pose', camera['c2w']), ('intrinsics', np.tile(camera['intrinsics'], (352, 1)))]:
|
|
directory = OUT / 'rgbd_cameras' / kind
|
|
directory.mkdir(parents=True, exist_ok=True)
|
|
np.savez(directory / (SEQ + '.npz'), data=data.astype(np.float32), inds=np.arange(352))
|
|
(OUT / 'camera_provenance.json').write_text(json.dumps(dict(
|
|
source=str(ROOT / 'output' / SEQ / 'rgbd_camera.npz'),
|
|
method=str(camera['method']), adapter='ViPE file schema only; cameras estimated from D405 RGB-D',
|
|
hand_reconstruction='Dyn-HaMR', hands=['left', 'right']), indent=2))
|
|
dyn = ROOT / 'third_party/Dyn-HaMR'
|
|
env = os.environ.copy()
|
|
env.update(TORCH_HOME=str(ROOT / '.torch_cache'), HF_HOME=str(ROOT / '.hf_cache'),
|
|
HF_HUB_OFFLINE='1', TRANSFORMERS_OFFLINE='1', PYTHONUNBUFFERED='1',
|
|
MPLCONFIGDIR='/tmp/matplotlib-dynhamr', HYDRA_FULL_ERROR='1',
|
|
PYOPENGL_PLATFORM='egl', LD_LIBRARY_PATH='')
|
|
env['PATH'] = str(dyn / '.dynhamr/bin') + ':' + env['PATH']
|
|
env['PYTHONPATH'] = ':'.join(str(dyn / p) for p in ['dyn-hamr', 'third-party/hamer', 'third-party/hamer/third-party/ViTPose'])
|
|
cmd = [str(dyn / '.dynhamr/bin/python'), '-u', 'run_opt.py', 'data=video_vipe',
|
|
'data.root=' + str(dataset), 'data.seq="' + SEQ + '"',
|
|
'data.vipe_dir=' + str(OUT / 'rgbd_cameras'), 'data.frame_opts.fps=30',
|
|
'is_static=False', 'model.opt_scale=False', 'run_opt=True', 'run_vis=True',
|
|
'run_prior=True', '+data.vipe_pipeline=dynhamr_cameras',
|
|
'HMP.vid_path=' + str(video), 'hydra.run.dir=' + str(OUT / 'optimization')]
|
|
def status(stage, **kw):
|
|
(OUT / 'status.json').write_text(json.dumps(dict(stage=stage,
|
|
updated=time.strftime('%Y-%m-%d %H:%M:%S'), pid=os.getpid(), **kw), indent=2))
|
|
status('RUNNING', command=cmd)
|
|
with (OUT / 'run.log').open('a') as log:
|
|
result = subprocess.run(cmd, cwd=dyn / 'dyn-hamr', env=env, stdout=log, stderr=subprocess.STDOUT)
|
|
status('RECONSTRUCTION_PROCESS_EXITED' if result.returncode == 0 else 'FAILED', returncode=result.returncode)
|
|
raise SystemExit(result.returncode)
|