Index
2026-07-22 — Experiment

MetaView zero-shot exo→wrist on DROID

MetaView | 단일 이미지 NVS로 로봇 wrist 뷰를 합성할 수 있는가

TL;DR

2026-07-23 갱신: 1샘플 스모크로 낸 초기 결론 2건을 9샘플 sweep으로 정정했다. 아래는 갱신된 결론이며, 취소선은 정정 전 주장이다.
7/9
PSNR baseline 이김
5/9
LPIPS 이김 (무승부)
+0.16
ρ(회전, 성적)
−0.58
ρ(이동, 성적)
147°
회전 median
1.1%
<60° 비율

1 배경 / 목적

MetaView는 단일 이미지 + target 카메라 pose로 novel view를 만드는 diffusion 모델이다 (Qwen-Image-Edit MM-DiT 백본 + DA3 implicit geometry prior + PRoPE metric scale anchoring). 학습 데이터는 scene-level orbit NVS(DL3DV-10K / RealEstate10K / Sekai)로, 카메라가 씬 중심 구면 위를 도는 움직임이다.

질문: DROID의 exo(고정 외부) 카메라 프레임을 넣고 실제 exo→wrist 상대 pose를 주면 wrist 뷰가 나오는가? 된다면 로봇 데이터셋에서 wrist 뷰를 합성으로 늘릴 수 있어 가치가 크다.

사전 예상은 실패였다. exo→wrist는 orbit이 아니라 씬 안쪽으로 파고드는 큰 이동 + 큰 회전이고, 최종 뷰는 그리퍼가 화면을 가린다. 그래서 "되는가"보다 "어디서 깨지는가"를 측정하도록 설계했다.

2 작업 내용

데이터 규약 확인

~/Dataset/droid_full_processed/ (3162 에피소드). 각 에피소드에 exo/wrist MP4(1280×720, 49프레임)와 pose npy.

네이밍 함정: 이 폴더에서 ego_camera_pose.npy (6,)는 정적 exo 카메라, wrist_camera_poses.npy (T,6)는 per-frame wrist다. DROID-EgoX 전처리의 "ego = wrist" 관례와 반대. 파일 shape(단일 vs per-frame)으로 교차 확인했다.

포즈 규약의 진실 소스는 ~/Dataset/droid_align/src/data/io.py:

6D = (xyz, xyz-euler), Rotation.from_euler("xyz"), 미터, T_base←cam (c2w) 카메라 축 = OpenCV 광학 프레임 (x right, y down, z forward) 근거: io.py:149 의 unprojection 이 X=(u-cx)d/fx, Z=d → DA3/MetaView 와 동일하므로 축 변환 불필요

구현

MetaView의 viewmats[target_w2c, source_w2c]이고 source는 항상 단위행렬(world = 소스 카메라 프레임). 따라서 orbit 파라미터를 버리고 target 자리에 실제 상대 pose를 넣으면 된다.

T_exo←wrist = inv(euler2mat(exo_pose)) @ euler2mat(wrist_pose[t]) # wrist c2w extrinsic_target = inv(T_exo←wrist) # w2c
신규
src/droid_pose.py
신규
src/infer_droid.py
신규
scripts/run_droid_zeroshot.sh

infer_droid.py는 DA3 prior를 프레임별로 먼저 뽑고 DiT는 1회만 로드해 (frame, α) 조합에 재사용한다. 출력은 3-panel [exo | 생성 | 실제 wrist GT]src/metric.py가 요구하는 포맷이라 정량 평가로 바로 넘어갈 수 있다.

왜 α sweep인가

scale_se3(T, α)는 회전을 axis-angle 크기로, 이동을 선형으로 스케일해 identity(α=0)→실제 pose(α=1)를 보간한다. α=1 단독 실행은 실패 시 "분포 밖이라 망함" 외에 정보가 없지만, sweep은 붕괴 지점을 준다.

실패 원인 분리를 위한 검증 순서

1. GPU 없이 pose 수학 검증 — α=0이 identity, α=1이 원본과 일치, w2c@c2w=I ✓ 2. 같은 exo 프레임에 stock orbit(yaw=-30) 실행 — 파이프라인/도메인 자체 확인 3. DROID pose 경로

2번이 핵심이다. orbit이 멀쩡한데 pose 경로가 깨지면 pose 문제, 둘 다 깨지면 도메인 문제로 감별된다.

3 결과

exo→wrist pose 통계 (에피소드 4개 × 프레임 3개)

