"""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))