CS231n Lecture 15 - 3D Vision

LECTURE 글 목록
목차

핵심 한 줄 정리

3D vision은 point cloud, mesh, voxel, implicit function처럼 서로 다른 장단점을 가진 표현 위에서 geometry와 appearance를 학습하는 문제이며, neural implicit field와 differentiable rendering은 2D 관측만으로도 3D scene을 복원하고 새로운 시점의 image를 합성할 수 있게 한다.

반드시 기억할 개념

3D에서는 representation 선택부터 문제이다

2D image는 보통 일정한 grid 위의 pixel tensor로 표현한다. 반면 3D object는 geometry뿐 아니라 texture, material, lighting에 따른 appearance까지 포함하며, 이를 표현하는 표준적인 형식이 하나로 정해져 있지 않다.

같은 object도 다음과 같이 여러 방식으로 나타낼 수 있다.

  • Point cloud: surface에서 sampling한 3D point 집합이다.
  • Polygon mesh: vertex와 그 연결 관계인 face를 함께 저장한다.
  • Parametric surface: 낮은 차원의 parameter를 3D coordinate로 mapping한다.
  • Implicit surface: 3D coordinate를 넣었을 때 surface와의 관계를 반환하는 function으로 표현한다.
  • Voxel: 3D 공간을 regular grid로 나누어 occupancy나 density를 저장한다.

표현 방식에 따라 쉬운 연산과 어려운 연산이 달라진다. 따라서 3D representation은 단순한 file format이 아니라 model architecture, loss function, rendering 비용까지 결정하는 설계 선택이다.

Representation저장 내용강점한계
Point cloud3D point 집합sensor output과 가깝고 topology 제약이 없음연결 관계와 매끄러운 surface가 없음
Meshvertex와 face정확한 surface와 효율적인 renderingirregular connectivity를 neural network가 다루기 어려움
Parametric surfaceparameter-to-coordinate mappingpoint sampling과 smooth surface 생성이 쉬움복잡한 topology를 하나의 mapping으로 표현하기 어려움
Implicit functioncoordinate-to-property mappinginside/outside query와 composition이 쉬움surface point를 직접 얻으려면 별도 extraction이 필요함
Voxelregular 3D grid3D convolution을 바로 적용할 수 있음resolution에 따라 memory와 computation이 cubic하게 증가함

Geometry와 appearance

Geometry는 object의 shape와 공간적 구조를 나타낸다. Appearance는 특정 위치가 어떤 color와 material을 가지며, viewing direction과 lighting에 따라 어떻게 보이는지를 나타낸다.

전통적인 shape representation은 주로 geometry에 초점을 맞춘다. NeRF 같은 neural rendering model은 coordinate에서 density와 radiance를 함께 예측하므로 geometry와 appearance를 하나의 field 안에 표현한다.

이 구분이 중요한 이유는 같은 geometry도 material, illumination, viewpoint에 따라 전혀 다르게 보일 수 있기 때문이다. 반대로 여러 2D image에서 일관된 geometry를 찾으려면 viewpoint에 따른 appearance 변화를 분리해 이해해야 한다.

Point cloud

Point cloud는 가장 단순한 3D representation이다. 강의의 convention을 따르면 NN개 point는 다음과 같은 3×N3 \times N matrix로 저장할 수 있다.

P=[x1x2xNy1y2yNz1z2zN]P = \begin{bmatrix} x_1 & x_2 & \cdots & x_N \\ y_1 & y_2 & \cdots & y_N \\ z_1 & z_2 & \cdots & z_N \end{bmatrix}

각 column pi=(xi,yi,zi)Tp_i=(x_i,y_i,z_i)^T는 3D 공간의 한 point이다. 구현에서는 같은 정보를 N×3N \times 3 tensor로 저장하기도 한다.

Depth sensor, LiDAR, 3D scanner에서 얻는 raw output이 point cloud인 경우가 많다. Point에 surface normal nin_i까지 붙이면 위치와 surface orientation을 함께 표현할 수 있으며, 이런 oriented point를 surfel이라고 부르기도 한다.

si=(pi,ni)s_i = (p_i,n_i)

Surface normal은 lighting과 surface의 상호작용을 계산할 때 필요하다. 다만 point cloud 자체에는 point 사이의 connectivity가 없으므로, 두 point가 같은 surface 위에서 이웃하는지 바로 알 수 없다.

Point cloud의 주요 한계는 다음과 같다.

  • Point ordering에 의미가 없다.
  • Sampling density가 object 부위마다 다를 수 있다.
  • Hole, noise, outlier가 포함될 수 있다.
  • Topology와 continuous surface가 명시되지 않는다.
  • Smooth rendering, subdivision, simplification 같은 surface operation이 바로 정의되지 않는다.