항목범위해석
이동량0.44 ~ 0.84 m씬 안쪽으로 파고듦
회전각103 ~ 165°wrist가 그리퍼를 내려다보느라 exo와 거의 마주봄. orbit 학습 범위(±60° 수준)의 약 3배

α 보간 (frame 24):

α이동회전
0.250.210 m41.2°
0.500.420 m82.4°
1.000.841 m164.7°

생성 결과 — AUTOLab+44bb9c36+2023-11-23-15h-16m-18s, frame 24

orbit baseline
Figure 1: orbit yaw=-30 baseline 성공 — [exo 입력 | 생성]. 기하학적으로 일관되고 Franka 팔·책상·물체가 전부 올바르게 이동. 파이프라인도 DROID 도메인도 정상임을 증명
alpha 0.25
Figure 2: α=0.25 (0.21m / 41°) 구조는 타당 — [exo | 생성 | 실제 wrist GT]. 오른쪽/아래로 이동하며 물체에 접근한 일관된 뷰. 다만 GT(오른쪽 근접 하향 뷰)와는 아직 멂
alpha 1.0
Figure 3: α=1.0 (0.84m / 165°) 실패 — 깨지지는 않았지만 틀렸다. 여전히 사실적·일관된 이미지지만 내용이 GT와 무관 (바닥/책상 잡동사니를 내려다봄). GT wrist는 박스 위 천 근접 + 그리퍼

정량 (생성 vs 실제 wrist GT)

조건PSNRSSIMNotes
α=0.2510.070.280baseline보다 낮음
α=1.09.620.308baseline보다 0.5dB 낮음
exo 원본 그대로 (baseline)10.140.302아무것도 안 한 것이 제일 낫다
핵심: 생성물이 exo 원본보다 GT에 더 가깝지 않다. zero-shot exo→wrist의 측정 가능한 이득은 0이다.
지표의 한계: PSNR 10dB대는 두 뷰가 애초에 거의 무관하다는 뜻이기도 하다. baseline 자체가 바닥이라 이 지표만으로는 미세한 개선을 잡아내기 어렵다. DMD/LPIPS 필요.

4 Takeaway

의미

1. 파이프라인은 완전히 동작한다. orbit baseline이 DROID 이미지에서 깨끗하게 나온 것이 결정적이다. 실패는 도메인(로봇 실내 씬) 문제도, 구현 버그도 아니고 pose가 학습 분포 밖이라서다. 이 감별을 위해 orbit baseline을 넣은 것이 설계상 제일 잘한 판단이었다.

2. 모델은 우아하게 실패한다. α=1.0에서 노이즈나 아티팩트가 아니라 "그럴듯하지만 틀린" 이미지를 낸다. 즉 극단적 pose를 받으면 조건을 무시하고 생성 prior로 도망간다. NVS로는 쓸모없지만, 백본이 로봇 씬을 이해는 하고 있다는 뜻이라 finetune 가능성의 신호다.

3. 165° 회전이 진짜 장벽으로 보인다. α=0.25(41°)에서 구조가 살아있고 α=1.0(165°)에서 무너지므로, 붕괴는 이동량보다 회전각에 걸려 있을 가능성이 높다. (미검증 가설)

4. zero-shot으로 wrist 뷰를 공짜로 얻는 길은 닫혔다. 쓰려면 finetune이 필요하다.

5 Next Steps

이번 실험의 알려진 결함

intrinsic 불일치 (가장 중요). droid_full_processed에 카메라 intrinsic이 없어 DA3가 exo에서 추정한 K를 target에도 그대로 썼다. 실제 wrist ZED는 FOV가 다르므로 오차 요인이다. raw ~/Dataset/droid/zed_calib/SN*.conf에 실제 값이 있다. α=1.0 실패의 일부가 여기서 왔을 수 있어, 결론을 확정하기 전에 배제해야 한다.

표본이 1 에피소드 1 프레임. 3-panel 이미지 3장이 전부다. 일반화 주장 불가.

PSNR/SSIM이 둔감. baseline이 10dB라 바닥에 깔려 있다. src/metric.py의 DMD나 LPIPS가 "기하가 맞아가는가"를 훨씬 잘 잡을 것. metric env 미구축.

α=0.5 미실행 (스모크에서 0.25/1.0만).

다음 작업 (우선순위)

1. 실제 wrist intrinsic 물려서 α=1.0 재실행 — 가장 싼 교란요인 제거

