AsianPlayer/TriDrive / code /data /extract_pose_causal_routes.py
AsianPlayer's picture
download
raw
23.3 kB
"""cwm3/data/extract_pose_causal_routes.py — ROUTE-LEVEL causal driver pose at 10 Hz for every s12 route (causal replacement of
s8_pose/cache/pose10hz, whose 400×400 crop was a whole-route median = non-causal).
Time base: frame/20 as s8_pose/extract_pose.py (fi = 2k, t = k/10; never container fps). Frames are decoded with cv2 seek+grab
(bit-identical to decord, verified 2026-09-10) in worker processes and resized aspect-preserving to width 640 (like the old
640-wide decode); coordinates are stored NORMALISED (x/W, y/H), so the decode size is irrelevant to the output.
Spans: union over the route's s12 anchors of [t − 8.2, t + 5.2] (8 s history + 5 s future + 0.2 s), merged when gaps ≤ 10 s,
clipped to the video (the old cache used [t − 4.2, t]).
1. Causal driver box. YOLO11x-pose (ultralytics, imgsz 384, half, conf 0.3) on every 10 Hz frame; persons with area < 2 % of the
frame ignored (driver_roi v2 rule). Driver = the candidate nearest the device's driver-side prior cx (|Δcx| ≤ 0.18 = v2 cluster
gap); prior = per-dongle median of person_cx_norm over the ROI mirror's solo-occupant pose_detector clips (results/roi, ≥ 3 clips),
else cwm2/private/person_diag.json['dside'], else BOOTSTRAPPED CAUSALLY inside the route (v2/extract_full analogue): solo-person
frames' cx are accumulated and become the prior after 30 of them; before that the largest-area candidate is taken (flag).
Once ≥ 30 frames were selected the reference cx becomes the running median of the selected cx.
box(t) = per-coordinate median over selected boxes on MOVING frames ≤ t (vEgo > 2 m/s from s14 grid10, column recovered by AST
from grid_s14.py + canspec.FEATURES, nearest 0.1 s; NaN vEgo = not moving); before any moving frame: median over all selected
frames so far (fallback); stage 1 (warm-up) until 30 s (300) of moving frames, stage 2 (expanding) until 60 s (600) of moving
frames, then FROZEN (stage 3, box_frozen_from_t). The box trajectory is stored per route (native px).
2. RTMW-x-l (rtmlib 'balanced' pose ONNX, onnxruntime CUDA, detection-free) on box(t) expanded by 10 % (same code path and
HALPE-136 mapping as extract_pose_causal.py) → results/pose_causal_routes/<uid>.npz:
t f32[N], frame_idx i64[N], kpts f16[N,136,3] (x/W, y/H, conf; NaN where no box), mask[N,136] (finite ∧ conf ≥ 0.3),
box f32[N,4] native px (NaN undefined), box_stage u8[N] {0 none,1 warm-up,2 expanding,3 frozen}, box_frozen_from_t,
driver_det[N], n_persons[N], moving[N], dside_prior, dside_source, decode_wh, native_wh, spans, model_ids, video_source.
v2 (--population-prior auto, --out-dir): routes whose device has no prior use the POPULATION driver-side prior (median cx over the
mirror-prior dongles) instead of the largest-area fallback — causal and route-independent. Block-level checkpointing was NOT added
(tracker state + in-flight decode futures would need serialising; not a small change).
GPU: ≤ 6 GB by construction (YOLO fp16 batch ≤ 24 + ORT arena limit); usable without the GPU lock only if decode-bound (bench).
Resumable (existing npz skipped; --max-minutes stops starting new routes). Exit 3 = work remaining, 0 = done."""
import argparse, ast, json, math, shutil, sys, time
import multiprocessing as mp
from concurrent.futures import ProcessPoolExecutor
from pathlib import Path
import numpy as np
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "common")); sys.path.insert(0, str(ROOT / "data"))
from extract_pose_causal import box_geometry, crop_input, wb133_to_halpe136, Pose, resolve_video, MODEL_ID as RTMW_ID, SCORE_TH, MARGIN, IN_W, IN_H # noqa: E402
EXPLORE = Path("/home/USER/explore"); S12R = EXPLORE / "s12_wm" / "results"; GRID10 = EXPLORE / "s14_corr" / "cache" / "grid10"
LEAVES = ROOT / "results" / "baton_leaves.json"; OUT = ROOT / "results" / "pose_causal_routes"; ROI = ROOT / "results" / "roi"
CLIP_MAP = EXPLORE / "cwm2" / "private" / "clip_map_full.json"; PERSON_DIAG = EXPLORE / "cwm2" / "private" / "person_diag.json"
YOLO_W = Path("/home/USER/Drive/explore/yolo11x-pose.pt")
FPS, HZ, DEC_W = 20, 10, 640
PAD_PRE, PAD_POST, MERGE_GAP = 8.2, 5.2, 10.0
MIN_AREA, GAP_CX, V_MOVE = 0.02, 0.18, 2.0
N_PRIOR_BOOT, N_REF, N_WARM, N_FREEZE = 30, 30, 300, 600
YOLO_ID = "yolo11x-pose.pt (ultralytics 8.4.66), imgsz 384, half, conf 0.3, persons area >= 2 %"
def leaf_of(uid):
p = uid.split("__"); return "/".join(p[:3]) + "/" + "__".join(p[3:])
def vego_col():
sys.path.insert(0, str(EXPLORE / "s3_can_baseline")); import canspec
tree = ast.parse((EXPLORE / "s14_corr" / "grid_s14.py").read_text()); lists = {}
for node in tree.body:
if isinstance(node, ast.Assign) and len(node.targets) == 1 and isinstance(node.targets[0], ast.Name) and node.targets[0].id in ("DCOLS", "PCOLS", "RCOLS"):
lists[node.targets[0].id] = [ast.literal_eval(e) for e in node.value.elts]
cols = lists["DCOLS"] + lists["PCOLS"] + list(canspec.FEATURES) + lists["RCOLS"]; return cols.index("vEgo")
def dside_priors():
"""per-dongle driver-side cx prior: ROI mirror (solo-occupant pose_detector clips, >= 3) else person_diag; cached."""
cache = OUT / "dside_prior.json"
if cache.exists(): return json.load(open(cache))
cm = json.load(open(CLIP_MAP)); by = {}
for p in ROI.glob("*.json"):
r = json.load(open(p))
if r.get("roi_source") == "pose_detector" and r.get("n_persons_max") == 1 and r.get("person_cx_norm") is not None:
by.setdefault(cm[r["clip_id"]]["dongle"], []).append(r["person_cx_norm"])
pri = {d: dict(cx=float(np.median(v)), n=len(v), source="roi_mirror_solo_median") for d, v in by.items() if len(v) >= 3}
diag = json.load(open(PERSON_DIAG)).get("dside", {}) if PERSON_DIAG.exists() else {}
for d, cx in diag.items():
if d not in pri: pri[d] = dict(cx=float(cx), n=None, source="person_diag_dside")
OUT.mkdir(parents=True, exist_ok=True); cache.write_text(json.dumps(pri, indent=1)); return pri
def anchors_by_uid():
A = {}
for reg in ("manual", "engaged"):
for sp in ("train", "val", "test"):
z = np.load(S12R / f"targets_{reg}_{sp}.npz", allow_pickle=True)
for u, t in zip(z["uid"], z["t"]): A.setdefault(u, []).append(float(t))
return {u: np.sort(np.array(v)) for u, v in A.items()}
def spans_of(ts, dur):
a, b = np.maximum(ts - PAD_PRE, 0.0), np.minimum(ts + PAD_POST, dur); o = np.argsort(a); a, b = a[o], b[o]; out = []; ca, cb = a[0], b[0]
for x, y in zip(a[1:], b[1:]):
if x > cb + MERGE_GAP: out.append((ca, cb)); ca, cb = x, y
else: cb = max(cb, y)
out.append((ca, cb)); return out
def decode_block(job):
"""worker: (vpath, fi_list, dec_w, dec_h) -> uint8 [n, dec_h, dec_w, 3] BGR (grab every frame from fi[0]..fi[-1], retrieve the 10 Hz ones)."""
import cv2; cv2.setNumThreads(2)
vpath, fis, dw, dh = job; t = time.time()
cap = cv2.VideoCapture(vpath); cap.set(cv2.CAP_PROP_N_THREADS, 2); cap.set(cv2.CAP_PROP_POS_FRAMES, int(fis[0])); want = {int(f): i for i, f in enumerate(fis)} # 2 ffmpeg threads/worker: no oversubscription
out = np.zeros((len(fis), dh, dw, 3), np.uint8); got = np.zeros(len(fis), bool); n_grab = 0
for i in range(int(fis[0]), int(fis[-1]) + 1):
if not cap.grab(): break
n_grab += 1
if i in want:
ok, fr = cap.retrieve()
if not ok: break
out[want[i]] = cv2.resize(fr, (dw, dh), interpolation=cv2.INTER_AREA); got[want[i]] = True
cap.release(); return dict(frames=out, got=got, n_grab=n_grab, secs=time.time() - t)
def infer_batched(pose, crops_u8, center, scale, chunk=96):
"""RTMW on a batch of crops with per-frame (center, scale): same maths as extract_pose_causal.Pose.infer, vectorised."""
from extract_pose_causal import MEAN, STD
x = np.ascontiguousarray(((crops_u8.astype(np.float32) - MEAN) / STD).transpose(0, 3, 1, 2))
locs, vals = [], []
for i in range(0, len(x), chunk):
sx_, sy_ = pose.sess.run(pose.outs, {pose.inp: x[i:i + chunk]}); l, v = pose.simcc(sx_, sy_); locs.append(l); vals.append(v)
locs = np.concatenate(locs); vals = np.concatenate(vals)
kp = locs / 2.0 / np.array([IN_W, IN_H], np.float32) * scale[:, None, :] + center[:, None, :] - scale[:, None, :] / 2
kp[locs[..., 0] < 0] = np.nan
return np.concatenate([kp, vals[..., None]], -1).astype(np.float32)
class DriverTracker:
"""causal driver selection + expanding-median box (decode-frame coordinates)."""
def __init__(self, prior_cx, dw, dh):
self.prior = prior_cx; self.dw, self.dh = dw, dh; self.boot = []; self.sel_cx = []; self.mov = [[], [], [], []]; self.all = [[], [], [], []]
self.n_mov = 0; self.frozen = None; self.stage = 0; self.uncertain = 0
def _ref(self):
if len(self.sel_cx) >= N_REF: return float(np.median(self.sel_cx))
if self.prior is not None: return self.prior
if len(self.boot) >= N_PRIOR_BOOT: self.prior = float(np.median(self.boot)); return self.prior
return None
def step(self, cands, moving):
"""cands: list of (cx_norm, area_norm, box_xyxy_dec) -> (box_dec or None, selected bool)"""
sel = None; ref = self._ref()
if cands:
if ref is not None:
c = min(cands, key=lambda z: abs(z[0] - ref))
if abs(c[0] - ref) <= GAP_CX: sel = c
else:
if len(cands) == 1: self.boot.append(cands[0][0]); sel = cands[0]
else: sel = max(cands, key=lambda z: z[1]); self.uncertain += 1
if sel is not None:
self.sel_cx.append(sel[0])
if self.frozen is None:
for j in range(4): self.all[j].append(float(sel[2][j]))
if moving:
for j in range(4): self.mov[j].append(float(sel[2][j]))
self.n_mov += 1
if self.frozen is not None: self.stage = 3; return self.frozen, sel is not None
if self.n_mov >= N_FREEZE:
self.frozen = np.array([np.median(v) for v in self.mov], np.float32); self.stage = 3; return self.frozen, sel is not None
if self.n_mov > 0:
self.stage = 1 if self.n_mov < N_WARM else 2; return np.array([np.median(v) for v in self.mov], np.float32), sel is not None
if len(self.all[0]) > 0:
self.stage = 1; return np.array([np.median(v) for v in self.all], np.float32), sel is not None
self.stage = 0; return None, False
def main():
ap = argparse.ArgumentParser(); ap.add_argument("--uids", default=""); ap.add_argument("--all", action="store_true"); ap.add_argument("--limit", type=int, default=0)
ap.add_argument("--max-minutes", type=float, default=20.0); ap.add_argument("--decode-workers", type=int, default=6); ap.add_argument("--block", type=int, default=300, help="10 Hz frames per decode block")
ap.add_argument("--yolo-batch", type=int, default=48); ap.add_argument("--ort-mem-gb", type=float, default=2.0); ap.add_argument("--bench-out", default=""); ap.add_argument("--force", action="store_true")
ap.add_argument("--out-dir", default="", help="versioned output dir (default results/pose_causal_routes)"); ap.add_argument("--population-prior", default="", help="'auto' = median driver-side cx over the mirror-prior dongles, or a float; used ONLY for routes whose device has no prior (replaces the largest-area fallback)")
ap.add_argument("--vram-check-gb", type=float, default=0.0, help="abort unless at least this much GPU memory is free before loading models")
a = ap.parse_args(); t_start = time.time()
global OUT
PRIOR_DIR = OUT # dside_prior.json / s12_uids.txt always come from the v1 location
if a.out_dir: OUT = Path(a.out_dir)
OUT.mkdir(parents=True, exist_ok=True)
from runmeta import write_run_json
import cv2, torch, psutil
if a.vram_check_gb > 0:
free_b, total_b = torch.cuda.mem_get_info(); print(f"VRAM free {free_b/1e9:.1f} / {total_b/1e9:.1f} GB (need {a.vram_check_gb})", flush=True)
if free_b < a.vram_check_gb * 1e9: print("VRAM_CHECK_FAILED", flush=True); sys.exit(4)
from ultralytics import YOLO
uids = [l.strip() for l in open(a.uids) if l.strip()] if a.uids else []
if a.all: uids += [l.strip() for l in open(PRIOR_DIR / "s12_uids.txt") if l.strip()]
seen = set(); uids = [u for u in uids if not (u in seen or seen.add(u))]
if a.limit: uids = uids[:a.limit]
todo = [u for u in uids if a.force or not (OUT / f"{u}.npz").exists()]
leaves = json.load(open(LEAVES)); pri = json.load(open(PRIOR_DIR / "dside_prior.json")) if (PRIOR_DIR / "dside_prior.json").exists() else dside_priors(); VCOL = vego_col(); A = anchors_by_uid()
pop_prior = None
if a.population_prior:
pop_prior = float(np.median([v["cx"] for v in pri.values() if v.get("source") == "roi_mirror_solo_median"])) if a.population_prior == "auto" else float(a.population_prior)
print(f"population driver-side prior cx = {pop_prior:.4f} (causal, route-independent; used only where the device has no prior)", flush=True)
print(f"routes requested {len(uids)} todo {len(todo)}; dside priors {len(pri)}; vEgo col {VCOL}", flush=True)
yolo = YOLO(str(YOLO_W)); pose = Pose(gpu_mem_limit=a.ort_mem_gb * 1e9)
pool = ProcessPoolExecutor(max_workers=a.decode_workers, mp_context=mp.get_context("spawn"))
stats = dict(download_bytes=0, download_secs=0.0, n_downloads=0, download_leaves=[]); recs, fails = [], []; budget_hit = False
for u in todo:
if time.time() - t_start > a.max_minutes * 60: budget_hit = True; break
leaf = leaf_of(u); tr0 = time.time()
try:
vpath, src = resolve_video(leaf, leaves, stats)
cap = cv2.VideoCapture(vpath); W, H, n_frames = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)), int(cap.get(cv2.CAP_PROP_FRAME_COUNT)); cap.release()
if n_frames <= 0 or W <= 0: raise RuntimeError("cannot read video header")
dw = DEC_W; dh = int(round(H * DEC_W / W)); sx, sy = W / dw, H / dh
dur = n_frames / FPS; ts = A.get(u)
if ts is None: raise RuntimeError("no s12 anchors")
spans = spans_of(ts, dur)
ks = np.unique(np.concatenate([np.arange(int(math.floor(a0 * HZ)), int(math.ceil(b0 * HZ)) + 1) for a0, b0 in spans])); fis = 2 * ks; keep = fis < n_frames; ks, fis = ks[keep], fis[keep]
N = len(ks); tt = (ks / HZ).astype(np.float32)
g = np.load(GRID10 / f"{u}.npz"); gt, gv = g["t"], g["G"][:, VCOL]
gi = np.clip(np.round(tt * 10).astype(np.int64) - int(round(gt[0] * 10)), 0, len(gt) - 1); moving = np.nan_to_num(gv[gi], nan=-1.0) > V_MOVE
dongle = u.split("__")[1]; pr = pri.get(dongle); prior_cx = pr["cx"] if pr else None
if prior_cx is None and pop_prior is not None: prior_cx = pop_prior; pr = dict(cx=pop_prior, source="population_median_cx")
trk = DriverTracker(prior_cx, dw, dh)
kpts = np.full((N, 136, 3), np.nan, np.float32); box = np.full((N, 4), np.nan, np.float32); stage = np.zeros(N, np.uint8); det = np.zeros(N, bool); npers = np.zeros(N, np.uint8); frozen_t = np.nan
blocks = [np.arange(i, min(i + a.block, N)) for i in range(0, N, a.block)]
futs = []; bi = 0; t_dec = t_yolo = t_rtmw = 0.0; n_grab = 0; n_yolo = 0; n_rtmw = 0
def submit_upto(n):
nonlocal bi
while bi < len(blocks) and len(futs) < n:
b = blocks[bi]; futs.append(pool.submit(decode_block, (vpath, fis[b], dw, dh))); bi += 1
submit_upto(2 * a.decode_workers)
for b in blocks:
res = futs.pop(0).result(); submit_upto(2 * a.decode_workers); t_dec += res["secs"]; n_grab += res["n_grab"]
frames = res["frames"]; got = res["got"]
# YOLO on the block
t1 = time.time(); cands_all = []
for i0 in range(0, len(b), a.yolo_batch):
rs = yolo.predict(list(frames[i0:i0 + a.yolo_batch]), imgsz=384, half=True, conf=0.3, verbose=False, classes=[0])
for r in rs:
cc = []
if r.boxes is not None and len(r.boxes):
bx = r.boxes.xyxy.cpu().numpy()
for x0, y0, x1, y1 in bx:
area = (x1 - x0) * (y1 - y0) / (dw * dh)
if area >= MIN_AREA: cc.append(((x0 + x1) / 2 / dw, area, (x0, y0, x1, y1)))
cands_all.append(cc)
t_yolo += time.time() - t1; n_yolo += len(b)
# causal tracker + crops
crops = []; idx_ok = []
for j, i in enumerate(b):
if not got[j]: cands_all[j] = []
bx, s_ = trk.step(cands_all[j], bool(moving[i])); det[i] = s_; npers[i] = min(len(cands_all[j]), 255); stage[i] = trk.stage
if trk.frozen is not None and np.isnan(frozen_t): frozen_t = float(tt[i])
if bx is not None and got[j]:
box[i] = [bx[0] * sx, bx[1] * sy, bx[2] * sx, bx[3] * sy]
x0, y0, x1, y1 = bx; w, h = x1 - x0, y1 - y0
used = [max(0, x0 - MARGIN * w), max(0, y0 - MARGIN * h), min(dw, x1 + MARGIN * w), min(dh, y1 + MARGIN * h)]
c, s = box_geometry(used); crops.append((crop_input(frames[j], c, s), c, s)); idx_ok.append(i)
if crops:
t2 = time.time()
# one CUDA batch per block with PER-FRAME geometry (box changes every frame while the median expands)
imgs = np.stack([c_[0] for c_ in crops]); cen = np.stack([c_[1] for c_ in crops]).astype(np.float32); scl = np.stack([c_[2] for c_ in crops]).astype(np.float32)
k133 = infer_batched(pose, imgs, cen, scl)
h136 = wb133_to_halpe136(k133); h136[..., 0] *= sx / W; h136[..., 1] *= sy / H # decode px -> native px -> normalised
kpts[idx_ok] = h136
t_rtmw += time.time() - t2; n_rtmw += len(crops)
k16 = kpts.astype(np.float16); mask = np.isfinite(k16).all(-1) & (np.nan_to_num(k16[..., 2].astype(np.float32)) >= SCORE_TH)
np.savez_compressed(OUT / f"{u}.npz", t=tt, frame_idx=fis.astype(np.int64), kpts=k16, mask=mask, box=box, box_stage=stage, box_frozen_from_t=np.float32(frozen_t), driver_det=det, n_persons=npers, moving=moving,
dside_prior=np.float32(prior_cx if prior_cx is not None else np.nan), dside_source=str(pr["source"] if pr else ("route_bootstrap" if trk.prior is not None else "none_largest_area")),
n_uncertain_largest_area=int(trk.uncertain), decode_wh=np.array([dw, dh], np.int32), native_wh=np.array([W, H], np.int32), spans=np.array(spans, np.float32), n_video_frames=n_frames,
model_ids=np.array([YOLO_ID, RTMW_ID]), kpt_order="halpe136", score_th=SCORE_TH, margin=MARGIN, video_source=src, time_base="frame/20: t=k/10, frame_idx=2k", v_move_mps=V_MOVE,
box_rule=np.array("per-coordinate median of selected driver boxes on moving frames <= t; warm-up <300 moving frames, expanding <600, then frozen"))
wall = time.time() - tr0
recs.append(dict(uid=u, n_frames_10hz=int(N), n_grab=int(n_grab), span_cover=float(sum(b0 - a0 for a0, b0 in spans) / dur), wall_s=round(wall, 1), decode_worker_s=round(t_dec, 1), yolo_s=round(t_yolo, 1), rtmw_s=round(t_rtmw, 1),
n_rtmw=int(n_rtmw), det_rate=float(det.mean()), moving_frac=float(moving.mean()), box_frozen_from_t=frozen_t, dside_source=str(pr["source"] if pr else "bootstrap/none"), video_source=src,
mask_body_rate=float(mask[:, :17].mean()), gpu_peak_torch_GB=round(torch.cuda.max_memory_reserved() / 1e9, 2)))
print(f"{u[:60]} N={N} wall {wall:.0f}s dec {t_dec:.0f}s(worker) yolo {t_yolo:.0f}s rtmw {t_rtmw:.0f}s det {det.mean():.3f} frozen@{frozen_t} rss {psutil.Process().memory_info().rss/1e9:.1f}GB", flush=True)
if src == "remote_download": shutil.rmtree(Path(vpath).parent, ignore_errors=True)
except Exception as e:
fails.append(dict(uid=u, err=repr(e)[:300])); print(f"FAIL {u[:60]}: {repr(e)[:200]}", flush=True)
pool.shutdown(wait=True)
remaining = len(todo) - len(recs) - len(fails); wall = time.time() - t_start
summ = dict(n_requested=len(uids), n_todo=len(todo), n_done=len(recs), n_failed=len(fails), n_remaining=max(0, remaining), budget_hit=budget_hit, wall_s=round(wall, 1), decode_workers=a.decode_workers, yolo_batch=a.yolo_batch)
if recs:
fr = sum(r["n_frames_10hz"] for r in recs); w_no_dl = wall - stats["download_secs"]
gpu_s = sum(r["yolo_s"] + r["rtmw_s"] for r in recs)
summ.update(frames_10hz=fr, frames_grabbed=sum(r["n_grab"] for r in recs), yolo_ms_per_frame=round(1000 * sum(r["yolo_s"] for r in recs) / fr, 3), rtmw_ms_per_frame=round(1000 * sum(r["rtmw_s"] for r in recs) / max(sum(r["n_rtmw"] for r in recs), 1), 3),
worker_decode_fps=round(sum(r["n_grab"] for r in recs) / max(sum(r["decode_worker_s"] for r in recs), 1e-9), 1), aggregate_decode_fps=round(sum(r["n_grab"] for r in recs) / max(w_no_dl, 1e-9), 1),
frames_10hz_per_s=round(fr / max(w_no_dl, 1e-9), 1), gpu_busy_frac=round(gpu_s / max(w_no_dl, 1e-9), 3), decode_bound=bool(gpu_s / max(w_no_dl, 1e-9) < 0.5),
det_rate_mean=round(float(np.mean([r["det_rate"] for r in recs])), 4), gpu_peak_torch_GB=max(r["gpu_peak_torch_GB"] for r in recs), ort_mem_limit_GB=a.ort_mem_gb,
download=dict(n=stats["n_downloads"], bytes=stats["download_bytes"], secs=round(stats["download_secs"], 1), MBps=round(stats["download_bytes"] / 1e6 / stats["download_secs"], 1) if stats["download_secs"] else None))
# projection over all s12 routes: 10 Hz frames in spans (local videos measured; remote estimated from bytes)
try:
tot10 = json.load(open(OUT / "span_frames_total.json"))["frames_10hz_total"]
except Exception: tot10 = None
if tot10: summ["projection_all_routes"] = dict(frames_10hz_total=tot10, wall_h=round(tot10 / summ["frames_10hz_per_s"] / 3600, 2), gpu_h=round(tot10 * (summ["yolo_ms_per_frame"] + summ["rtmw_ms_per_frame"]) / 3.6e6, 2))
if a.bench_out: Path(a.bench_out).write_text(json.dumps(dict(utc=time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), summary=summ, routes=recs, fails=fails), indent=1))
write_run_json(OUT, "extract_pose_causal_routes", [Path(__file__), ROOT / "data" / "extract_pose_causal.py"], [LEAVES], None, t_start, extra=dict(summary=summ, fails_head=fails[:20]), input_listing=False)
print(("BUDGET_EXIT " if budget_hit else "ALL_DONE ") + json.dumps({k: summ[k] for k in ("n_done", "n_failed", "n_remaining", "wall_s")}), flush=True)
sys.exit(3 if (budget_hit or remaining > 0) else 0)
if __name__ == "__main__":
main()

Xet Storage Details

Size:
23.3 kB
·
Xet hash:
e1deb3f2e38611c47d255e86710bb08eff731bc675e63ed2c1e1d236c348c0f3

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.