예를 들어 같은 위치의 point 집합이라도 어떤 point를 연결하느냐에 따라 torus와 서로 분리된 ring처럼 다른 topology가 될 수 있다. Coordinate만으로는 이 차이를 완전히 복원할 수 없다.

Polygon mesh

Polygon mesh는 vertex 집합과 face 집합으로 surface를 표현한다.

M=(V,F)\mathcal{M} = (V,F) V={vi}i=1N,viR3V = \{v_i\}_{i=1}^{N}, \qquad v_i \in \mathbb{R}^3

FF는 어떤 vertex들이 하나의 polygon을 이루는지 나타낸다. Triangle mesh라면 각 face는 세 vertex index로 구성된다.

fj=(i1,i2,i3)f_j = (i_1,i_2,i_3)

Mesh는 point cloud에 없던 connectivity와 surface를 제공하므로 rendering, animation, subdivision, simplification에 적합하다. 게임과 graphics engine에서 널리 사용하는 이유도 이 때문이다.

반면 mesh는 regular grid가 아니다. Vertex마다 이웃 개수가 다를 수 있고 face의 크기와 모양도 일정하지 않다. 강의에서는 2,800만 vertex와 5,600만 triangle을 가진 sculpture scan처럼 매우 큰 mesh를 예로 들었다. 이 정도 규모의 irregular structure를 고정된 kernel을 사용하는 일반 CNN에 바로 넣기는 어렵다.

Mesh processing에서는 triangle 크기와 sampling density를 고르게 만드는 remeshing, detail을 늘리는 subdivision, 계산량을 줄이는 simplification 등이 중요하다.

Parametric representation

Parametric curve와 surface는 낮은 차원의 parameter domain을 3D coordinate로 mapping한다.

Curve는 보통 하나의 parameter를 사용한다.

c(t):RR3c(t) : \mathbb{R} \rightarrow \mathbb{R}^3

2D unit circle은 다음처럼 쓸 수 있다.

c(t)=(cost,sint)c(t) = (\cos t,\sin t)

Surface는 두 parameter를 사용한다.

s(u,v):R2R3s(u,v) : \mathbb{R}^2 \rightarrow \mathbb{R}^3

Unit sphere의 한 parameterization은 다음과 같다.

s(u,v)=(sinucosv,sinusinv,cosu)s(u,v) = (\sin u\cos v,\sin u\sin v,\cos u)

여기서 uuvv를 변화시키면 sphere surface의 point를 직접 얻는다. 이처럼 parametric representation은 point sampling이 쉽고 smooth surface를 만들기 좋다. Bezier curve와 Bezier surface는 control point 몇 개로 더 유연한 shape를 정의한다.

다만 하나의 parameter domain으로 복잡한 topology를 가진 object 전체를 덮기는 어렵다. Sphere와 같은 단순한 surface는 closed form으로 쓸 수 있지만, chair나 animal shape 전체를 표현하는 mapping은 직접 작성하기 어렵다. 뒤에서 보는 AtlasNet은 이 mapping을 neural network로 학습한다.

Explicit representation과 implicit representation

Point cloud, mesh, parametric surface는 surface point를 직접 제공한다는 의미에서 explicit representation으로 볼 수 있다. 반면 implicit representation은 3D coordinate를 function에 넣어 그 위치가 surface와 어떤 관계인지 묻는다.

f:R3Rf : \mathbb{R}^3 \rightarrow \mathbb{R}

Surface는 보통 function의 zero level set으로 정의한다.

S={xR3f(x)=0}\mathcal{S} = \{x\in\mathbb{R}^3 \mid f(x)=0\}

Unit sphere는 다음 function으로 표현할 수 있다.

f(x,y,z)=x2+y2+z21f(x,y,z) = x^2+y^2+z^2-1

이때 다음 sign convention을 사용할 수 있다.

f(x)<0x is insidef(x)<0 \quad\Longrightarrow\quad x\text{ is inside} f(x)=0x is on the surfacef(x)=0 \quad\Longrightarrow\quad x\text{ is on the surface} f(x)>0x is outsidef(x)>0 \quad\Longrightarrow\quad x\text{ is outside}

Explicit representation은 parameter를 sampling하면 surface point가 바로 나오지만, arbitrary query point가 closed object의 내부인지 외부인지 판단하기가 상대적으로 어렵다. Implicit representation은 function evaluation 한 번으로 inside/outside를 확인할 수 있지만, f(x)=0f(x)=0을 만족하는 surface point를 직접 얻으려면 root finding이나 surface extraction이 필요하다.

Signed Distance Function

Signed Distance Function, SDF는 point에서 가장 가까운 surface까지의 distance에 inside/outside sign을 붙인 implicit representation이다.

d(x)=s(x)minySxy2d(x) = s(x) \min_{y\in\mathcal{S}} \lVert x-y\rVert_2