2. α ∈ {0.25, 0.4, 0.5, 0.6, 0.75, 1.0} 조밀 sweep × 에피소드 10개 → 붕괴 지점을 회전각의 함수로 특정. 가설: 60~90° 사이에서 무너진다

3. 회전/이동 분리 실험 — 회전만 α, 이동은 1.0 (및 반대). Takeaway 3 검증

4. metric env 구축 후 DMD/LPIPS로 재측정

5. 그 다음에야 finetune 판단. exo→wrist pair는 3162 ep × 49 frame ≈ 15만 쌍으로 충분하다

부수 발견 — repo 결함

README / pyproject.toml이 실제 의존성과 어긋난다:

문제조치
README clone Depth-Anything-3.gitcd DepthAnything3 (디렉토리명 불일치). inference.py:10 import는 DepthAnything3clone 대상을 DepthAnything3로 지정
README 레이아웃은 checkpoint-best.safetensors, HF 실제 파일은 model-2500-best.safetensors실제 이름 사용
opencv-python(GUI 빌드)이 헤드리스 노드에서 libGL.so.1로 죽음opencv-python-headless==4.11.0.86
위 설치가 numpy를 2.2.6으로 승격, DA3는 numpy<2 요구numpy==1.26.4
src/lora.py:9가 쓰는 diffusers가 README·pyproject 어디에도 없음diffusers==0.39.0 설치

env: ~/conda_envs/envs/metaview (python 3.10, torch 2.13.0+cu130). 추론 속도 40 step / 30초.

6 업데이트 (07-23) — pose 검증 + 9샘플 층화 sweep

1샘플 스모크만으로 결론을 낸 게 성급했다. 두 가지를 검증했다: (a) 내 pose가 맞는가 (w2c/c2w 뒤집기 버그는 "그럴듯하지만 틀린" 이미지라는 동일 증상을 낸다), (b) 1샘플로 일반화 불가.

6.1 pose 독립 검증 — diffusion 없이 기하 워프

DA3 metric depth로 exo를 unproject → 같은 exo→wrist 행렬로 변환 → 재투영(forward splat + z-buffer). 모델 개입 없음.

pose warp check
[exo | 기하 워프 | 실제 wrist GT]. 워프(가운데)가 GT와 같은 물체(박스 위 분홍/주황 천, 판지 상자)에 떨어진다 pose 정상. 픽셀 정렬은 안 되지만(DA3 depth 오차 + exo K 재사용) "어느 물체를 보나" 판정엔 충분
결론: 내 pose는 맞다. w2c/c2w 뒤집기 아님. → MetaView가 pose 조건을 무시한 게 확정. (앞서 열어둔 "내 pose가 틀렸을 가능성" 배제)

6.2 pose 분포 조사 (12개 랩, 1440 샘플, GPU 불필요)

percentilerotationtranslation
p158.4°0.23 m
p25128.5°0.47 m
median147.2°0.60 m
p75162.0°0.73 m
orbit 학습범위(<60°) 진입은 전체의 1.1%뿐 (<90°: 4.8%, >150°: 45.3%). 38,759 프레임 전수 스캔에서 <60°는 269개(0.69%). 12개 랩 전부 median 128~165°로 일관 — 랩별 우연이 아니라 wrist가 그리퍼를 내려다보는 하드웨어 배치의 필연. frame 24의 165°는 어려운 샘플이 아니라 p75 수준의 평범한 값이었다.

7 9샘플 층화 sweep 결과

난이도 3구간(easy <60° / mid 90° / hard 150°) × 3, 랩 분산. LPIPS(vgg) 추가 — PSNR/SSIM이 10dB 바닥에서 포화돼 둔감했으므로.

bandrottransΔPSNRΔLPIPS
easy10.3°0.73m+0.80+0.001
easy14.4°0.68m+0.27−0.006
easy16.5°0.84m+0.11+0.030
mid90.0°0.49m+0.81−0.001
mid90.1°0.60m−0.20+0.018
mid90.1°0.40m+2.51−0.042
hard150°0.34m+1.02−0.013
hard150°0.52m−0.39+0.037
hard150°0.52m+1.34−0.023

Δ = 생성 − exo원본 baseline. ΔPSNR>0 좋음, ΔLPIPS<0 좋음.

easy 10deg
easy 10.3° [exo|워프|생성|GT]. 눈으론 GT와 같은 창문/정원 방향 — 그러나 수치상 "같은 씬의 그럴듯한 뷰"일 뿐
hard 150deg
hard 150° [exo|워프|생성|GT]. easy와 성적이 구분되지 않는다

