흐린 점 몇백 개가 당신 사진을 따라 그립니다.
3D Gaussian Splatting(3DGS)은 장면을 흐릿한 타원체 수십만 개로 저장하고, 사진과 똑같아질 때까지 그 값을 고칩니다. 아래 장면을 끌어서 돌려 보고, 크기를 줄여 점으로 만들어 보세요.
컴퓨터가 장면을 기억하는 방법은 크게 넷입니다. 메시는 삼각형을 이어 붙이고, 포인트 클라우드는 색 있는 점을 흩뿌립니다. NeRF는 신경망 하나가 "이 위치, 이 방향의 색과 밀도"를 대답하게 만듭니다. 3DGS는 점마다 크기·방향·투명도를 줘서 번지는 타원체로 만들고, 사진과 똑같이 보일 때까지 그 값을 학습합니다.
신경망이 없으니 그리기는 그래픽카드가 원래 잘하는 래스터화로 끝납니다. 그래서 NeRF 계열보다 학습도 빠르고, 무엇보다 실시간으로 돌아갑니다. 대가는 용량입니다.
| 방법 (Mip-NeRF360 데이터셋) | PSNR ↑ | 학습 시간 | FPS | 용량 |
|---|---|---|---|---|
| Plenoxels | 23.08 | 25m49s | 6.79 | 2.1 GB |
| Instant-NGP (Big) | 25.59 | 7m30s | 9.43 | 48 MB |
| Mip-NeRF360 † | 27.69 | 48h | 0.06 | 8.6 MB |
| 3DGS 7천 단계 | 25.60 | 6m25s | 160 | 523 MB |
| 3DGS 3만 단계 | 27.21 | 41m33s | 134 | 734 MB |
Kerbl 외(2023) 표 1에서 옮김. 학습·속도는 논문 저자들의 A6000 GPU 기준, † 표시는 원 논문 값을 그대로 가져온 것. PSNR은 정답 사진과 얼마나 같은지 dB로 잰 값으로, 클수록 비슷합니다.
맨 위 장면은 가우시안 약 13,000개를 코드로 배치한 것입니다(학습한 장면이 아님). 점 구름처럼을 누르면 크기만 줄어든 같은 데이터가 보입니다. 점 구름과 3DGS의 차이는 "점에 크기와 모양이 있느냐" 하나입니다.
가우시안 하나가 가진 값은 다섯 가지입니다. 위치 μ(3개), 크기 s(3개), 회전 q(쿼터니언 4개), 불투명도 o(1개), 색(구면 조화 계수 48개). 다 합쳐 실수 59개입니다.
모양을 정하는 공분산 Σ를 바로 학습하지 않고 크기 S와 회전 R로 나눠 저장하는 이유가 있습니다. 학습 중에 Σ의 숫자를 아무렇게나 고치면 타원이 아닌 것(음수 분산)이 되어 버리기 때문입니다. S와 R로 만들면 항상 올바른 타원입니다.
아래는 화면 위로 투영된 2D 가우시안 하나입니다. 슬라이더를 움직이면 Σ가 바로 계산되고, 그림 위를 누르면 그 점의 불투명도 α를 보여 줍니다. 3σ 밖은 계산하지 않습니다(원본 구현과 같음).
색 48개는 보는 방향에 따라 색이 달라지게 하는 구면 조화(SH) 계수입니다. 0차 3개(RGB)가 기본색, 1~3차 45개가 반짝임과 반사를 흉내 냅니다. 이 페이지의 데모는 0차만 씁니다.
W는 카메라 회전, J는 원근 투영을 그 점 근처에서 직선으로 근사한 야코비 행렬입니다(EWA 스플래팅, Zwicker 외 2001). 결과 Σ′의 왼쪽 위 2×2가 화면 위 타원입니다. 맨 위 뷰어도 셰이더에서 이 식을 그대로 계산합니다.
화면을 16×16 픽셀 타일로 자르고, 가우시안마다 걸치는 타일을 적습니다. 그다음 (타일 번호, 깊이)를 한 번에 GPU 기수 정렬합니다. 픽셀마다 따로 정렬하지 않는 것이 핵심입니다.
T는 "아직 남은 빛"입니다. 앞의 가우시안이 가릴수록 줄어들고, 0.0001 아래로 떨어지면 그 픽셀은 더 볼 필요가 없어 멈춥니다.
맨 위 뷰어에서 깊이 정렬 켬을 눌러 꺼 보세요. 같은 가우시안을 정해진 순서로만 쌓으면 고리 앞쪽이 행성 뒤로 숨고, 행성 뒷면이 앞면을 뚫고 비칩니다. 정렬이 틀리면 그림이 틀립니다.
위 식은 전부 매끄러운 함수의 조합입니다. 그래서 픽셀 하나의 오차를 그 픽셀에 기여한 모든 가우시안의 위치·크기·회전·불투명도·색까지 거꾸로 나눠 줄 수 있습니다. 역전파 때는 T를 저장하지 않고 Tᵢ = Tᵢ₊₁ / (1 − αᵢ)로 뒤에서부터 되살립니다. 4편의 학습 데모도 같은 방법을 씁니다.
진짜 3DGS는 사진 수백 장과 카메라 위치로 3D 가우시안을 학습합니다. 여기서는 같은 원리를 사진 한 장(96×96)과 2D 가우시안에 적용해 브라우저에서 실제로 돌립니다. 그리기·역전파·Adam·밀도 제어가 모두 코드로 계산됩니다.
올린 사진은 이 브라우저 안에서만 쓰고 저장하거나 보내지 않아요. 예시 그림은 코드로 그린 것입니다.
위치 기울기가 계속 큰 가우시안은 "여기가 아직 안 맞는다"는 신호입니다. 작으면 복제해서 둘이 나눠 맡고, 크면 둘로 분할해 크기를 1/1.6로 줄입니다. 거의 투명해진 것(불투명도 1% 미만)은 제거합니다. 원 논문은 기울기 문턱 0.0002, 이 데모는 96×96 MSE에 맞춘 0.000001(정한 값)을 씁니다.
PSNR 곡선이 100단계마다 톱니처럼 꺾이는 것은 분할 직후 새 가우시안들이 아직 자리를 못 잡아서입니다. 수십 단계 안에 이전보다 높게 회복합니다.
타원 보기로 바꾸면 처음엔 큰 타원 64개가 흐릿하게 덮고 있다가, 경계와 무늬가 있는 곳부터 작은 타원으로 쪼개지는 게 보입니다. 밀도 제어를 끄고 다시 돌리면 64개로만 버텨야 해서 PSNR이 낮게 멈춥니다.
3DGS 학습에는 사진과 함께 "각 사진을 어디서 어느 방향으로 찍었는지"가 필요합니다. 이걸 사진만 보고 계산해 주는 프로그램이 COLMAP입니다(Structure-from-Motion). 덤으로 나오는 듬성듬성한 점 구름이 가우시안의 출발점이 됩니다.
# 동영상에서 사진 뽑기 (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(카메라·점 구름)가 생깁니다.
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 실패 | 겹침 부족, 무늬 없는 면 | 더 촘촘히 찍기 |
학습 결과 PLY는 가우시안 하나에 실수 62개(위치 3, 법선 3, 색 48, 불투명도 1, 크기 3, 회전 4)를 담아 큽니다. 웹에서는 반짝임(SH 1~3차)을 버리고 숫자를 줄인 형식으로 바꿔 올립니다. 아래에 개수를 넣으면 크기를 계산합니다.
| 형식 | 가우시안 하나 | 파일 크기 | Pages 한도 25 MiB |
|---|
.splat은 위치·크기 float32 각 3개, 색 RGBA 4바이트, 회전 4바이트 = 32바이트. 헤더는 빼고 계산.
2023년 논문 이후 갈래가 빠르게 늘었습니다. 큰 줄기 여섯 개와 대표 논문입니다.
가까이 가거나 멀어질 때 생기는 깜빡임과 굵어짐을 3D 필터로 막습니다.
타원체 대신 납작한 원반을 써서 법선과 깊이가 정확해집니다. 메시 추출에 유리.
가우시안을 시간에 따라 변형하는 작은 네트워크를 붙여 동영상을 복원합니다.
덜 중요한 가우시안을 지우고, SH를 줄이고, 양자화해 용량을 크게 줄입니다.
장면마다 학습하지 않고, 미리 학습한 네트워크가 사진 두어 장에서 가우시안을 바로 뽑습니다.
이미지 생성 모델의 지식을 빌려 글이나 그림 한 장에서 3D 가우시안 물체를 만듭니다.
이 페이지의 데모는 교육용 축소판입니다. 맨 위 3D 장면은 코드로 배치한 것이고, 4편의 학습은 3D가 아니라 같은 원리를 사진 한 장에 적용한 것입니다. PSNR은 정답 그림과의 차이를 잰 값이며 품질 보증이나 확률이 아닙니다.