Repository navigation
Conversation
3a1c92d to
fc272d2
Compare
fc272d2 to
4a21de7
Compare
e9a9545 to
ec615c7
Compare
4a21de7 to
388ce59
Compare
388ce59 to
b649f4e
Compare
b649f4e to
d04cb33
Compare
d04cb33 to
ab61d1e
Compare
7246780 to
222aa11
Compare
b2dc225 to
d99acaf
Compare
d99acaf to
fe8933a
Compare
RyanPCo
left a comment
There was a problem hiding this comment.
Automated adversarial review (read-only; findings were checked by a second skeptical pass before posting): 3 low, 2 nit.
| return image | ||
|
|
||
|
|
||
| def _draw_skeleton(image, keypoints, intrinsics, edges, color): |
There was a problem hiding this comment.
low (consistency): _draw_skeleton is a second keypoint renderer, and Human.viz says there is deliberately no static-skeleton path. Move it into egomimic/utils/viz_utils.py next to _viz_keypoints_horizon_trace (sharing _N_KP and the layout checks), and update the Human.viz comment to say the replay video is the one sanctioned per-step skeleton renderer.
| self.val_image_buffer[key].clear() | ||
| self.val_counter[key] += 1 | ||
| if isinstance(images, ReplayClip): | ||
| self.val_image_buffer[key].append(images) |
There was a problem hiding this comment.
low (correctness): Replay mode caps a head at replay_chunks * H * stride frames over one concatenated clip of all its pinned episodes. For unseen_op_valid (two pins) that is 500 frames, so only the first operator's episode is ever rendered, while the yaml says one episode per operator. If a pinned episode is shorter than the cap, a chunk anchored near its end draws on the next episode's frames and rigid_fit pairs hands from two episodes. Either apply the cap per episode and don't anchor chunks across an episode boundary (carry the episode hash per frame in ReplayClip), or document that replay renders only the first pin.
| _REPLAY_OWN_KWARGS = { | ||
| "image_key", | ||
| "action_key", | ||
| "annotation_key", |
There was a problem hiding this comment.
low (correctness): Replay mode removes annotation_key from the viz kwargs, and render_replay never draws the prompt. Pinned-episode videos for configs that set it (cartesian.yaml, cotrain_lang.yaml, pi__lang.yaml) therefore silently lose the prompt overlay now that replay is the default. Carry the per-frame annotation in ReplayClip and draw it next to the GT/PRED label, or at least log once that replay ignores annotation_key.
| from egomimic.utils.type_utils import _to_numpy | ||
| from egomimic.utils.viz_utils import _prepare_viz_image | ||
|
|
||
| _KP_WIDTH = 126 |
There was a problem hiding this comment.
nit (duplication): _KP_WIDTH = 126 duplicates the layout that viz_utils derives from _N_KP. Define it as 2 * 3 * _N_KP, or export a named constant from viz_utils, so the two cannot drift.
| self._replay_seen[key] = seen | ||
| self._replay_horizon[key] = images.gt.shape[1] | ||
| # infer_stride compares steps 1-8 against up to 32 frames on. | ||
| if key not in self._replay_stride and seen >= 40: |
There was a problem hiding this comment.
nit (magic-number): seen >= 40 only works because it exceeds max(candidates) * steps (32) for infer_stride's defaults. If those defaults change, larger strides are silently skipped. Derive it from named constants in replay_viz, e.g. MIN_FRAMES_FOR_STRIDE = max(STRIDE_CANDIDATES) * STRIDE_STEPS + 1.
Each mp4 EvalVideo writes is also logged to any WandbLogger under <video dir>/<embodiment> (videos/, videos_train_viz/, videos_unseen_op_valid/), captioned with the epoch, so runs can be reviewed without copying files off the cluster. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01415567AQYskZLeSpSMsgwL
viz_mode=replay plays each action chunk twice over the frames it spans: first the ground-truth hand at each step, then the predicted one. Each step is drawn on the frame it belongs to, with the chunk mapped into that frame's camera by a rigid fit of the GT keypoints (the same hand at the same instant in both frames), so head motion needs no head pose. The 126-D keypoint layout draws both hands' 21-keypoint skeletons; other layouts fall back to the embodiment's own viz over a short trail. Chunks don't overlap and span horizon * action_stride frames; frames of an incomplete chunk carry over to the next flush. viz_max_batches must cover at least one chunk (a 100-step horizon needs ~13 batches of 8). _visualize_preds moves from HPTEvalVideo / PIEvalVideo (identical copies) into EvalVideo. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01516MaELbiPNmJzkjPGebhu
Replay becomes EvalVideo's default. It needs consecutive frames, so it runs only on a pinned video loader; a head without one keeps the overlay video, and EvalLatent stays on overlay. The replay video loader is capped at replay_chunks (5) chunks instead of viz_max_batches, which at 8 frames a batch could not cover one 100-step chunk; viz_max_batches still bounds a loader that yields no clips. action_stride defaults to None and is inferred from the GT keypoints (step k of a chunk rigidly matches frame k*stride's own step 0): data configs use 1 or 3 and cotrain mixes them under one embodiment. TrainVizEvalVideo passes the replay settings through and tells its base which mode each step is. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01516MaELbiPNmJzkjPGebhu
26995d8 to
863ec5e
Compare
fe8933a to
1228626
Compare
|
Review findings: status after the fixup pass. The fixes are squashed into this PR's commits, and the whole stack was force-pushed. Fixed
Partial
|

Each mp4 EvalVideo writes is also logged to any WandbLogger under
<video dir>/<embodiment>(videos/,videos_train_viz/,videos_unseen_op_valid/), captioned with the epoch, so runs can be reviewed without copying files off the cluster.It also adds a GT/prediction replay video mode (
egomimic/eval/replay_viz.py) and makes it the default viz, with a chunk-based cap and an inferred stride.Tests:
tests/unit/test_eval_video_upload.py,tests/unit/test_replay_viz.py.Folded in (to keep the stack under Graphite's 50-branch cap):
🤖 Generated with Claude Code
https://claude.ai/code/session_01HjCQBqQCr2igFEMR7yUovw