3D Gaussian Splatting 8편 English

스플랫 교실

흐린 점 몇백 개가 당신 사진을 따라 그립니다.

3D Gaussian Splatting(3DGS)은 장면을 흐릿한 타원체 수십만 개로 저장하고, 사진과 똑같아질 때까지 그 값을 고칩니다. 아래 장면을 끌어서 돌려 보고, 크기를 줄여 점으로 만들어 보세요.

…
끌어서 돌리기 · 휠이나 두 손가락으로 확대
1.00×
1.00×
1편 · 이론

왜 3DGS인가

컴퓨터가 장면을 기억하는 방법은 크게 넷입니다. 메시는 삼각형을 이어 붙이고, 포인트 클라우드는 색 있는 점을 흩뿌립니다. NeRF는 신경망 하나가 "이 위치, 이 방향의 색과 밀도"를 대답하게 만듭니다. 3DGS는 점마다 크기·방향·투명도를 줘서 번지는 타원체로 만들고, 사진과 똑같이 보일 때까지 그 값을 학습합니다.

신경망이 없으니 그리기는 그래픽카드가 원래 잘하는 래스터화로 끝납니다. 그래서 NeRF 계열보다 학습도 빠르고, 무엇보다 실시간으로 돌아갑니다. 대가는 용량입니다.

방법 (Mip-NeRF360 데이터셋)PSNR ↑학습 시간FPS용량
Plenoxels23.0825m49s6.792.1 GB
Instant-NGP (Big)25.597m30s9.4348 MB
Mip-NeRF360 †27.6948h0.068.6 MB
3DGS 7천 단계25.606m25s160523 MB
3DGS 3만 단계27.2141m33s134734 MB

Kerbl 외(2023) 표 1에서 옮김. 학습·속도는 논문 저자들의 A6000 GPU 기준, † 표시는 원 논문 값을 그대로 가져온 것. PSNR은 정답 사진과 얼마나 같은지 dB로 잰 값으로, 클수록 비슷합니다.

맨 위 장면은 가우시안 약 13,000개를 코드로 배치한 것입니다(학습한 장면이 아님). 점 구름처럼을 누르면 크기만 줄어든 같은 데이터가 보입니다. 점 구름과 3DGS의 차이는 "점에 크기와 모양이 있느냐" 하나입니다.

3줄 요약
  1. 3DGS = 크기·방향·투명도·색을 가진 흐린 점 수십만~수백만 개.
  2. 신경망 없이 래스터화로 그려서 실시간(논문 Mip-NeRF360 장면 134 FPS).
  3. 대신 장면 하나가 수백 MB. 압축은 8편에서.
2편 · 이론

가우시안 하나 뜯어보기

가우시안 하나가 가진 값은 다섯 가지입니다. 위치 μ(3개), 크기 s(3개), 회전 q(쿼터니언 4개), 불투명도 o(1개), 색(구면 조화 계수 48개). 다 합쳐 실수 59개입니다.

Σ = R S Sᵀ Rᵀ   ·   α(x) = o · exp(−½ (x−μ)ᵀ Σ⁻¹ (x−μ))

모양을 정하는 공분산 Σ를 바로 학습하지 않고 크기 S와 회전 R로 나눠 저장하는 이유가 있습니다. 학습 중에 Σ의 숫자를 아무렇게나 고치면 타원이 아닌 것(음수 분산)이 되어 버리기 때문입니다. S와 R로 만들면 항상 올바른 타원입니다.

아래는 화면 위로 투영된 2D 가우시안 하나입니다. 슬라이더를 움직이면 Σ가 바로 계산되고, 그림 위를 누르면 그 점의 불투명도 α를 보여 줍니다. 3σ 밖은 계산하지 않습니다(원본 구현과 같음).

색 48개는 보는 방향에 따라 색이 달라지게 하는 구면 조화(SH) 계수입니다. 0차 3개(RGB)가 기본색, 1~3차 45개가 반짝임과 반사를 흉내 냅니다. 이 페이지의 데모는 0차만 씁니다.

3줄 요약
  1. 가우시안 하나 = 위치·크기·회전·불투명도·색, 실수 59개.
  2. Σ는 크기와 회전으로 나눠 저장해야 학습 중에도 타원이 유지된다.
  3. 3σ 바깥은 0으로 보고 건너뛴다. 빠른 이유 중 하나.
3편 · 이론

미분 가능 래스터화

① 3D 타원체를 화면 위 2D 타원으로

Σ′ = J W Σ Wᵀ Jᵀ

W는 카메라 회전, J는 원근 투영을 그 점 근처에서 직선으로 근사한 야코비 행렬입니다(EWA 스플래팅, Zwicker 외 2001). 결과 Σ′의 왼쪽 위 2×2가 화면 위 타원입니다. 맨 위 뷰어도 셰이더에서 이 식을 그대로 계산합니다.

② 타일로 나누고 깊이로 정렬