여기서는 inside에서 음수, outside에서 양수가 되도록 s(x)s(x)를 정한다. Surface에서는 d(x)=0d(x)=0이다.

Occupancy function이 inside/outside만 알려 주는 반면 SDF의 절댓값은 surface까지 얼마나 떨어져 있는지도 알려 준다. 따라서 surface normal, collision, smooth blending 등에 더 풍부한 정보를 제공한다. 충분히 smooth한 영역에서는 SDF gradient가 surface normal 방향을 나타낸다.

n(x)=d(x)d(x)2n(x) = \frac{\nabla d(x)}{\lVert\nabla d(x)\rVert_2}

Implicit function의 composition

Implicit representation은 여러 primitive를 조합하기 쉽다. Inside에서 음수를 쓰는 SDF convention에서 두 field ffgg의 기본 Constructive Solid Geometry, CSG operation은 다음처럼 나타낼 수 있다.

funion(x)=min(f(x),g(x))f_{\text{union}}(x) = \min(f(x),g(x)) fintersection(x)=max(f(x),g(x))f_{\text{intersection}}(x) = \max(f(x),g(x)) fdifference(x)=max(f(x),g(x))f_{\text{difference}}(x) = \max(f(x),-g(x))

이런 union, intersection, difference를 반복하면 simple primitive에서 복잡한 CAD shape를 구성할 수 있다. Hard min과 max 대신 smooth approximation을 사용하면 두 shape가 부드럽게 이어지는 blend도 만들 수 있다.

Level set과 voxel

복잡한 implicit function을 매번 계산하기 어렵다면 regular 3D grid의 coordinate마다 function 값을 미리 저장할 수 있다.

Fijk=f(xi,yj,zk)F_{ijk} = f(x_i,y_j,z_k)

인접한 grid value의 sign이 바뀌는 곳 사이에는 f(x)=0f(x)=0인 surface가 존재한다. Marching Cubes 같은 algorithm은 이 sign change를 이용해 implicit grid에서 triangle mesh를 추출한다.

Distance 값을 모두 저장하지 않고 inside/outside만 이산화하면 voxel occupancy grid가 된다.

Vijk{0,1}V_{ijk} \in \{0,1\}

강의에서는 100×100×100100\times100\times100 grid를 예로 들었다. 이 경우 총 voxel 수는 다음과 같다.

1003=1,000,000100^3 = 1{,}000{,}000

Voxel은 pixel의 3D counterpart처럼 regular tensor이므로 3D convolution을 바로 적용할 수 있다. 그러나 한 축의 resolution이 RR이면 저장량과 dense convolution 비용은 대략 R3R^3에 비례한다.

memory=O(R3)\text{memory} = O(R^3)

Resolution을 두 배로 올리면 voxel 수는 여덟 배가 된다.

(2R)3=8R3(2R)^3 = 8R^3

대부분의 3D 공간이 empty이거나 object 내부의 균일한 영역이라는 점도 낭비이다. Surface 근처에만 fine cell을 두고 나머지 공간에는 큰 cell을 두는 octree는 이 문제를 줄인다. 강의의 예에서는 dense voxel이 64364^3 정도를 다룰 때 adaptive octree를 이용해 2563256^3 수준의 detail을 표현했다.

%% title: 3D Representation별 Query와 사용 방식
%% caption: 같은 3D object도 surface를 직접 저장할 수도, coordinate에서 property를 묻는 function으로 저장할 수도 있으며 representation이 가능한 연산과 비용을 결정한다.
flowchart TB
    object["3D Object / Scene"]
    object --> points["Point Cloud<br/>unordered xyz samples"]
    object --> mesh["Mesh<br/>vertices + faces"]
    object --> parametric["Parametric Surface<br/>(u,v) → xyz"]
    object --> implicit["Implicit Field<br/>xyz → occupancy / SDF"]
    object --> voxel["Voxel Grid<br/>regular D × H × W"]
    points --> setnet["Set Model / PointNet"]
    mesh --> render["Rasterization / Geometry Ops"]
    parametric --> sample["Direct Surface Sampling"]
    implicit --> extract["Query + Marching Cubes"]
    voxel --> conv3d["3D Convolution"]

3D data의 규모 문제

3D learning은 representation뿐 아니라 data 부족에도 크게 영향을 받는다. 2D image는 web에서 대규모로 수집할 수 있지만, 정확한 3D geometry는 직접 modeling하거나 여러 view를 촬영하고 reconstruction해야 한다.

