Files
hand-motion-pipeline/scripts/export_dynhamr_bimanual_rgbd.py
liyang ae28d55f81 Update to 2026-09-17 pipeline snapshot; add weights, L20 assets and recording via Git LFS
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>
2026-09-17 11:43:37 +08:00

19 lines
1.9 KiB
Python

"""Export corrected Dyn-HaMR world-oriented, wrist-relative joints for both L20 hands."""
from pathlib import Path
import json,shutil,numpy as np
ROOT=Path(__file__).resolve().parents[1]; BASE=ROOT/'output/20260915_171525_dynhamr'
source=BASE/'corrected/prior/20260915_171525_000000_world_results.npz'
a=np.load(source); joints=np.load(BASE/'corrected/comparison_joints.npz')['after']; camera=np.load(ROOT/'output/20260915_171525/rgbd_camera.npz')
assert joints.shape==(2,352,21,3) and np.isfinite(joints).all()
for b in range(2):
side='right' if a['is_right'][b,0]>.5 else 'left'
assert np.all(a['is_right'][b]==a['is_right'][b,0])
track=BASE/f'dataset/dynhamr/track_preds/20260915_171525/{b:03d}'
valid=np.array([(track/f'{t+1:06d}_keypoints.json').is_file() for t in range(352)])
np.savez_compressed(BASE/f'human_joints_{side}.npz',joints=joints[b]-joints[b,:,:1],wrist_world=joints[b,:,0],root_orient=np.zeros((352,3)),fps=30.,time=camera['time'],detection_valid=valid,source=str(source),side=side,coordinate_note='World-oriented wrist-relative joints from exact Dyn-HaMR run_mano, including left reflection; root rotation identity because joint directions already carry world orientation.',valid_semantics='Upstream keypoint file available; not per-joint confidence or depth acceptance.',depth_correction_applied=False)
print(side,'frames',len(joints[b]),'track available',valid.sum())
for name in ['rgbd_camera.npz','object_poses.npz','object_fit_validation.json']:
shutil.copy2(ROOT/'output/20260915_171525'/name,BASE/name)
shutil.copytree(ROOT/'output/20260915_171525/object_assets',BASE/'object_assets',dirs_exist_ok=True)
(BASE/'object_assets/colors.json').write_text(json.dumps({'upper':{'source':'上半.stl','rgba':[.8,.08,.05,1]},'lower':{'source':'下半.stl','rgba':[.05,.15,.65,1]},'note':'STL geometry is colorless; colors stored in replay scene.xml material/rgba.'},ensure_ascii=False,indent=2))