화면을 16×16 픽셀 타일로 자르고, 가우시안마다 걸치는 타일을 적습니다. 그다음 (타일 번호, 깊이)를 한 번에 GPU 기수 정렬합니다. 픽셀마다 따로 정렬하지 않는 것이 핵심입니다.

③ 앞에서부터 쌓기

C = Σᵢ cᵢ αᵢ Tᵢ   ·   Tᵢ = ∏j<i (1 − αj)

T는 "아직 남은 빛"입니다. 앞의 가우시안이 가릴수록 줄어들고, 0.0001 아래로 떨어지면 그 픽셀은 더 볼 필요가 없어 멈춥니다.

맨 위 뷰어에서 깊이 정렬 켬을 눌러 꺼 보세요. 같은 가우시안을 정해진 순서로만 쌓으면 고리 앞쪽이 행성 뒤로 숨고, 행성 뒷면이 앞면을 뚫고 비칩니다. 정렬이 틀리면 그림이 틀립니다.

④ 왜 "미분 가능"인가

위 식은 전부 매끄러운 함수의 조합입니다. 그래서 픽셀 하나의 오차를 그 픽셀에 기여한 모든 가우시안의 위치·크기·회전·불투명도·색까지 거꾸로 나눠 줄 수 있습니다. 역전파 때는 T를 저장하지 않고 Tᵢ = Tᵢ₊₁ / (1 − αᵢ)로 뒤에서부터 되살립니다. 4편의 학습 데모도 같은 방법을 씁니다.

3줄 요약
  1. 투영: Σ′ = J W Σ Wᵀ Jᵀ 로 3D 타원체 → 2D 타원.
  2. 타일 + 한 번의 정렬로 픽셀마다 앞→뒤 순서를 얻는다.
  3. 합성식이 매끄러워서 오차를 모든 값까지 거꾸로 전달할 수 있다.
4편 · 이론 + 실험

학습과 밀도 제어

진짜 3DGS는 사진 수백 장과 카메라 위치로 3D 가우시안을 학습합니다. 여기서는 같은 원리를 사진 한 장(96×96)과 2D 가우시안에 적용해 브라우저에서 실제로 돌립니다. 그리기·역전파·Adam·밀도 제어가 모두 코드로 계산됩니다.

내 사진 올리기
오른쪽 칸 보기
정답 96×96
가우시안 그림 (4배 해상도)
단계
0
 
가우시안
0
 
PSNR (가우시안)
–
정답과의 차이, dB
같은 개수 모자이크
–
 
평균색 한 장
–
가장 단순한 기준
가우시안 PSNR같은 개수 네모 모자이크

올린 사진은 이 브라우저 안에서만 쓰고 저장하거나 보내지 않아요. 예시 그림은 코드로 그린 것입니다.

한 단계에서 일어나는 일

  • 가우시안을 깊이 순서로 쌓아 그림을 그린다(3편의 식).
  • 정답과 픽셀마다 비교해 오차를 잰다. 이 데모는 평균 제곱 오차, 원 논문은 L1 0.8 + D-SSIM 0.2.
  • 오차를 거꾸로 흘려 값 9개(위치 2, 크기 2, 회전 1, 불투명도 1, 색 3)의 기울기를 구한다.
  • Adam으로 조금씩 고친다. 위치 학습률은 0.4픽셀에서 0.032픽셀까지 줄인다(정한 값).

100단계마다: 밀도 제어

위치 기울기가 계속 큰 가우시안은 "여기가 아직 안 맞는다"는 신호입니다. 작으면 복제해서 둘이 나눠 맡고, 크면 둘로 분할해 크기를 1/1.6로 줄입니다. 거의 투명해진 것(불투명도 1% 미만)은 제거합니다. 원 논문은 기울기 문턱 0.0002, 이 데모는 96×96 MSE에 맞춘 0.000001(정한 값)을 씁니다.

PSNR 곡선이 100단계마다 톱니처럼 꺾이는 것은 분할 직후 새 가우시안들이 아직 자리를 못 잡아서입니다. 수십 단계 안에 이전보다 높게 회복합니다.

타원 보기로 바꾸면 처음엔 큰 타원 64개가 흐릿하게 덮고 있다가, 경계와 무늬가 있는 곳부터 작은 타원으로 쪼개지는 게 보입니다. 밀도 제어를 끄고 다시 돌리면 64개로만 버텨야 해서 PSNR이 낮게 멈춥니다.

3줄 요약
  1. 그리기 → 비교 → 역전파 → Adam, 이걸 수천 번.
  2. 기울기가 큰 곳은 복제·분할해 가우시안을 늘리고, 투명한 것은 지운다.
  3. 같은 개수의 네모 모자이크보다 훨씬 정답에 가깝다. 모양과 위치를 고를 수 있어서.
5편 · 실습

데이터 준비

3DGS 학습에는 사진과 함께 "각 사진을 어디서 어느 방향으로 찍었는지"가 필요합니다. 이걸 사진만 보고 계산해 주는 프로그램이 COLMAP입니다(Structure-from-Motion). 덤으로 나오는 듬성듬성한 점 구름이 가우시안의 출발점이 됩니다.