강의에서 제시한 규모 변화는 다음과 같다.

  • 초기 Princeton Shape Benchmark는 180 category, 약 1,800 model 규모였다.
  • ShapeNet 전체는 약 300만 model이며, 자주 사용하는 ShapeNetCore는 약 5만 model과 55 category로 구성된다.
  • Objaverse와 Objaverse-XL은 대략 100만, 1,000만 단위의 synthetic 3D asset으로 규모를 키웠다.
  • Real object와 indoor scene scan은 수집 비용 때문에 synthetic asset보다 훨씬 적다.

이 차이 때문에 3D model을 처음부터 학습하는 것만큼, 대규모 2D image·video model의 prior를 rendering을 통해 3D로 옮기는 방법이 중요하다.

3D vision의 주요 task

3D representation을 사용하는 task는 크게 다음과 같이 나눌 수 있다.

  • Recognition: shape classification, part segmentation, scene understanding이다.
  • Reconstruction: image, video, depth, LiDAR에서 3D geometry와 appearance를 복원한다.
  • Completion과 repair: partial scan의 누락된 영역을 채운다.
  • Generation: text나 image condition에서 object와 scene을 생성한다.
  • Editing과 animation: geometry, texture, articulation을 수정한다.
  • Multimodal fusion: RGB, depth, LiDAR, tactile, text를 함께 사용한다.

이 task들을 잇는 핵심 도구가 differentiable rendering이다. 3D representation을 2D image로 render하는 과정이 미분 가능하면, rendered image와 target image의 차이를 3D parameter까지 backpropagation할 수 있다.

θ3D representationrendererI^L(I^,I)\theta \longrightarrow \text{3D representation} \longrightarrow \text{renderer} \longrightarrow \hat{I} \longrightarrow \mathcal{L}(\hat{I},I) Lθ=LI^I^θ\frac{\partial\mathcal{L}}{\partial\theta} = \frac{\partial\mathcal{L}}{\partial\hat{I}} \frac{\partial\hat{I}}{\partial\theta}

이 구조 덕분에 직접적인 3D ground truth가 없더라도 여러 2D view를 supervision으로 사용할 수 있다.

Multi-view CNN

초기 deep 3D recognition의 실용적인 방법은 3D object를 여러 camera view에서 2D image로 render한 뒤, pretrained 2D CNN으로 처리하는 것이었다.

각 view IkI_k에서 feature를 추출한다.

hk=ϕ(Ik)h_k = \phi(I_k)

그다음 view 순서에 덜 민감한 pooling으로 하나의 object feature를 만든다.

h=pool(h1,h2,,hK)h = \operatorname{pool} \left( h_1,h_2,\ldots,h_K \right) y^=g(h)\hat{y} = g(h)

이 방식은 대규모 image data로 pretrained된 CNN을 활용할 수 있다는 장점이 있다. 반면 camera placement와 rendering quality에 따라 성능이 달라지고, 3D connectivity와 metric structure를 직접 처리하지는 않는다.

Image와 video foundation model이 3D dataset보다 훨씬 큰 data로 학습된 현재에는 이 multi-view 접근이 다시 중요해지고 있다.

Volumetric CNN과 3D GAN

Voxel은 regular grid이므로 2D convolution을 3D convolution으로 확장할 수 있다. 3D kernel은 height와 width뿐 아니라 depth 방향으로도 이동한다.

Input channel까지 포함한 voxel tensor를 다음처럼 둘 수 있다.

XRCin×D×H×WX \in \mathbb{R}^{C_{\text{in}}\times D\times H\times W}

3D convolution kernel의 shape는 다음과 같다.

KRCout×Cin×kD×kH×kWK \in \mathbb{R}^{C_{\text{out}}\times C_{\text{in}}\times k_D\times k_H\times k_W}

이를 이용해 voxel classification, reconstruction, generation을 구현할 수 있다. GAN의 generator가 image pixel 대신 voxel occupancy를 출력하면 3D GAN이 된다.

또한 generated voxel을 depth image로 render하고 image adversarial loss를 추가할 수 있다. Shape realism은 3D loss로, rendered appearance는 2D loss로 제약하는 방식이다. Shape, viewpoint, texture latent를 분리하면 viewpoint 변경이나 texture transfer 같은 control도 가능하다.

Dense voxel의 cubic cost 때문에 높은 resolution에서 세밀한 surface를 만들기 어렵다는 한계는 그대로 남는다.

PointNet과 permutation invariance

Point cloud는 순서가 없는 set이다. 같은 point를 다른 순서로 나열해도 같은 geometry이므로 network output도 같아야 한다.

f(p1,p2,,pN)=f(pπ(1),pπ(2),,pπ(N))f(p_1,p_2,\ldots,p_N) = f(p_{\pi(1)},p_{\pi(2)},\ldots,p_{\pi(N)})

π\pi는 point index의 임의 permutation이다.

PointNet은 모든 point에 같은 MLP hh를 적용한 뒤 symmetric function으로 feature를 aggregate한다.

