返回汇报

P3R2 真实拟合入口

原路径:/SSD2/yangzijing/egoview-v9-foundationhand-s9l10-20260901/v9_benchmark/p3r2_fit.py
SHA256:7226c41a93fa0bfcb0a4f32016572ac4bfe25875e53c8f914acf512ca99a346c

   1 """Full-sequence V9P3R2 fitting and isolated single-factor controls."""
   2 import argparse,os,time,traceback
   3 from dataclasses import asdict,replace
   4 from pathlib import Path
   5 os.environ.setdefault('PYOPENGL_PLATFORM','egl')
   6 import numpy as np
   7 from v9_benchmark.p3r2_common import OUT,rows,read,write,load,sha,link
   8 from v9_benchmark.p3r1_anomaly_experiment import hand_arrays,export
   9 from v9_benchmark.p3r1_anomaly import compute,quantiles
  10 
  11 def run(row,mano,faces,variant='V9P3R2'):
  12  import torch
  13  from v9_fusion.s9_sequence_fit import SequenceFitConfig,fit_sequence
  14  from v9_fusion.hand_surface import SurfaceConfig
  15  w=OUT/'work'/row['sequence_id'];dest=OUT/'results'/row['sequence_id'] if variant=='V9P3R2' else OUT/'ablations'/row['sequence_id']/variant;dest.mkdir(parents=True,exist_ok=True)
  16  if (dest/'complete.json').exists():return
  17  raw=load(w/'raw_s9.npz');e=load(w/'semantic_observations.npz');surface=load(w/'surface_constraints.npz');c=load(w/'camera.npz');previous=read(w/'sequence_fit.json');old=load(Path(row['work'])/'final_hand_camera.npz')
  18  conf=replace(SequenceFitConfig(**previous['config']),respect_observation_track_boundaries=True,partial_mask_initialization=True,palm_confidence_guard=True);sc=SurfaceConfig(**previous['surface_constraints']['config'])
  19  if variant=='no_palm_guard':conf=replace(conf,palm_confidence_guard=False)
  20  elif variant=='no_partial_init':conf=replace(conf,partial_mask_initialization=False)
  21  elif variant=='no_boundaries':conf=replace(conf,respect_observation_track_boundaries=False)
  22  elif variant=='no_scene':
  23   for k in ['scene_depth_m','scene_depth_valid','scene_depth_boxes']:surface.pop(k,None)
  24   partial=(e['v5r_mmpose_keypoint_scores']>=.35).sum(-1)<12;surface['containment_weight'][partial]=0
  25  elif variant=='no_ownership':e=load(w/'unowned_observations.npz');surface=load(w/'unowned_surface.npz')
  26  elif variant!='V9P3R2':raise ValueError('Unknown ablation')
  27  torch.set_grad_enabled(True);torch.manual_seed(20260914);np.random.seed(20260914);start=time.monotonic()
  28  if (dest/'fitted.npz').exists() and (dest/'fit.json').exists():result=load(dest/'fitted.npz');fit=read(dest/'fit.json')
  29  else:
  30   def progress(r):
  31    if r['step']%120==1:
  32     q=dict(sequence_id=row['sequence_id'],variant=variant,step=r['step'],loss=r['loss'],seconds=time.monotonic()-start);write(dest/'progress.json',q);print(q,flush=True)
  33   result,fit=fit_sequence(raw,e,c['K'].astype(np.float32),mano,conf,surface_constraints=surface,surface_config=sc,progress=progress)
  34   np.savez_compressed(dest/'fitted.npz',**result);write(dest/'fit.json',fit)
  35  h=hand_arrays(result,e);np.savez_compressed(dest/'final_hand_camera.npz',**h);np.savez_compressed(dest/'evidence.npz',**e);export(dest,h,c,faces)
  36  tracks=e['observation_track_ids'];values,_,_=compute(h,e,c,tracks,surface);np.savez_compressed(dest/'frame_metrics.npz',**values,hand_valid=h['hand_valid'],tracks=tracks,timestamps_s=c['timestamps_s'])
  37  common=h['hand_valid']&old['hand_valid'];delta=np.linalg.norm(h['joints_camera_m']-old['joints_camera_m'],axis=-1)
  38  report=dict(profile='V9P3R2',variant=variant,sequence_id=row['sequence_id'],date=row['date'],frames=row['frames'],fps=row['fps'],config=asdict(conf),surface_config=asdict(sc),random_seed=20260914,common_valid_slots=int(common.sum()),gained_slots=int((h['hand_valid']&~old['hand_valid']).sum()),lost_slots=int((~h['hand_valid']&old['hand_valid']).sum()),joint_difference_from_R1_m=quantiles(delta[common]),metrics={k:quantiles(v[h['hand_valid']]) for k,v in values.items()},seconds=time.monotonic()-start,runtime=dict(python=__import__('sys').executable,torch=torch.__version__,numpy=np.__version__),input_sha256={k:sha(w/k) for k in ['raw_s9.npz','camera.npz','semantic_observations.npz','surface_constraints.npz','sequence_fit.json']},source_sha256={str(p):sha(p) for p in [Path(__file__),Path('v9_fusion/s9_sequence_fit.py'),Path('v9_fusion/s9_pose_initialization.py')]},limitations='Model and stereo consistency, no 3D GT. Hidden fingers inferred, no interpolation or overlay clipping. Compare observation gains/losses separately.',accepted=False)
  39  write(dest/'report.json',report);write(dest/'complete.json',dict(profile='V9P3R2',variant=variant,frames=row['frames'],seconds=time.monotonic()-start));print('fit_complete',row['sequence_id'],variant,flush=True)
  40 
  41 def main():
  42  p=argparse.ArgumentParser();p.add_argument('--sequence');p.add_argument('--date');p.add_argument('--shard',type=int,default=0);p.add_argument('--shards',type=int,default=1);p.add_argument('--variants',default='V9P3R2');a=p.parse_args()
  43  from v9_fusion import s9l10_worker as locked
  44  locked._activate_official_runtime()
  45  import torch,yaml
  46  from foundation_hand.models.mano import ManoCameraLayer
  47  from v9_fusion.s9l10 import S9L10_CONFIG,S9L10_PYTHON
  48  if not Path(__import__('sys').executable).samefile(S9L10_PYTHON):raise ValueError('Locked fitting environment required')
  49  from v9_benchmark.hf_0907_contract import mano_topology
  50  torch.set_num_threads(3);cfg=yaml.safe_load(S9L10_CONFIG.read_text());mano=ManoCameraLayer(cfg['assets']['mano_root'],fix_left_shapedirs=True).cuda().eval();mano.requires_grad_(False);faces,_=mano_topology()
  51  selected=[r for r in rows() if (not a.sequence or r['sequence_id']==a.sequence) and (not a.date or r['date']==a.date)][a.shard::a.shards];done=[]
  52  while len(done)<len(selected):
  53   for row in selected:
  54    if row['sequence_id'] in done or not (OUT/'work'/row['sequence_id']/'surface_ready.json').exists():continue
  55    for v in a.variants.split(','):run(row,mano,faces,v)
  56    done.append(row['sequence_id']);write(OUT/f'fit_progress_{a.date}_{a.shard}_{a.sequence or "all"}.json',dict(done=done,total=len(selected),pid=os.getpid()))
  57   if len(done)<len(selected):time.sleep(10)
  58 if __name__=='__main__':main()