촬영할 때

  • 대상을 가운데 두고 한 바퀴, 높이를 바꿔 두세 바퀴. 옆 사진과 많이 겹치게.
  • 노출·초점·화이트밸런스를 고정. 사진마다 밝기가 다르면 학습이 그 차이를 "물체"로 착각합니다.
  • 움직이는 것(사람, 나뭇잎), 거울·유리, 무늬 없는 흰 벽은 피하기.
  • 동영상으로 찍었다면 초당 2장 정도로 뽑아 흔들린 장면을 뺍니다.

명령

# 동영상에서 사진 뽑기 (room/input 폴더에)
ffmpeg -i room.mp4 -vf fps=2 -qscale:v 2 room/input/%04d.jpg

# 원 저장소의 변환 스크립트: COLMAP으로 카메라 위치 계산 + 왜곡 보정
python convert.py -s room

convert.py는 graphdeco-inria/gaussian-splatting 저장소에 들어 있고, COLMAP이 설치돼 있어야 합니다. 결과로 room/images(보정된 사진)와 room/sparse(카메라·점 구름)가 생깁니다.

3줄 요약
  1. 필요한 것 = 사진 + 카메라 위치. 위치는 COLMAP이 계산.
  2. 겹치게, 노출 고정, 움직이는 것 피하기.
  3. COLMAP 점 구름이 가우시안의 첫 위치가 된다.
6편 · 실습

학습 돌려보기

CUDA GPU가 필요합니다. 원 저장소는 논문 품질로 학습하려면 VRAM 24GB를 권합니다. 해상도를 낮추면 더 작은 GPU에서도 돕니다.

# 원 구현 (graphdeco-inria)
git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive
cd gaussian-splatting
python train.py -s ../room            # 기본 30,000단계
python render.py -m output/<id>
python metrics.py -m output/<id>      # PSNR·SSIM·LPIPS

# gsplat (nerfstudio 팀, 빠르고 메모리를 덜 씀)
pip install gsplat
# gsplat 저장소의 examples 폴더에서
python simple_trainer.py default --data_dir ../room --data_factor 4 --result_dir ./out

자주 겪는 문제

증상흔한 원인해볼 것
공중에 먼지(플로터)사진이 적은 방향, 하늘·흰 벽그 방향 사진 더 찍기, 배경 가리기
전체가 흐림흔들린 사진, 카메라 위치 오차흔들린 사진 빼고 COLMAP 다시
메모리 부족해상도·가우시안 수-r 2, --data_device cpu
COLMAP 실패겹침 부족, 무늬 없는 면더 촘촘히 찍기
3줄 요약
  1. 원 구현은 train.py 한 줄, gsplat은 더 가볍다.
  2. 결과는 point_cloud.ply 한 파일.
  3. 문제의 대부분은 학습이 아니라 사진에서 온다.
7편 · 실습

웹에 올리기

학습 결과 PLY는 가우시안 하나에 실수 62개(위치 3, 법선 3, 색 48, 불투명도 1, 크기 3, 회전 4)를 담아 큽니다. 웹에서는 반짝임(SH 1~3차)을 버리고 숫자를 줄인 형식으로 바꿔 올립니다. 아래에 개수를 넣으면 크기를 계산합니다.

형식가우시안 하나파일 크기Pages 한도 25 MiB

.splat은 위치·크기 float32 각 3개, 색 RGBA 4바이트, 회전 4바이트 = 32바이트. 헤더는 빼고 계산.

  • 뷰어: antimatter15/splat(WebGL, .splat), GaussianSplats3D(three.js), PlayCanvas SuperSplat(편집·압축), Spark(three.js).
  • 올릴 곳: Cloudflare Pages는 파일 하나가 25 MiB까지라 큰 장면은 R2에 두고 뷰어만 Pages에 둡니다.
  • 정리 먼저: SuperSplat에서 공중 먼지와 배경을 잘라 내면 크기가 크게 줄어듭니다.
3줄 요약
  1. PLY 원본은 가우시안당 248바이트.
  2. .splat으로 바꾸면 32바이트, 약 8분의 1.
  3. 큰 파일은 R2, 뷰어는 Pages.
8편 · 응용

최신 흐름 한눈에

2023년 논문 이후 갈래가 빠르게 늘었습니다. 큰 줄기 여섯 개와 대표 논문입니다.

3줄 요약
  1. 품질(Mip, 2DGS), 시간(4D), 용량(압축)으로 갈래가 나뉜다.
  2. 장면마다 학습하지 않는 피드포워드 방식이 빠르게 큰다.
  3. 출발점은 모두 Kerbl 외(2023)의 같은 래스터라이저.

이 페이지의 데모는 교육용 축소판입니다. 맨 위 3D 장면은 코드로 배치한 것이고, 4편의 학습은 3D가 아니라 같은 원리를 사진 한 장에 적용한 것입니다. PSNR은 정답 그림과의 차이를 잰 값이며 품질 보증이나 확률이 아닙니다.