ui=h(pi)u_i = h(p_i) u=MAXi=1Nuiu = \operatorname{MAX}_{i=1}^{N} u_i y^=γ(u)\hat{y} = \gamma(u)

Max, sum, mean 같은 symmetric aggregation은 input order가 바뀌어도 결과가 같다. 이것이 PointNet의 핵심이다.

Shared MLP는 각 point를 독립적으로 embedding하고 global max pooling은 각 feature dimension에서 가장 강한 response를 선택한다. PointNet++는 local neighborhood를 계층적으로 묶어 fine geometry를 더 잘 포착한다. Point를 graph node로 보고 spatially 가까운 point를 edge로 연결하면 Graph Neural Network 방식으로도 확장할 수 있다.

Permutation invariance와 sampling invariance는 같은 개념이 아니다. Symmetric pooling은 순서 변화에는 정확히 invariant하지만, point의 위치나 sampling density 자체가 달라지면 output도 달라질 수 있다. 다양한 sampling에 대한 robustness는 training augmentation, local aggregation, density-aware method로 보완해야 한다.

%% title: PointNet의 Permutation-Invariant 구조
%% caption: 모든 point에 같은 MLP를 적용하고 point 축에서 symmetric max pooling하면 input 순서가 바뀌어도 같은 global representation을 얻는다.
flowchart LR
    p1["Point p₁<br/>(x,y,z)"] --> mlp1["Shared MLP h"]
    p2["Point p₂<br/>(x,y,z)"] --> mlp2["Shared MLP h"]
    pn["Point pₙ<br/>(x,y,z)"] --> mlpn["Shared MLP h"]
    mlp1 --> max["Symmetric MAX<br/>over points"]
    mlp2 --> max
    mlpn --> max
    max --> global["Global Shape Feature"]
    global --> head["Classification / Segmentation Head"]

Point cloud distance

Image는 같은 pixel 위치끼리 비교하면 되지만 point cloud에는 고정된 correspondence가 없다. 따라서 generated point set과 target point set을 비교하려면 set distance가 필요하다.

두 point set을 PPQQ라 할 때 symmetric Chamfer distance는 다음과 같다.

dCD(P,Q)=1PpPminqQpq22+1QqQminpPqp22d_{\text{CD}}(P,Q) = \frac{1}{|P|} \sum_{p\in P} \min_{q\in Q} \lVert p-q\rVert_2^2 + \frac{1}{|Q|} \sum_{q\in Q} \min_{p\in P} \lVert q-p\rVert_2^2

양방향 nearest-neighbor distance를 사용하므로 두 set이 서로를 얼마나 잘 cover하는지 측정한다. 계산이 비교적 간단하지만 여러 point가 같은 nearest neighbor에 몰릴 수 있어 one-to-one correspondence를 보장하지 않는다.

두 set의 point 수가 같을 때 Earth Mover’s Distance, EMD는 가능한 bijection 중 전체 이동 cost가 최소인 matching을 찾는다.

dEMD(P,Q)=minϕ:PQ1PpPpϕ(p)2d_{\text{EMD}}(P,Q) = \min_{\phi:P\rightarrow Q} \frac{1}{|P|} \sum_{p\in P} \lVert p-\phi(p)\rVert_2

ϕ\phi는 one-to-one matching이다. EMD는 global assignment를 고려해 correspondence가 더 균형적이지만 exact computation이 더 비싸다. 두 distance는 미분 가능한 형태 또는 approximation으로 구현해 point cloud generator를 학습할 수 있다.

AtlasNet과 learned parametric surface

AtlasNet은 복잡한 parametric mapping을 closed-form equation 대신 MLP로 학습한다. 2D patch coordinate (u,v)(u,v)와 input의 latent shape code zz를 넣어 3D point를 출력한다.

fθk:R2×RdzR3f_{\theta_k} : \mathbb{R}^2 \times \mathbb{R}^{d_z} \rightarrow \mathbb{R}^3 p=fθk(u,v,z)p = f_{\theta_k}(u,v,z)

하나의 patch만으로 복잡한 topology를 표현하기 어려우므로 여러 mapping을 함께 사용한다.

S^=k=1K{fθk(u,v,z)(u,v)[0,1]2}\hat{\mathcal{S}} = \bigcup_{k=1}^{K} \left\{ f_{\theta_k}(u,v,z) \mid (u,v)\in[0,1]^2 \right\}

각 network는 종이 한 장을 접듯 2D patch를 3D surface로 변형하고, 여러 patch가 object 전체를 덮는다. Voxel보다 resolution 제약이 적고 point cloud보다 smooth surface를 제공하지만, patch 사이 seam과 overlap을 관리해야 한다.

Deep implicit function

Neural network 자체를 coordinate-based implicit function으로 사용할 수 있다. Latent shape code zz와 query point xx를 넣고 occupancy나 SDF를 예측한다.