상관 분석 (n=9)

회전각 vs ΔPSNR
ρ=+0.16 (p=0.68)
이동량 vs ΔPSNR
ρ=−0.58 (p=0.10)
easy 평균 ΔPSNR
+0.39
mid 평균 ΔPSNR
+1.04
hard 평균 ΔPSNR
+0.66

8 정정된 Takeaway & 다음

2건 정정

정정 1 — "이득 0"은 1샘플 과잉단정이었다. 9샘플에서 PSNR 7/9로 baseline 이김(+0.70dB, t≈2.5). 단 LPIPS 무승부(5/9, 값 0.61~0.81로 매우 높음) — 지각적 개선은 없고 PSNR 이득은 전역 밝기/색 통계 수준.

정정 2 — "회전이 장벽" 가설이 데이터와 반대. 난이도 구간이 성적과 무상관(ρ=+0.16). 상관은 이동량에서 나옴(ρ=−0.58). 최고 +2.51dB가 이동 0.40m(최단), 최악이 0.84m.

핵심 진단: 모델이 pose를 각도 크기와 무관하게 약하게 반영한다. pose를 실제로 따른다면 10°는 거의 정확해야 하는데 easy가 hard와 구분 안 됨. "분포 밖이라 큰 각도에서 깨진다"보다 나쁜 진단 — 조건 자체가 약하게 먹힌다.

다음 (우선순위 갱신)

1. 이동량 상관을 n=30~50으로 검증 (최우선). 유의하면 "PRoPE metric anchoring이 >0.5m 이동에서 실패" 확정 → finetune 설계 직결. 회전/이동 α 독립 스케일로 교차확인

2. wrist intrinsic 보정은 우선순위 하락 — 모델이 각도 무관하게 pose를 약하게 쓴다면 intrinsic으론 안 고쳐짐

3. metric env로 DMD 측정 (기하 정합엔 LPIPS/DMD가 PSNR보다 적합)

4. finetune 판단: exo→wrist 약 15만 쌍. 단 median 147°는 orbit prior와 너무 멀어 LoRA 이상 개입 필요할 수 있음

9 업데이트 (07-31) — "연속 카메라 파라미터로 비디오 생성해서 붙이면?"

큰 한 방(0.84m/165°)을 모델이 무시하니, 궤적을 잘게 쪼개 비디오로 붙이면 다를까? 한 에피소드 49프레임을 각 프레임의 실제 pose(t)로 생성 — exo는 정적이나 씬(팔/물체)이 매 프레임 변하고 wrist pose도 변하므로 전 프레임에 실제 wrist GT가 존재한다.

8/49
gen이 baseline 이김
0.728
LPIPS gen 평균
0.714
LPIPS baseline 평균
gen이 baseline보다 평균 더 나쁘다. 독립 생성을 이어붙여도 pose 순응도가 생기지 않는다.
per-frame LPIPS curve
per-frame LPIPS. 파란 선(gen)이 회색 선(baseline)과 거의 포개져 같이 움직인다 — 두 선의 출렁임은 빨간 점선(회전각)이 아니라 씬 변화가 만든 것. gen이 pose 정보를 전혀 더하지 못했다는 직접 증거
frame strip
7개 프레임 × [exo | 워프 | MetaView | 실제 wrist GT]. 3번 열(gen)은 개별로는 그럴듯하나 프레임 간 내용이 크게 출렁이고, 4번 열(GT, 시종일관 분홍/주황 천 근접)을 따라가지 못한다. ▶ 4-panel 비디오

결론

갈래 A(독립 생성 stitch)는 correctness를 못 고친다 — 확정. 시간축으로 매끄럽게 이어붙여도 각 프레임 pose 순응도가 그대로. 결과는 "실제 wrist와 다른, 그럴듯한 대체 뷰의 비디오". 정지 9장 + 연속 49프레임 두 방식이 일치하므로 "모델이 pose를 각도 무관하게 약하게 반영"이라는 진단은 이제 단단하다.

correctness를 고칠 유일한 후보는 갈래 B(autoregressive chaining)뿐 — 작은 스텝 생성 → 생성물을 다음 source로 재투입. 단 (a)10°도 안 따라가 작은 스텝 이점 약함 (b)DA3를 생성 프레임에서 재추출해 오차 복리누적. 예측은 B도 실패. zero-shot의 마지막 시도.