Index
2026-05-12 — Progress

viz_superset.py egox_meta 비변형 리팩토링 + extrinsics 다중 소스 지원

EgoX v2 (EgoX2_exp1) | DROID Visualization | visualization/viz_superset.py

TL;DR

0
mutation 건수
3
ext_source 종류
262
frames (테스트)
~157 MB
mp4 per source

1 배경 / 목적

이전 구현(claude/260508/progress-viz_superset_wrist_render.md)에서 superset JSON으로 ext1/ext2 c2w를 불러온 뒤 egox_meta["extrinsics"][cam_id]를 직접 덮어써서 viz에 사용했다. 이 mutation 패턴이 두 가지 문제를 일으켰다:

문제 1 — 재사용 불가: egox_meta가 in-memory에서 mutate돼 동일 episode를 다른 extrinsic 소스로 비교하려면 프로세스를 다시 띄워야 했다.
문제 2 — 확장성 저하: cam2base_extrinsics.json(per-uuid 단일 serial, ext1/ext2 중 하나에만 해당)를 추가 소스로 지원하려면 mutation 패턴이 누적돼 정합성 관리가 복잡해진다.

요구사항: (1) egox_meta는 절대 건드리지 않고, override는 viz 함수에만 전달. (2) cam2base_extrinsics.json도 override 소스로 사용 가능.

2 작업 내용

① CLI: --ext_source 도입 (3종)

egox — JSON 없이 egox_meta 원본 c2w 그대로 superset — cam2base_extrinsic_superset.json (per-serial, ext1+ext2 모두) extrinsics — cam2base_extrinsics.json (single serial, source 메타 entry-level)

기본값은 superset (기존 호환성 유지).

② Mutation 제거 → override dict 분리

apply_superset_overrides()build_ext_overrides()로 교체. 반환값:

overrides = {"ext1": np.ndarray|None, "ext2": np.ndarray|None} # None → viz 시점에 egox_meta로 fallback status = {"ext1": "GT|Pred|egox|missing|none", "ext2": ...}

episode 객체에 ext_overrides, ext_status 키로 들고 다님. egox_meta는 read-only.

resolve_c2w() 헬퍼

viz 시점에 ext1/ext2이면 override가 있으면 그걸, 없으면 egox_meta의 per-frame c2w를 반환. wrist는 dynamic이라 항상 egox_meta 사용.

④ JSON 포맷 분기

superset : entry[serial] = vec6, entry[f"{serial}_source"] = "GT"|"Pred" extrinsics : entry[serial] = vec6, entry["source"] = "GT"|"Pred" # vec6 → c2w: Euler ZYX, superset_vec6_to_c2w() (두 포맷 공통)

⑤ mp4 출력 파일명 분리

wrist_view_super.mp4wrist_view_{ext_source}.mp4. 동일 uuid에 대해 3 source 결과를 한 디렉토리에 공존. panel label에 [{ext_source}:{status}] 추가.

3 결과

테스트 episode: AUTOLab+9aed6d7a+2023-11-07-17h-06m-48s (262 frames, 1280×720 × 3 panels, 10 fps, CPU ~2분)

ext_sourceext1 statusext2 statusext1 overrideext2 overridemp4 size
egoxegoxegoxFalseFalse157.0 MB
supersetGTGTTrueTrue157.2 MB
extrinsicsGTnoneTrueFalse157.1 MB
Mutation 완전 제거 확인: grep -E '\] *=' visualization/viz_superset.py | grep egox_meta 결과 0건. egox_meta length 모든 source에서 1로 유지.
Fallback 동작 확인: extrinsics 모드에서 episode JSON entry는 serial 22008760(= ext1)만 있어 ext2는 egox_meta로 자동 fallback (status=none, override=False).

4 Takeaway

의미

viz가 메타데이터를 변경하지 않으므로 동일 egox_meta 객체를 다른 분석 파이프라인과 안전하게 공유할 수 있게 됐다. 더 중요한 것은 extrinsic 소스를 CLI 한 줄로 바꾸며 동일 episode의 reproject 품질을 비교할 수 있다는 점이다. 특히 extrinsics(half-coverage)와 superset(full-coverage)이 같은 ext1에 대해 값이 다른지 픽셀 단위로 검증 가능하다 — 이는 후속 finetuning 데이터 큐레이션에서 extrinsic 소스 신뢰도 평가에 직접 활용된다.

5 Next Steps

미해결 한계: fallback panel 시각 표시

extrinsics 모드에서 ext2처럼 egox fallback이 사용된 panel은 label에 [extrinsics:none]으로만 표시된다. 실제 렌더는 egox_meta 기준이므로 사용자가 헷갈릴 여지 있음. 필요 시 label을 ext2->wrist [extrinsics:none → egox fallback]으로 확장.

다음 작업: 5개 default UUID 전체 bulk 비교

superset vs extrinsics 두 source로 5개 UUID 전체를 일괄 렌더링해서, extrinsics 단일 serial이 ext1/ext2 중 어느 쪽으로 더 자주 잡히는지 통계 정리. 후속 finetuning 데이터 큐레이션 기준 마련 목적.