Fθ(x,z)o(x)F_\theta(x,z) \rightarrow o(x)

Occupancy network라면 o(x)o(x)는 point가 object 내부일 probability이다.

o(x)[0,1]o(x) \in [0,1]

SDF network라면 scalar signed distance를 출력한다.

Fθ(x,z)d(x)F_\theta(x,z) \rightarrow d(x)

이 접근은 dense voxel을 input으로 처리하는 것이 아니라 필요한 coordinate에서 network를 query한다. 따라서 representation resolution이 고정 grid에 직접 묶이지 않고 continuous coordinate에서 surface를 표현할 수 있다.

Training에는 query point와 그 point의 occupancy 또는 SDF label이 필요하다. Inference에서는 많은 coordinate를 평가한 뒤 zero level set을 Marching Cubes로 추출할 수 있다. Dense grid를 저장하지 않아도 되지만 고해상도 surface extraction에는 여전히 많은 network query가 필요하다.

Neural Radiance Field

Neural Radiance Field, NeRF는 neural implicit function을 geometry뿐 아니라 appearance까지 확장한다. Query position x=(x,y,z)x=(x,y,z)와 viewing direction dd를 입력받아 volume density σ\sigma와 color cc를 출력한다.

Fθ(x,d)(σ,c)F_\theta(x,d) \rightarrow (\sigma,c) σ0,c[0,1]3\sigma \ge 0, \qquad c \in [0,1]^3

Density는 해당 위치가 ray의 light를 얼마나 가리는지 나타내며 geometry를 암묵적으로 표현한다. Color가 viewing direction에도 의존하게 하면 specular reflection처럼 보는 방향에 따라 달라지는 appearance를 모델링할 수 있다.

Camera origin oo에서 direction dd로 나가는 ray는 다음과 같다.

r(t)=o+tdr(t) = o+td

NeRF는 ray 위의 여러 tit_i에서 point를 sampling하고 각 위치의 density와 color를 예측한다.

(σi,ci)=Fθ(r(ti),d)(\sigma_i,c_i) = F_\theta(r(t_i),d)
%% title: NeRF의 Ray Sampling과 Pixel Rendering
%% caption: Camera ray 위의 여러 3D position을 neural field에 query해 density와 color를 얻고, transmittance를 고려한 alpha compositing으로 하나의 pixel color를 만든다.
flowchart LR
    camera["Camera Origin o<br/>Ray Direction d"] --> samples["Sample Points<br/>xᵢ = o + tᵢd"]
    samples --> field["NeRF MLP Fθ(xᵢ, d)"]
    field --> density["Density σᵢ"]
    field --> color["Color cᵢ"]
    density --> weights["Transmittance × Alpha<br/>wᵢ"]
    color --> composite["Volume Rendering<br/>Ĉ(r) = Σ wᵢcᵢ"]
    weights --> composite
    composite --> pixel["Rendered Pixel"]
    target["Observed Pixel"] --> loss["Photometric Loss"]
    pixel --> loss
    loss -. "backpropagation" .-> field

Differentiable volume rendering

Sample interval을 δi=ti+1ti\delta_i=t_{i+1}-t_i라 하면 point ii에서 light가 흡수될 probability는 다음과 같다.

αi=1exp(σiδi)\alpha_i = 1-exp(-\sigma_i\delta_i)

앞선 sample들을 통과해 ii번째 sample까지 도달할 transmittance는 다음과 같다.

Ti=exp(j<iσjδj)T_i = \exp \left( -\sum_{j<i} \sigma_j\delta_j \right)

같은 값을 alpha의 곱으로 쓸 수도 있다.

Ti=j<i(1αj)T_i = \prod_{j<i} (1-\alpha_j)

최종 pixel color는 각 sample color의 alpha-composited sum이다.

C^(r)=i=1KTiαici\hat{C}(r) = \sum_{i=1}^{K} T_i\alpha_i c_i

TiαiT_i\alpha_i는 camera ray가 앞의 모든 sample을 통과한 뒤 정확히 ii번째 sample에서 color를 얻을 weight이다. 앞쪽 density가 크면 뒤쪽 sample의 contribution은 작아진다.

모든 항이 미분 가능하므로 rendered color와 observed pixel color 사이의 reconstruction loss로 neural field를 학습할 수 있다.

Lrender=rRC^(r)C(r)22\mathcal{L}_{\text{render}} = \sum_{r\in\mathcal{R}} \left\lVert \hat{C}(r)-C(r) \right\rVert_2^2

R\mathcal{R}은 training image에서 sampling한 camera ray 집합이다. Gradient는 volume rendering equation을 거쳐 각 sample의 color와 density, 다시 network parameter θ\theta로 전달된다.

