[Paper Review, KR] Layered 4D-Rotor Gaussian Splatting: A Compressed Representation for Long Dynamic Scenes
Paper Information
Title: Layered 4D-Rotor Gaussian Splatting: A Compressed Representation for Long Dynamic Scenes
Authors: Hanjie Xu, Yuanxing Duan, Qiyu Dai, Ge Li, Baoquan Chen, He Wang
Venue: CVPR 2026
Link: [Paper], [Project]
Teaser Image
Introduction
Dynamic Environments를 표현하는 것의 가장 어려운 점은 복잡한 spatio-temporal deformations 과 diverse motion patterns 를 모델링하는 것이다. 특히, 시간 변화와 viewpoints 변화에 따라 이것들을 모델링하는 것은 더욱 어렵다.
즉, dynamic novel view synthesis 분야는 under-explored 되어 있다. 이를 위해 기존의 NeRF 방식의 NVS은 slow volume rendering과 real-time 혹은 long-duration application이 힘들다는 문제가 있었고, 3DGS가 이것들을 해결하기 위해 등장했다. 그럼에도 불구하고, 기존의 3DGS 기법들은 짧은 영상에서는 좋은 성능을 보였지만, 긴 영상에서는 급격하게 증가하는 Gaussian 수 때문에 큰 GPU VRAM 차지와 storage requirements 에 단점을 가진다.
그래서 긴 영상을 위해 4D Gaussian을 연구한 Temporal Gaussian Hierarchy (TGH) 라는 기법이 존재하지만, mobile과 같은 낮은 대역폭을 요구하는 상황을 충족시키지 못한다.
그래서 이 논문은 Layered 4D-Rotor Gaussian Splatting (L4DRotorGS)라는 새로운 framework를 소개하며, high-fidelity reconstruction과 real-time rendering, reducing storage costs를 가능케한다.
Method & Technical Details
Preliminary of 4D-Rotor Gaussian Splatting
논문의 저자는 해당 SIGGRAPH 2024에 출판된 “4D-Rotor Gaussian Splatting: Toward Efficient Novel View Synthesis for Dynamic Scenes”라는 논문의 사전지식을 필요로 하여 해당 섹션을 구성했다고 한다.
4DRGS 논문의 핵심을 먼저 말하면,
4D-Rotor GS는 하나의 Gaussian을 단순한 3D 타원체가 아니라 x, y, z, t 공간의 4D 타원체로 만들어 놓고, 원하는 시간 t에서 이 4D 타원체를 잘라서 그 시점의 3D 가우시안을 얻는 방식이다.
먼저, 일반적인 3D Gaussian Splatting은
\[\mu = \begin{bmatrix} \mu_x \\ \mu_y \\ \mu_z \end{bmatrix}\]라는 중심과
\[\Sigma \in \mathbb{R}^{3 \times 3}\]라는 covariance를 가지고 있고,
\[G(x) = \text{exp}(-\frac{1}{2}(x-\mu)^T \Sigma^{-1} (x-\mu))\]로 표현된다. 또한 covariance를 직접 최적화하는 대신 scale과 rotation으로 분해한다.
보통
\[\Sigma = RSS^TR^T\]이고
\[S = diag(s_x, s_y, s_z)\]이다.
여기에 opacity와 SH coefficient까지 추가하면 우리가 알고 있는 일반적인 3DGS primitive가 된다.
dynamic scene에서는 사실 Gaussian이 (x, y, z) 뿐만 아니라 t에 따라서도 어떻게 존재하는지를 표현해야 한다. 그래서 4DRotorGS는 Gaussian 자체를 (x, y, z, t) 공간으로 올린다. 즉, 3D Gaussian을 4D Gaussian으로 표현하는 것이다.
그러면, 이렇게 파악할 수 있다.
각 시간의 3D scene을 따로 만드는 대신 하나의 XYZT Gaussian을 시간 평면으로 slice하면 각 시점의 3D Gaussian을 얻을 수 있다.
3D Gaussian의 center가 \((\mu_x, \mu_y, \mu_z)\) 였다면, 4D 에서는
\[\mu_{4D} = (\mu_x, \mu_y, \mu_z, \mu_t)\]가 된다. 여기서 \(\mu_t\)는 frame index가 아니라 “이 Gaussian이 시간축상에서 가장 중심이 되는 시점” 이라고 생각하면 된다. 즉 \(t=\mu_t\)일 때 가장 강하게 보이고, 시간적으로 멀어질수록 약해진다. 원 논문에서는 slice된 Gaussian 앞에
\[e^{-\frac{1}{2} \lambda (t-\mu_t)^2}\]가 붙으며, \(\mu_t\)에서 최대가 되고 멀어질수록 사라진다고 설명한다.
그렇다면 covariance도
\[\Sigma_{4D} = R_{4D}S_{4D}S_{4D}^TR_{4D}^T\in \mathbb{R}^{4 \times 4}\]가 된다.
따라서
\[G_{4D}(x) = \text{exp} (-\frac{1}{2} (x-\mu_{4D})^T \Sigma_{4D}^{-1} (x-\mu_{4D}))\]이고, 여기서 \(x = (x,y,z,t)^T\)이다.
직관적으로 보았을 때, 4D Gaussian이 기울어져 있으면 motion이 생긴다. 예를 들어, x-t 평면에서 Gaussian이 기울어져 있다고 하고, 이 Gaussian을 서로 다른 시간에서 자르면,
\[\begin{aligned} t1 &\rightarrow x=1 \\ t2 &\rightarrow x=2 \\ t3 &\rightarrow x=3 \end{aligned}\]처럼 slice 위치가 달라진다. 따라서, 4D 공간에서의 기울기 = 시간에 따른 3D 위치 변화, 즉 motion이 된다.
여기서, Rotor는 이 4D 기울기를 표현하는 rotation parameter다. 3DGS에서는 quaternion으로 Gaussian의 3D 방향을 표현한다. 하지만 4D에서는 xy, xz, yz 회전뿐 아니라 xt, yt, zt처럼 공간축과 시간축 사이의 회전도 필요하다.
그래서 4DRotorGS는 3DGS의 quaternion 방식 대신 8개의 coefficient를 가진 rotation representation인 4D rotor \(r\)을 사용한다:
\[r = (s, b_{01}, b_{02}, b_{12}, b_{03}, b_{13}, b_{23}, p)\]논문에서는 앞의 네 성분을 spatial rotation, 뒤의 네 성분을 spatio-temporal rotation으로 해석한다. 뒤의 temporal 성분을 0으로 하면 일반적인 3D quaternion과 같은 형태로 축소된다. 즉, \(r\)이 학습하고 저장하기 위한 4D rotation parameterization이다.
즉, 아주 단순하게 생각하면 spatial rotor = Gaussian 자체의 방향, temporal rotor = 시간에 따른 공간 변화와 관련있다고 생각하면 된다.
그리고 논문에서는 4D covariance를
\[\Sigma_{4D} = \begin{bmatrix} U \;\;\;\;\; V \\ V^T \;\;\; W \end{bmatrix}\]로 나눈다.
실제 4D covariance를 전부 쓰면,
\[\Sigma_{4D} = \begin{bmatrix} \sigma_{xx} & \sigma_{xy} & \sigma_{xz} & \sigma_{xt} \\ \sigma_{xy} & \sigma_{yy} & \sigma_{yz} & \sigma_{yt} \\ \sigma_{xz} & \sigma_{yz} & \sigma_{zz} & \sigma_{zt} \\ \sigma_{xt} & \sigma_{yt} & \sigma_{zt} & \sigma_{tt} \end{bmatrix}\]이다.
여기서 공간 $x,y,z$에 해당하는 부분을
\[U = \begin{bmatrix} \sigma_{xx} & \sigma_{xy} & \sigma_{xz} \\ \sigma_{xy} & \sigma_{yy} & \sigma_{yz} \\ \sigma_{xz} & \sigma_{yz} & \sigma_{zz} \end{bmatrix}\]로 두고,
공간과 시간 사이의 covariance를
\[V = \begin{bmatrix} \sigma_{xt} \\ \sigma_{yt} \\ \sigma_{zt} \end{bmatrix}\]로 두며,
시간축의 variance를
\[W = \sigma_{tt}\]로 둔다.
따라서 전체 4D covariance를 간단하게
\[\Sigma_{4D} = \begin{bmatrix} U & V \\ V^T & W \end{bmatrix}\]로 표현할 수 있다.
여기서 \(U\)는 x, y, z 끼리의 관계, \(W\)는 시간 t 방향의 크기, 그리고 \(V\)는 공간 xyz와 시간 t가 얼마나 서로 엮여 있는가를 나타낸다.
즉, \(V=0\)이면 공간과 시간이 안 엮여 있으므로 Gaussian이 시간 축에 대해 똑바로 서 있는 것과 비슷하다. 그래서 시간이 변해도 위치가 안 변한다. 반대로 \(V \ne 0\) 이면 Gaussian이 x-t, y-t, z-t 방향으로 기울어져 있을 수 있다.
특정 시간 t에서 Gaussian을 자르면 그 단면의 중심이
\[\mu(t) = \mu_{xyz} + (t-\mu_t)\frac{V}{W}\]가 된다. 원 논문의 slicing 결과도 이 식이다. 각 항을 하나씩 보면 어렵지 않다.
여기서 \(\mu_{xyz}\)는 Gaussian의 기준 spatial position이고, \(t-\mu_t\)는 “Gaussian의 중심 시간에서 현재 시간이 얼마나 떨어졌는가”이다. 그리고 \(\frac{V}{W}\) 는 시간 1만큼 변했을 때 spatial position이 얼마나 변하는 지 알려준다. 원 논문은 이를 motion speed라고 부르기도 한다.
다시 강조하자면, 4D Gaussian 자체를 프레임마다 이동시키는 것이 아니라 4D Gaussian을 다른 t에서 자르면서 3D 단면 위치가 달라지는 것이다.
Layer and bucket Structure
이 섹션의 핵심은
긴 동영상을 하나의 거대한 4D Gaussian 집합으로 GPU에 올려놓지 않고, Gaussian들을 시간적 특성에 따라 “Layer \(\rightarrow\) Bucket” 구조로 정리해서 필요한 것만 불러온다.
이다. 앞의 개념에서 우리는 4D Gaussian이 시간 중심 \(\mu_t\)와 유효한 temporal extent \(\tau\)를 가진다는 것을 알 수 있었다.
이제 여기서 말하는 Layer가 무엇인지 설명하겠다. 먼저, 이 논문은 “Temporal Gaussian Hierarchy(TGH)”라는 논문을 기반으로 설계되었다.
TGH에서는 Gaussian의 temporal extent \(\tau\)에 따라 서로 다른 temporal level에 배치한다. 즉, \(\tau\)가 크다면 오랫동안 존재하는 Gaussian이며, \(\tau\)가 작으면 짧은 시간 동안만 존재하는 Gaussian인 것이다. 이렇게 TGH는 Guassian을 temporal extent에 따라 여러 level로 정리한다.
직관적으로 보자면, lower layer은 벽, 책상, 배경처럼 오랫동안 거의 변하지 않는 부분이고, higher layer은 사람의 팔, 손, 움직이는 물체처럼 짧은 시간 동안 상태가 유지되는 부분이다.
그래서 Layer를 한마디로 표현하면:
비슷한 temporal lifetime을 가진 Gaussian들을 모아놓은 계층
이다.
그런데, 기존 TGH에는 문제가 있다. 각 layer level에는 동일한 길이의 여러 temporal segments를 가진다. 그리고, layer level이 낮으면 이 segment의 길이가 길고, layer level이 높으면 segment의 길이가 길다. Gaussian을 fixed temporal segment 안에 넣어야 한다는 문제가 있는데, 이는 특정 Gaussian들이 만약 두 segment에 걸쳐 있다면 이를 어떻게 처리해야할지 알아야 한다. TGH의 경우에는 이를 자기의 temporal influence range \(\tau\)를 완전히 포함할 수 있는 가장 짧은 segment에 넣는다.
예를 들어, Gaussian 하나가 \(\mu_t = 9.8\) 이고 temporal extent가 커서 실제로는 \(8.5 \sim 11.1\) 동안 유효하다고 보고, level-1의 layer segment가 각각 0~10, 10~20, 20~30 이라면 TGH는 segment boundary에 걸쳐 있다고 생각하고, 더 큰 temporal segment(ex. 0~20, 20~40,… )가 있는 level-0 layer segment에 넣어서 처리한다. 이렇게, 이를 어느 segment로 Gaussian들을 밀어서 각 Gaussian의 temporal extent에 맞는 layer에 위치시키는 게 아니라 다른 특정 layer 안에 존재하게 된다면, 이 문제를 TGH Boundary 문제라고 표현하고, 이로 인해 서로 다른 temporal/geometric 특성을 가진 Gaussian들이 layer 안에서 섞이면서 distribution이 넓어진다. 이렇게 되면, compression이 어려워진다는 문제점이 있다.
그래서 이 논문의 저자는 Layer+Bucket이라는 해결책을 도입했다. 간단하게 전체 구조는 “Scene \(\rightarrow\) Temporal Layers \(\rightarrow\) Temporal Buckets \(\rightarrow\) 4D Gaussians”다.
논문은 기존 TGH layer segment를 다시 left/right bucket으로 나누고, 동시에 Gaussian이 bucket boundary를 넘어갈 수 있도록 허용한다. 여기서 좀 헷갈릴 수 있는데, “segment boundary는 결국 남아 있는 것 아닌가?”라고 생각할 수 있지만, 여기서부터는 완전히 segment라는 개념을 bucket이라는 구조로 탈바꿈 했다고 보는 게 맞다. 이게 아래의 figure 2 (a) 이미지의 설명과 같다:
여기서 Layer의 경우에는 Gaussian의 지속시간 \(\tau\) 역할을 수행하고, Bucket은 Gaussian이 시간축에서 어디에 있는지 나타내는 \(\mu_t\) 역할을 수행한다.
이제 이해가 됐다면, 이렇게 정리할 수 있다:
- 기존 TGH의 기법의 경우에는 가우시안의 time span이 어정쩡하게 각 layer-level의 segment boundary에 걸쳐져 있다면, 이를 temporal segment가 큰 low-level의 layer로 해당 Gaussian을 내린다.
- 이 경우 Gaussian 자체의 저장량이 직접 증가하는 것은 아니지만, 짧은 temporal extent를 가진 Gaussian이 원래보다 낮은 layer에 들어가면서 해당 layer의 Gaussian 특성이 불균일해져 압축 효율이 떨어질 수 있다.
- 또한, 시간적 특성이 다른 가우시안들끼리 하나의 layer에 들어가면 distribution이 넓어진다는 문제가 있는데, 이는 VQ codebook으로 압축할 때 드러나는 문제인데, 이는 이후에 설명하도록 하겠다.
- 이를 해결하기 위해 저자들은 TGH의 fixed segment 구조를 bucket 기반 구조로 재구성하고, Gaussian이 bucket boundary를 자유롭게 넘어갈 수 있도록 한다.
- 이렇게 되면, Bucket의 Boundary를 넘는 Gaussian이 있다면, 이의 layer를 바꾸지 않고 각 Gaussian의 시간적 특성에 적절한 layer-level에 남을 수 있다.
- 또한 각 layer를 여러 bucket으로 나누기 때문에, 특정 시간 \(t\)를 렌더링할 때는 현재 bucket과 인접한 bucket의 Gaussian만 GPU로 불러오면 된다. 따라서 긴 영상에서도 필요한 Gaussian만 선택적으로 로드하여 가시성을 보장하는 동시에 메모리 사용량을 최소화할 수 있다.
TGH처럼 레이어의 개수를 수동으로 고정하는 대신, 논문의 저자들은 레이어 개수 \(L\)을 다음과 같이 유동적으로 계산하여 설정한다:
\[L = \lceil \log_2 n \rceil + 1\]여기서 \(n\)은 video sequence의 총 프레임 수다.
Training Framework
이제 앞에서 Layer-Bucket Structure를 어떻게 효율적으로 학습할지를 설명하고자 한다. 크게 Triple-buffer training + DARLR 두 부분으로 나뉜다.
먼저, Triple-buffer training에 대해서 설명하겠다.
앞에서 설명했다시피, 전체 Gaussian을 GPU에 계속 올려놓는 게 아니라, timestamp t에 필요한 bucket 주변의 Gaussian만 사용하기로 했다. 근데 이렇게 되면, 학습에서도 매 iteration마다 timestamp가 바뀐다.
training image를 하나 뽑을 때마다 필요한 Gaussian 집합이 달라진다는 것인데, 문제는 매번 CPU는 필요한 Gaussian을 GPU로 복사하고, GPU는 필요 없어진 Gaussian을 CPU로 복사하는 방식을 반복하면, CPU와 GPU 사이에 memory transfer가 병목된다는 것이다. 특히 TGH에서 이 CPU-to-GPU transfer cost가 주요 bottleneck이다.
그래서 논문의 저자들은 Triple-buffer를 사용한다. 이는 GPU double buffer와 CPU bucket buffer로 구성된 triple-buffer strategy를 사용한다.
CPU Bucket Buffer 에는 전체 scene의 Gaussian을 bucket 구조에 따라 CPU 쪽에 보관한다(Bucket 1, Bucket 2, …). 현재 timestamp에 필요하지 않은 Gaussian까지 GPU에 전부 둘 필요가 없으니까, 장기 저장소 역할을 CPU가 담당한다.
GPU Buffer는 현재 또는 최근 iteration에서 사용되는 Gaussian들을 GPU에 유지하는 공간이다. Figure 3(b)를 보면 Step i에서 가지고 있던 GPU buffer를 전부 비우는게 아니라 요구사항에 따라 달라지는 것을 볼 수 있다.
GPU Render Buffer는 현재 timestamp t에서 실제로 rendering에 필요한 Gaussian 집합을 따로 구성한다.
그러면 한 training iteration이 어떻게 진행되는지 확인해보자:
- Timestamp t의 training image를 하나 sampling
- 전체 multi-view dynamic video(\(I_0, I_1, I_2, ... , I_t , ... , I_n\))에서 \(I_t\)를 하나 sampling한다.
- 이에 따라 이번 iteration에서 학습할 timestamp t가 결정된다.
- GPU buffer update 및 GPU render buffer 구성
- Timestamp t에서 필요한 bucket과 Gaussian을 확인한다.
- 필요한 Gaussian 중 이미 GPU buffer에 존재하는 것은 그대로 재사용하고, GPU에 없는 Gaussian만 CPU bucket에서 load하여 현재 t를 위한 GPU render buffer를 구성한다.
- 동시에 pruning과 densification 등의 adaptive density control을 수행한다.
- GPU에 존재하지만 여러 step 동안 사용되지 않은 Gaussian은 CPU bucket으로 offload한다.
- 따라서 매 iteration마다 Gaussian 전체를 CPU와 GPU 양방향으로 옮기는 것이 아니라, 필요한 Gaussian만 load/offload 하면서 GPU buffer를 계속 유지한다.
- 일반적인 3DGS optimization
- GPU render buffer에 현재 t에서 필요한 Gaussian이 준비되면, \(Gaussian \rightarrow Render \rightarrow \hat{I}_t\)를 수행한다.
- 렌더링 결과 \(\hat{I}_t\)와 GT image \(I_t\)를 비교하여 Loss를 계산한다.
- 이후, \(Loss \rightarrow Gradient \rightarrow Optimizer\)를 통해 Gaussian parameter를 업데이트한다.
- 학습된 Gaussian 중 계속 GPU에 유지할 Gaussian은 다음 iteration의 GPU buffer i+1로 이어지고, 오래 사용되지 않는 Gaussian만 CPU로 offload된다.
다음으로, Dynamic-Aware Rotor Learning Rate (DARLR)에 대해서 설명하도록 하겠다.
4D-rotor를 사용하는 것은 Vanilla 3DGS를 사용하는 것과 좀 다르다. Vanilla 3DGS에서는 rotation이 spatial rotation 뿐이라서 하나의 rotation learning rate로 충분하다. 그런데 4D-rotor에서는 temporal component까지 학습해야 한다. 즉, 4D-rotor는 temporal/spatio-temporal rotor component가 spatial rotation과 함께 있다.
이런 Gaussian의 temporal rotor에 큰 learning rate를 주면, optimization 중 temporal orientation이 조금만 바뀌어도 시간적으로 먼 위치에서 spatial position drift가 크게 발생할 수 있다.
긴 영상일수록 $\lvert t-\mu_t\rvert$가 훨씬 커질 수 있기 때문에 이 문제가 더 심해진다.
그래서 저자들은 \(\tau\)가 클수록 temporal rotor Learning Rate를 작게 설정한다. 즉, Large \(\tau\)는 오래 존재하는 Gaussian이고, static/slowly varying일 가능성이 크므로, temporal rotor learning rate를 낮춰서 시간에 따른 drift를 억제하자는 것이다.
반대로 short-\(\tau\) Gaussian은 보다 dynamic한 영역을 표현하므로 상대적으로 더 큰 temporal rotor update를 허용할 수 있다.
Factorized Covariance Quantization
먼저, SQ와 VQ에 대해 설명을 하려고 한다. 아래의 정보들을 펼쳐서 간단하게 살펴보기를 바란다.
Scalar Quantization
scalar 값 하나하나를 양자화하는 방식
예시로 설명해보겠다.
값의 범위가 \([0,1]\)이고 2-bit quantization을 한다고 한다면,
표현 가능한 값은 총 \(2^2=4\)개 뿐이다. 예를 들어,
\[\{0, 0.33,0.67,1.0\}\]만 허용한다면,
\[0.1 \rightarrow 0 \\ 0.4 \rightarrow 0.33 \\ 0.71 \rightarrow 0.67\]처럼 바뀌게 된다. 당연히 원래 값과 약간의 차이가 생기는데, 이걸 quantization error라고 한다:
\[\text{error} = |x-Q(x)|\]원래 Gaussian마다 parameter를 float32로 저장했다면 값 하나당 32 bit가 필요하다. 하지만 8-bit SQ를 사용하면 32bit를 8bit로 줄여서 저장량을 줄일 수 있다.
그래서 SQ로 opacity, scale factor, scalar parameter 같은 것들을 압축하기 좋다.
실제로 이 논문에서는 scale factor를 SQ로 압축하고, opacity 역시 SQ를 사용한다.
Vector Quantization
이번에는 숫자 하나가 아니라
\[x = [x_1, x_2, ... , x_D]\]같은 D 차원 vector 전체를 압축한다.
예를 들어 Gaussian의 normalized scale이
\[s = [0.72, 0.41, 0.19, 0.11]\]이라고 한다면, 이걸 각 component별로 따로 quantization 하는 대신, 해당 벡터 자체를 하나의 단위로 취급한다.
만약, codebook에 다음 4개의 vector가 있다고 하자.
\[C = \begin{cases} c_1 = [1.0, 0.5, 0.2, 0.1] \\ c_2 = [0.7, 0.4, 0.2, 0.1] \\ c_3 = [0.2, 0.8, 0.6, 0.3] \\ c_4 = [0.1, 0.2, 0.9, 0.7] \end{cases}\]각 codebook vector와 비교하면 \(c_1\)이랑 가장 비슷할 것이고, 그러면 원래 vector는 저장하지 않고
\[\text{index} = 1\]만 저장한다. 나중에 rendering할 때는 $$c_1$으로 복원하면 된다.
따라서, Gaussian마다 float vector 전부를 저장하는 게 아니라 codebook index만 저장한다.
이렇게 SQ와 VQ에 대해 이해했다면, 4D Gaussian을 quantization 하는 방법을 살펴보자.
핵심은
4D Gaussian의 covariance를 통째로 VQ를 하게되면 값의 범위가 너무 커 압축이 제대로 되지 않으므로, covariance를 구성하는 scale과 rotor를 성질별로 쪼개고 각각 적합한 방식으로 quantization을 수행한다.
이다.
우리는 아래의 식을 아까 전에 살펴보았다:
\[\Sigma_{4D} = R_{4D}S_{4D}S_{4D}^TR_{4D}^T\in \mathbb{R}^{4 \times 4}\]여기서
\[S_{4D} = diag(s_x, s_y, s_z, s_t)\]는 Gaussian의 4D scale이고,
\[R_{4D}\]는 4D Rotor로 표현되는 4D rotation이다. 즉, covariance는 scale과 rotor를 저장하고 있다는 소리다.
기존의 “C3DGS”라는 논문에서는 normalized 3D covariance에 VQ를 직접 적용할 수 있었다. 즉, 여러 Gaussian의 covariance가 비슷하다면, codebook에 있는 대표 covariance 하나를 공유하게 만들 수 있었다.
그런데, 4D covariance는 spatial scale과 temporal scale의 값 범위 차이가 너무 커서 그대로 VQ를 하면 안된다고 논문의 저자들은 주장한다. 논문에서는 4D Gaussian의 spatial/temporal scale이 대략 \(10^{-3} \sim 10^3\)범위까지 퍼질 수 있다고 말한다. 이것만 해도 \(10^6\)배 차이가 나는데, 여기에 covariance는 scale과 quadratic relation을 가지고 있다는 것을 위의 \(\Sigma_{4D}\) 수식을 보면 알 수 있다. 즉, 사실상 scale이 제곱되어 들어가니까 \(10^{-6} \sim 10^{6}\) 정도의 범위로 더 확장된다.
이렇게 넓은 범위로 벡터들이 펴져 있으면 codebook으로 이 모든 범위를 정밀하게 표현하기 어렵기 때문에, VQ representation precision이 부족하다는 것을 알 수 있다. 그래서 저자들은 4D covariance를 통째로 VQ하는 방식을 포기하고 Factorized Covariance Quantization을 진행한다. 좀 더 자세하게, Scale과 Rotor를 따로 압축하는 방식으로 진행한다.
Scale의 경우, 먼저 Scale Decomposition을 진행한다. 원래 4D scale은
\[S_{4D} = (s_x, s_y, s_z, s_t)\]처럼 4개의 값을 가지고 있는데, 이를 scale factor와 normalized scale로 나눈다.
개념적으로
\[s = a\hat{s}\]같은 느낌으로 \(a\)가 scale factor가 되는 것이고, \(\hat{s}\)가 normalized scale이 되는 것이다. 즉, 각각 전체적인 Gaussian의 크기와 각 축 간 상대적인 비율을 표현한다고 생각하면 된다.
자, 그러면 scale factor와 normalized scale을 quantization 해야 한다. 우리는 앞서 SQ와 VQ의 개념에 대해 이해했으니, 각각에 어떤 quantization을 적용해야 할지 어렴풋이 짐작이 가능하다. scale factor에는 SQ를 normalized scale에는 VQ를 진행하면 된다. scale factor는 결국 scalar 하나이기 때문에 SQ를 진행하고, normalized scale은 vector기 때문에 이런 선택을 진행한 것이다.
다음으로, Rotor를 Decomposition 하고 quantization 해보자.
우리는 4D Rotor \(R_{4D}\)를 8개의 coefficient로 표현했었다:
\[(s, b_{01}, b_{02}, b_{12}, b_{03}, b_{13}, b_{23}, p)\]그리고 앞의 4개의 coefficient를 spatial component, 뒤의 4개의 coefficient를 temporal/spatio-temporal component 성질로 바라보았다.
여기서 논문의 저자들은 직관적으로 생각한다. 벽과 같은 static한 Gaussian이라면 spatial rotor는 일반적인 quaternion과 비슷한 역할을 수행할 것이고, temporal rotor component는 보통 0 근처에 있을 거라는 것이다. 즉, static과 dynamic을 분리할 수 있게 되는 것이다. static Gaussian은 spatial orientation은 필요하지만, space-time rotation은 거의 필요 없어 temporal component가 작을 가능성이 크다는 전제를 깔고 들어가는 것이다.
여기서 만약 8D rotor를 한꺼번에 VQ를 진행하게 되면, 앞 4개의 coefficient와 뒤 4개의 coefficient의 값의 범위(distribution)이 너무 달라 codebook이 두 종류의 서로 다른 statistics를 동시에 표현해야하기 때문에 힘들어진다고 말한다.
\[Rotor \rightarrow Rotor_{spatial}+Rotor_{temporal}\]로 분리하고 나서, 각각의 spatial rotor와 temporal rotor에 VQ codebook을 할당한다. 그러면 우리는 결과적으로
\[i_{spatial}, i_{temporal}\]이라는 두 개의 index만 저장하면 된다.
그러면 Decoder는 해당 index를 불러와서 각각의 codebook에서 spatial rotor와 temporal rotor component를 추출해서 합친 다음 normalize해서 사용하면 된다.
추가로, 해당 논문의 저자들은 C3DGS를 따라 Gaussian importance weight를 사용한다. 모든 training image를 시간에 걸쳐 render한 다음, 각 Gaussian이 pixel에 얼마나 기여했는지를 backpropagation gradient를 이용해 측정하고, 이를 quantization weight로 사용한다.
Layered Compression
우리는 앞서 scale factor, normalized scale, rotor spatial, rotor temporal component들로 분리했고 이를 codebook이라는 개념을 통해 압축하고자 했다.
핵심부터 말하면, 이 4개의 component들을 모든 Gaussian에 하나의 codebook으로 압축하지 말고, temporal layer별로 따로 압축하고자 한다. 즉,
Layer마다 Gaussian parameter 분포가 다르니까 layer 별 codebook을 쓰자는 소리
우리는 앞의 Layer-Bucket 구조에서 temporal extent \(\tau\)에 따라 Gaussian들은 서로 다른 layer에 들어갔었다. 이 temporal extent가 다른 Gaussian들 즉, layer가 다른 Gaussian들의 4개 component의 분포가 달라질 수 있다는 것이다.
모든 layer를 하나의 VQ codebook으로 압축하게 되면, codebook은 서로 매우 다른 distribution을 동시에 커버해야 한다. 이러면 대표 vector가 많이 필요해서 codebook size가 증가하거나, codebook 사이즈를 작게 유지하려고 하면 quantization error가 증가한다. 즉,
shared codebook을 사용하면 wide distributional variance 때문에 codebook이 커지고 quantization error가 증가한다.
그래서 논문의 저자들은 layer-wise compression를 진행한다.
각 layer에 codebook을 따로 둔다는 것이다. layer 0에는 codebook 0, layer 1에는 codebook 1, … 이런 식이다. 즉, 각 codebook은 자기 자신 layer의 좁은 distribution만 표현하면 된다.
단, Gaussian의 SH나 Opacity와 같은 parameter의 경우에는 각각 Global VQ와 Global SQ를 사용한다.
Opacity(불투명도)의 경우에는 sigmoid 이후 \(\alpha \in [0,1]\)범위에 있어 값 범위가 애초에 제한되기 때문이고, SH의 경우에는 distribution이 layer가 달라도 상대적으로 비슷하게 유지되어 하나의 global codebook으로도 각 layer의 SH를 충분히 표현할 수 있다고 한다. 이로써 storage requirements를 줄일 수 있다.
그러면, codebook은 각 layer 별로 Normalized scale, rotor spatial, rotor temporal에 사용되니까 \(3L\)에 SH가 global codebook을 사용하니 \(3L+1\)이 될 것이다. 나머지는 SQ를 사용하기 때문에 이는 codebook을 사용하지 않는다. 만약 quantization unit 개수를 묻는다면, SQ까지 포함하여 \(4L+2\)가 될 것이다. 그런데, 사실 이에 더해 이 논문은 layer 자체도 merge 한다고 한다.
모든 layer가 Gaussian을 많이 가진 것은 아니므로 마지막 쪽에 있는 layer들 중 Gaussian 수가 적은 layer들을 서로 merge 한다. 이러면 codebook에 대한 overhead를 아낄 수 있다고 표현한다.
Residual Codebook Quantization (RCQ)
논문의 저자들은 layer마다 별도의 VQ codebook을 만들었다. 그런데 영상이 아주 길어지면, 같은 layer 안에서도 시간적으로 멀리 떨어진 Gaussian들의 parameter distribution이 달라질 수 있다. 이러면, 각 layer 별로 하나의 codebook만으로는 layer 전체를 표현하기에 한계가 있다고 본다. 논문은 이를 limited capacity문제라고 표현한다.
그래서 각 layer의 bucket 내부 Gaussian들을 다시 여러 bucket block으로 나눈다. 각 layer에 Block A, B, C가 있다고 한다면, 각 block에 codebook A, B, C를 두는 것이다. 그러면 local한 distribution이 완성된다.
그런데, 이는 block마다 codebook 전체를 저장해야 해서 storage가 다시 커진다는 문제점이 있다.
그래서 codebook 전체를 저장하는 게 아니라 difference만 저장하고자 한다.
Layer 전체를 위한 기존 codebook을 \(C_{global}\)이라고 하고, 특정 block에 최적화된 codebook을 \(C_{block}\)이라고 하자.
\[C_{block} \approx C_{global} + \Delta C\]여기서 \(\Delta C\)가 residual이라고 표현한다.
그래서 저자들은 block-specific codebook 전체를 저장하지 않고, 그 codebook과 layer-global codebook 사이의 difference를 residual codebook으로 다시 quantization한다. 그러면 이 layer-global codebook과 block-specific codebook의 difference distribution을 quantization하는 residual codebook 덕분에 Gaussian들은 2번의 압축을 겪은 셈이 된다.
순서가 헷갈릴 수 있다. 흐름을 명확하게 해주자면,
각 Block의 Gaussian들에 대해 별도의 VQ를 수행해서 block-specific codebook \(C_{block}\)을 만든다. 그리고 기존 layer-global codebook \(C_{global}\)과 비교해서 residual을 구할 수 있다. 그리고 이 residual들을 다시 작은 residual codebook으로 quantize한다.
이렇게 하면 block-specific codebook을 버리고도, decoding 할 때 다시
\[\hat{C}_{block} = C_{global} + C_{residual}\]로 복원이 가능하다.
이제, 특정 block에 있는 Gaussian들은 저장된 global codeword index와 Residual codeword index를 사용해서 decoding할 수 있다는 것을 이해했다.
추가적으로 이를 보면 index table도 필요하다는 것을 알 수 있다. 그리고 실제로는 residual codebook을 block마다 따로 저장하는 게 아니라, lightweight residual representation과 index table을 사용해서 overhead를 줄인다. 왜냐하면 storage requirements가 늘어날 수 있기 때문이다.
Layer 0에는 RCQ를 또한 적용하지 않는다. 일반적으로 temporal variation이 적어서 추가적인 local residual compression으로 얻는 이득이 적다고 보고한다.
Experiments
Implementation Details
논문의 저자들이 사용한 자원은 NVIDIA RTX 3090 1장이며, 학습 시간은 대략 30분이며, 그동안 GPU memory는 2GB만 사용되었다. 그리고 compression 시간은 대략 4분이었다고 한다. inference에서는 rendering이 660FPS의 속도를 유지하였다.
Datasets
해당 논문의 저자들이 사용한 데이터셋은 N3DV와 SelfCap 데이터셋이다. N3DV 데이터셋의 경우에는 6개의 동적 장면을 포함하고, 각 장면은 19~21개의 카메라를 사용해 1352 \(\times\) 1014 해상도에서 10초 동안 촬영되었다. SelfCap 데이터셋의 경우에는 큰 움직임을 보여주는 6개의 장면을 포함한다. 이 시퀀스들은 긴 재생시간(1~10분)을 가지는 것이 특징이다.
Evaluation on N3DV Dataset
Table 1에서는 기존 NeRF 기반 방식들과 Gaussian 기반 방식들과 함께 비교한다. Ours model의 경우에는 압축되지 않은 경우인데, 높은 visual quality를 보이지만 큰 저장 공간을 필요로 한다. Ours Large 모델은 4분간의 compression 단계를 거쳐 저장 공간을 13.1배 절감하고 약 90% 빠른 렌더링 속도를 구현하는 동시에, 성능 하락은 미미했음을 보여준다. Ours Small 모델은 압축률을 20.5배까지 추가로 끌어올려 bitrate를 1MB/s 미만으로 낮추면서도, 기존 베이스라인들과 견줄 만한 시각적 품질을 보여준다.
Evaluation on SelfCap Dataset
대부분의 Dynamic NVS baseline 모델들은 대략 10초 내외의 짧은 클립만을 처리할 수 있었는데, 논문의 저자들은 긴 비디오 시퀀스에 대한 효과성을 평가하기 위해 SelfCap의 6개 장면 전체에 대한 평가를 수행했다.
Table 2를 볼 수 있듯이, Compression을 진행하더라도 시각적 품질은 보존되면서 storage requirements는 줄어들고 렌더링 효율은 대폭 향상되어 약 40%의 FPS 향상을 달성하였다. Ours Large 모델의 경우 high-fidelity reconstruction를 보여주는 반면, Ours Small 모델의 경우에는 경쟁력 있는 화질을 유지하면서도 압축률을 19.1배까지 끌어올렸다.
Figure 9를 보면 알겠지만, 해당 방법이 사람과 물체 간의 매우 dynamic하고 빠른 움직임이 일어나는 영역에서도 고주파 디테일과 high-fidelity를 유지하며, 압축된 결과물 역시 압축되지 않은 원본 모델 버전과 매우 유사함을 보여준다.
더 나아가, SelfCap Bike 장면을 활용해서 더 긴 시퀀스에서의 재구성 성능을 추가로 평가하고자 했다. Table 3를 보면 알겠지만, 비디오의 길이가 늘어나도 일관되게 안정적인 성능을 보여준다.
Ablation Studies
N3DV Flame Salmon 장면을 대상으로 Compression 파이프라인의 핵심 설계 단계들을 소거해 가며 화질 및 성능 변화를 측정했다. Table 4의 PSNR 지표 결과와 Figure 6를 보면 알 수 있듯이, 4D covariance를 단순하게 quantization하여 압축하면 복원 fidelity가 극심하게 저하되는 현상이 발생했다. 여기에 FCQ를 적용하면 저장 공간이 줄어드는 동시에 PSNR도 추가로 개선되는 게 보인다. Layered Compression까지 적용하면 PSNR이 더 개선될 수 있다. 최종적으로 RCQ까지 모두 적용하면 약간의 저장 공간 증가만으로 정밀도를 미세 조정하여 추가적인 화질 보상 효과를 얻을 수 있다.
N3DV Flame Salmon 장면에 대해 compression 알고리즘의 주요 하이퍼파라미터가 미치는 영향도 분석하였다. Figure 4에서 볼 수 있듯이, VQ codebook 크기를 1024에서 16384로 점진적으로 늘려가면 Compression error가 감소하면서 PSNR 성능이 지속적으로 향상하지만, 그만큼 storage requirements가 함께 늘어난다. 특히 SH codebook의 크기를 키울 때 단위 용량 대비 화질 상승 효율(PSNR per MB)이 가장 강력함을 확인했다.
Figure 5에서는 SH feature의 VQ threshold를 낮추어 정밀하게 처리할 때의 저장 효율과 시각적 품질 간 trade-off를 보여준다.
Table 5에서는 RCQ codebook 크기를 여러 수준으로 변경하더라도 최종 저장 용량과 화질 변동폭이 미미하게 나타나 파라미터 설정에 따른 모델의 robustness를 확인했다.
논문의 저자들은 DARLR strategy를 학습 단계에 적용했는데, 이를 적용했을 때 정적인 배경 영역들의 정교한 텍스처와 형태를 뭉개짐 없이 선명하게 보존하는 것을 확인할 수 있다.
Limitations & Future work
- 해당 논문의 파이프라인은 매우 낮은 VRAM 사용량을 보여주지만, 학습을 마친 가우시안들을 압축하는 과정 자체가 상당한 시간을 소모한다.
- 실시간으로 들어오는 비디오 소스를 실시간으로 반영하여 학습하는 온라인 학습을 지원하지 않는다.
즉, 이후의 연구에서는 더 빠르게 압축할 수 있는 기법을 연구하고, 실시간 온라인 학습 및 점진적 압축을 지원하는 framework를 연구해야 한다.