NeRF가 2D image로 3D를 학습하는 방식

기존 deep implicit geometry는 query point의 occupancy나 SDF ground truth가 필요했다. NeRF는 known camera pose를 가진 여러 2D image를 supervision으로 사용한다.

  1. Training image에서 pixel과 camera ray를 sampling한다.
  2. Ray 위의 3D point들을 sampling한다.
  3. NeRF에서 density와 color를 query한다.
  4. Volume rendering으로 predicted pixel color를 계산한다.
  5. Observed pixel과의 차이를 줄이도록 network를 update한다.

여러 camera view를 동시에 설명하려면 서로 일관된 3D density와 appearance field가 필요하다. 학습 후 새로운 camera origin과 direction으로 ray를 만들면 training에 없던 viewpoint의 image를 render할 수 있다. 이것이 novel-view synthesis이다.

NeRF의 핵심 변화는 다음 두 가지이다.

  • Geometry만 표현하던 implicit field를 density와 radiance field로 확장했다.
  • Differentiable volume rendering을 사용해 3D supervision 대신 2D image에서 학습한다.

NeRF의 계산 비용

Vanilla NeRF는 image의 각 ray마다 많은 3D sample을 만들고 각 sample에서 MLP를 평가한다. Empty space의 point도 반복해서 query하므로 training과 rendering이 느리다.

network evaluationsNrays×Nsamples per ray\text{network evaluations} \approx N_{\text{rays}} \times N_{\text{samples per ray}}

Hierarchical sampling, occupancy grid, hash-grid encoding 등은 empty space query를 줄이거나 field evaluation을 빠르게 하는 방향의 개선이다. Lecture의 큰 흐름에서 보면 dense voxel의 empty-space 낭비가 neural field의 repeated query 형태로 다시 나타난 셈이다.

3D Gaussian Splatting

3D Gaussian Splatting은 scene을 continuous MLP가 아니라 학습 가능한 3D Gaussian primitive 집합으로 나타낸다. 각 Gaussian은 대략 다음 parameter를 가진다.

Gi=(μi,Σi,αi,ci)G_i = (\mu_i,\Sigma_i,\alpha_i,c_i)

μiR3\mu_i\in\mathbb{R}^3는 center, ΣiR3×3\Sigma_i\in\mathbb{R}^{3\times3}는 shape와 orientation을 나타내는 covariance, αi\alpha_i는 opacity, cic_i는 color 또는 view-dependent appearance coefficient이다.

Gaussian density의 형태는 다음과 같다.

Gi(x)exp(12(xμi)TΣi1(xμi))G_i(x) \propto \exp \left( -\frac{1}{2} (x-\mu_i)^T \Sigma_i^{-1} (x-\mu_i) \right)

각 3D Gaussian을 camera plane에 projection하면 2D ellipse가 된다. Renderer는 pixel에 영향을 주는 Gaussian만 depth 순서로 alpha compositing한다. Gaussian의 위치를 알고 있으므로 전체 3D 공간을 균일하게 sampling하거나 모든 ray point에서 MLP를 호출할 필요가 없다.

3D Gaussian Splatting은 NeRF의 neural implicit representation과 달리 명시적인 Gaussian primitive 집합을 학습하는 explicit representation에 가깝다. Point cloud의 sparse spatial support와 differentiable volumetric compositing의 장점을 결합한 것으로 이해할 수 있다.

강의의 비교에서는 PSNR과 SSIM으로 측정한 rendering quality가 당시 NeRF와 비슷하면서, Gaussian Splatting은 약 150 FPS를 보였고 vanilla NeRF는 image 한 장에 약 20초가 걸리는 예가 제시되었다. 이 숫자는 hardware와 implementation에 따라 달라지지만, 핵심은 empty-space query를 줄여 rendering 속도를 크게 높였다는 점이다.

%% title: 3D Gaussian Splatting Rendering Pipeline
%% caption: 학습 가능한 3D Gaussian을 camera plane에 투영하고, screen-space ellipse를 depth 순서로 alpha blending해 image를 렌더링한다.
flowchart LR
    gaussians["3D Gaussians<br/>mean · covariance · opacity · color"] --> project["Project with Camera"]
    project --> ellipses["2D Screen-Space Ellipses"]
    ellipses --> tiles["Tile Culling + Depth Sort"]
    tiles --> blend["Front-to-Back<br/>Alpha Blending"]
    blend --> image["Rendered Image"]
    target["Target View"] --> loss["Image Loss"]
    image --> loss
    loss -. "optimize" .-> gaussians

3D structure는 local geometry만으로 충분하지 않다

Point, mesh, SDF, radiance field는 local geometry와 appearance를 자세히 표현하지만 symmetry, repetition, part relation 같은 high-level structure를 직접 나타내지는 않는다.

Chair를 예로 들면 seat, back, base, leg이라는 part hierarchy가 있고, 왼쪽과 오른쪽 leg 사이에는 symmetry와 alignment constraint가 있다. Indoor scene에서는 bed가 wall 가까이에 있고 chair가 table 주변에 놓이는 식의 object relation이 있다.

이를 나타내기 위한 representation은 다음과 같다.

  • Primitive set: box, cylinder 같은 simple part의 조합이다.
  • Part graph: node는 part, edge는 symmetry나 adjacency relation이다.
  • Hierarchical graph: object, part, subpart를 여러 level로 표현한다.
  • Shape program: loop, repetition, transform 같은 명령으로 geometry를 생성한다.

Neural encoder와 decoder가 이런 graph나 program을 생성하도록 학습하면 local detail뿐 아니라 구조적 constraint를 유지할 수 있다. 최근에는 language model이 semantic structure를 반영한 shape program을 만들고, neural implicit field가 각 part의 세부 geometry를 채우는 조합도 가능하다.

3D representation의 발전 흐름

강의에서 본 흐름은 특정 representation 하나가 다른 모든 방식을 대체했다는 이야기가 아니다. 각 방식의 약점을 다음 방식이 보완해 온 과정에 가깝다.

  1. Multi-view CNN은 3D object를 image로 바꾸어 강한 2D model을 사용했다.
  2. Voxel과 3D CNN은 regular grid 덕분에 3D-native learning을 쉽게 만들었지만 cubic cost가 컸다.
  3. Octree는 surface 근처에 resolution을 집중해 dense voxel의 낭비를 줄였다.
  4. PointNet은 symmetric aggregation으로 unordered point set을 직접 처리했다.
  5. AtlasNet은 learned parametric patch로 smooth surface를 생성했다.
  6. Deep implicit function은 coordinate query network로 continuous geometry를 표현했다.
  7. NeRF는 density와 radiance, differentiable volume rendering을 결합해 2D image에서 3D scene을 학습했다.
  8. 3D Gaussian Splatting은 sparse explicit primitive로 novel-view rendering을 크게 가속했다.

실제 system은 여러 representation을 함께 사용한다. Sensor에서는 point cloud를 받고, optimization에는 neural field를 사용하며, rendering이나 downstream engine에는 mesh를 추출할 수 있다. 좋은 representation은 task에 필요한 query와 operation을 기준으로 선택해야 한다.

과제에서 확인할 것

Representation별 query 구분

Point cloud, mesh, voxel, implicit field가 각각 무엇을 직접 저장하는지 구분한다. 특히 surface point sampling과 arbitrary coordinate의 inside/outside query 중 어느 쪽이 쉬운지 비교한다.

Voxel resolution 계산

한 축의 resolution을 두 배로 만들었을 때 memory와 3D convolution 연산량이 왜 약 여덟 배로 증가하는지 확인한다. Octree가 surface 근처에만 fine resolution을 두는 이유도 함께 본다.

PointNet의 set 처리

Shared MLP와 max pooling을 통과할 때 point 순서를 바꾸어도 global feature가 같은지 직접 확인한다. Permutation invariance가 sampling density 변화까지 자동으로 해결하지는 않는다는 점도 구분한다.

Point cloud loss 구현

Chamfer distance의 두 nearest-neighbor 방향이 모두 필요한 이유를 확인한다. 한 방향만 사용하면 generated point가 target의 일부 영역에 몰려도 작은 loss가 나올 수 있다. EMD가 one-to-one matching을 요구해 더 비싼 이유도 비교한다.

AtlasNet의 shape 추적

Patch coordinate (u,v)(u,v)와 latent code zz가 MLP에 들어가 3D coordinate가 되는 shape를 확인한다. 여러 patch를 사용할 때 output point 수와 patch 사이 overlap도 점검한다.

NeRF volume rendering

σi\sigma_i, δi\delta_i, αi\alpha_i, TiT_i, cic_i가 각각 무엇인지 구분하고, 앞쪽 density가 커질수록 뒤쪽 sample의 weight TiαiT_i\alpha_i가 작아지는지 확인한다.

2D supervision에서 3D gradient까지

Rendered pixel loss가 volume rendering을 거쳐 density와 color prediction으로, 다시 neural field parameter로 전달되는 computational graph를 따라간다. Camera pose와 ray construction이 틀리면 여러 view를 일관되게 설명할 수 없는 이유도 확인한다.

NeRF와 Gaussian Splatting 비교

NeRF는 coordinate를 넣어 density와 radiance를 얻는 implicit neural field이고, 3D Gaussian Splatting은 위치와 covariance가 명시된 primitive 집합이라는 차이를 구분한다. 두 방식이 empty space를 처리하는 방법과 rendering 속도 차이도 함께 본다.