想象一位画家接到一个任务:把一座小城完整地“搬”进电脑里,让人能绕着它走、从任意角度观察。他没有用画笔一笔笔描,而是取来一盒半透明的水彩墨点贴纸。贴纸近似椭圆、边缘柔和、能透光。他把贴纸在三维空间里一张张贴好,调整每张的位置、大小、颜色、浓淡和倾斜角度;每调整一次,就从一个方向“看”一眼——贴纸叠出来的画面,必须和他手里那张真实照片对得上。贴纸成千上万,反复调整,直到不管从哪个角度望过去,画面都和照片一致。这,就是高斯泼溅(Gaussian Splatting,简称3DGS)的工作方式。它把3D重建变成一场“贴墨点、对照片、再调整”的循环,训练几十分钟就能完成,渲染时更是能达到实时浏览。本文就用这盒“墨点贴纸”带你走完3DGS从原理到落地实践的全过程。
掌握Gaussian Splatting,意味着你能用一套GPU脚本在数分钟内产出可实时浏览的写实三维场景——这是数字孪生、AR电商、虚拟制片等领域最热门的选型方向之一,也是简历上最具辨识度的新技能。
目录
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
本质原理:一颗会呼吸的水彩墨点
画家手里的墨点贴纸从来不是简单圆片:贴在玻璃板上的那面有圆心位置,贴纸本身有长轴短轴、可以旋转、半透明,颜色还会随观看角度微微变化。一颗墨点用几个数字就能描述:中心、胖瘦、朝向、浓淡、颜色。这盒墨点,就是3DGS里讲的“显式表示”——场景信息全部以这些参数的形式存在,而不是被压进某个神经网络的黑盒里。
在数学上,这颗墨点是一个三维高斯椭球,由中心 μ 和协方差矩阵 Σ 决定形状,再配上不透明度 o 与颜色系数。渲染时,每个椭球沿视线投影成屏幕上一个边缘柔和的椭圆光斑——这就是“软边缘混合”;整个过程可求导,梯度能一路传回每个参数,让算法用梯度优化来“调墨点”,这就是“可微光栅化”。训练中系统还会按需增删墨点,这部分称为密度控制,后文会细讲。
回到比喻:整盒墨点叠起来,就是完整的三维风景。每颗墨点都清清楚楚、可调可删——这正是3DGS与NeRF最大的气质差异。
- 三维坐标 x查询空间中任意一点(像素射线穿过的位置)
- 中心位置 μ墨点贴纸的圆心所在的三维坐标
- 协方差矩阵 Σ决定椭球如何拉伸与旋转的矩阵,用它的逆矩阵把普通距离换算成“马氏距离”
- 指数衰减加权距离平方越大,墨点浓度越快衰减为 0,形成柔和边缘
- 不透明度 o墨点浓淡系数,取值 0 到 1,控制这颗墨点对外观贡献的上限
重建流程:从照片堆到立体画布
画家开工前要先收集“参考照片”:绕着雕塑走一圈,每个角度都拍,相邻照片要有重叠。然后他会迅速在三维空间里撒一把粗略定位的墨点,先框出雕塑的大致轮廓,再不断比对照片、微调每一颗。这盒墨点的训练流程,走的是完全相同的三步。
第一步是多视角采集:用手机、相机或无人机围绕场景拍摄几十到几百张照片,保证视角覆盖与重叠。第二步是 SfM 初始化:算法(常用 COLMAP)从照片的特征匹配中估计每张照片的相机位姿,并输出一份稀疏点云——这些稀疏点直接当作墨点的初始中心,相当于画家“先撒一把粗定位的墨点”。第三步是迭代优化:随机挑选一个相机视角,把当前墨点配置渲染成图,与对应真实照片比较像素差异,再反向传播更新所有墨点参数,重复成千上万次。
训练使用的损失函数是亮度误差与结构相似度的加权组合。误差越小,说明这盒墨点从该视角看过去越像真实照片;当所有视角都足够像时,训练收敛,此后任意新视角都可以实时渲染。
画家每调一颗墨点,都要停下来看一眼对比图;3DGS的训练循环,就是把这套“看—比—调”的动作自动化并加速了几万倍。
- 预测图 C_pred当前墨点配置在某个相机角度渲染出的画面
- 真值图 C_gt同一角度真实拍摄的照片
- L1 误差逐像素求亮度差绝对值之和,衡量整体颜色贴不贴
- D-SSIM 项结构相似度损失,感知两图在边缘、纹理结构上的差异
- 权重 λ两部分配比,通常取 0.2
方法对比:和两位老对手同场竞技
在墨点画家之前,还有两位老师傅:一位只擅长拼硬纸板模型,另一位把颜料慢慢“蒸”进玻璃里逐层显影。前者对应传统 MVS(多视角立体视觉),后者对应 NeRF(神经辐射场)。贴墨点的3DGS,和这两位走的是完全不同的路。
MVS 先做稠密匹配得到点云,再建网格、贴纹理,流程长,弱纹理区域容易破洞,遇到反射表面更是头疼;NeRF 把整个场景编码进神经网络权重,渲染时每条视线要采样几十上百个点做积分,训练以小时计、渲染也远达不到实时。3DGS 则把墨点显式摆在三维空间里,渲染时一次光栅化全部画完,不需要逐点查询网络。
3DGS 的“画法”可以用一条渲染方程概括:沿视线把墨点从前到后排序,逐颗叠加“这颗墨点的颜色 × 它挡住的比例 × 前方所有墨点都没挡住的比例”。这个操作本质是一次透明度混合,计算量小,显卡并行度高,因此训练分钟级、渲染上百帧,这就是它相对二位前辈最亮眼的代表优势。
同样的“看画”任务,拼纸板太慢、蒸颜料更慢,而一盒墨点几分钟叠完、还能实时换角度——这就是3DGS在速度与质量上的制胜点。
- 颜色 c_i第 i 颗墨点自带的基础颜色(三维 RGB 向量)
- 该点不透明度 α_i屏幕某像素处这颗高斯椭球贡献的透明度(墨点浓度 × 不透明度)
- 累积透过率排在它前面的墨点都“没挡住它”的概率乘积
- 从前到后求和所有墨点按视线排序后加权求和,得到该像素最终颜色
优势局限:亮眼的优点与现实的短板
贴纸画家并非没有烦恼:风景越大,墨点越多;画廊的“玻璃板”(显存)就那么大;遇到镜面和水面,墨点怎么叠都不太像。先看优点:3DGS 渲染质量高、训练速度快、渲染实时,而且因为是显式表示,可以直接增删改查某颗墨点——想删掉场景里的电线杆,删对应墨点即可。这些特性让它在新视角合成和场景编辑中格外顺手。
再看短板,最大的痛点是显存开销:一个场景动辄上百万颗墨点,每颗还带着一长串参数;其次是新视角外推弱,极端角度会“糊”;玻璃、水面等透明反光表面难以用不透明椭球近似;最后,它强依赖 SfM 给出的相机位姿,位姿错了全盘皆输。显存成本可以用一个简单公式估算,也正因如此,工程上才需要压缩与加速。
墨点画法擅长“大场面、平滑表面”,但真要选型,就得看清它“贵在玻璃板、怕镜子水面”——认清局限,才能把它用在刀刃上。
- 高斯个数 N场景中墨点总数,典型值 100 万 ~ 500 万
- 每颗参数体积 B位置、旋转、尺度、不透明度、球谐系数合计约 240 字节
- 估算总内存两者相乘得到 GB 级显存占用,解释“为什么大场景离不了大显存”
关键技术:墨点的形状配方与变色魔术
怎么把一颗圆墨点拉成长条再斜着贴?两步:先沿坐标轴拉伸,再整体旋转。怎么让墨点在转动角度时变色?给贴纸涂一层珠光漆。这两件事,对应 3DGS 里最重要的两个技术细节:协方差矩阵的合法分解与球谐函数着色。
数学上,缩放用一个对角矩阵 S 记录三根轴的半长,旋转用一个由四元数编码出的矩阵 R。协方差矩阵被写成 Σ = R S Sᵀ Rᵀ 的形式,这样无论参数怎么更新,Σ 都天然是对称正定的——也就是说墨点永远是合法的椭球,不会扭曲成“哑铃”或“负体积”。颜色方面,球谐函数用一组正交基函数来近似“颜色随视角变化”,常用 3 阶共 48 个系数,相当于给墨点涂上会随角度变色的珠光漆。
渲染时,三维协方差还要经过视图变换和投影雅可比变换,变成屏幕上的二维椭圆再光栅化;训练过程中,密度控制会不断“分裂”大而模糊的墨点、“克隆”小而密的墨点填补空洞、“剪枝”透明度过低的废墨点。这套组合拳决定了重建细节的上限。
形状靠“缩放 + 旋转”,颜色靠“珠光漆基函数”,两者合体,墨点才能在照片面前以假乱真。
- 缩放矩阵 S对角矩阵,记录椭球三根轴的半长
- 平方 S Sᵀ对角线取平方,保证缩放值非负
- 旋转矩阵 R由四元数转换来的正交旋转矩阵
- 相似变换先缩放后旋转,得到合法对称正定的协方差矩阵
工程部署:把巨幅画作搬进展厅
巨幅贴纸画完工后要搬进展厅:画太大进不了门(显存不够),得先压缩成便携版;上墙后还要让游客秒开、随手就能转着看(渲染加速)。部署 3DGS 的工程考虑,和布置展厅一模一样。
先看硬件门槛:训练端建议 24GB 级显存(如 RTX 3090/4090),因为 Adam 优化器还要额外存一阶、二阶动量,训练时显存比推理更大;常用手段包括限制场景规模、设置合理的稠密化阈值、降低球谐波段数。再看显存管理:推理时场景加载、渲染缓冲都要精打细算,必要时分块加载。压缩量化是当前主流优化方向,把位置、缩放和球谐系数做量化编码,模型体积可缩小 10~20 倍,质量损失很小。
渲染加速方面,3DGS 采用 tile 分块光栅化:把屏幕切块,每块只处理可能投影进来的墨点,配合 GPU 并行,实现百帧级实时。而这一切的数学根基是投影变换——把三维椭球正确地“摊”到屏幕上。
展厅布置的完整流程是:掂量显存预算 → 压缩画作 → 并行快显。三步走完,墨点画就能从实验室跑进产品里。
- 视图变换 W把三维墨点从世界坐标搬到相机坐标系
- 投影雅可比 J透视投影在墨点附近的一阶导数,近似把椭圆压到屏幕平面
- 相似变换左右各乘一次,把三维协方差投影成二维屏幕椭圆
实践建议:开画前的准备清单与验收尺
画家最后会给你一份开工清单:照片怎么拍、墨点怎么调、成品怎么验收,以及什么题材根本不适合墨点画。数据采集是第一道关:环绕场景多圈拍摄,相邻照片重叠建议不低于 70%,避免曝光跳跃与运动模糊;弱纹理或透明区域,最好放一些标定物辅助。调参方面,重点关注学习率、密度控制阈值、球谐波段数,并用验证视角做早停,防止过拟合到训练视角。
质量评估要用“没参与训练”的照片做测试集:计算 PSNR 看像素误差,SSIM 看结构相似,LPIPS 感知相似度更贴近人眼。选型建议很直白:需要实时渲染、场景可编辑,选 3DGS;需要精确网格做测量,选 MVS;做重光照、极端视角等前沿研究,NeRF 仍有价值。下面这条公式就是你验收时的“量尺”。
有了清单和验收尺,你就能判断“这片风景适不适合墨点画”,并在真实项目里做出有理有据的选型。
- 均方误差 MSE渲染图和真实照片逐像素差平方的平均,越小越好
- 最大像素值 MAX8 位图像取 255,作为归一化基准
- 对数刻度用分贝式对数把误差压缩成直观分数,每多 10 倍误差,分数掉 10
AI 应用场景
数字孪生与实景三维
阶段:三维场景重建与数字化
解决的问题:传统 MVS 需要复杂的稠密匹配、网格化和贴图流程,动辄数小时到数天,弱纹理区域还容易破洞;NeRF 训练慢且渲染不实时。3DGS 用无人机环绕照片,十几分钟训练即可产出可实时浏览、可叠加标注的三维场景,适合规划、应急与资产管理。
具体案例:某智慧园区对 2 公里街区采集约 800 张航拍照片,用 COLMAP 求位姿后跑 3DGS,在消费级 GPU 上约 15 分钟生成 400 万颗高斯的街区模型,Web 端 60FPS 浏览,支持楼层选中与漫游。
电商商品建模与 AR 试摆
阶段:商品数字化与 AR 展示
解决的问题:商品 3D 建模过去依赖扫描仪和人工修模,成本高、周期长。用手机绕商品拍 30~60 张照片,3DGS 分钟级出模,质量足以支撑 AR 试摆和商品详情页的交互展示。
具体案例:某家具品牌用转盘加手机拍摄沙发、台灯各 50 张照片,3DGS 训练后导出压缩模型,用户在 App 里把沙发“摆”进客厅,实时查看尺寸与配色是否协调。
影视虚拟制片
阶段:现场场景快速重建与视效合成
解决的问题:影视预演需要把实景快速数字化,供导演和摄影在虚拟引擎里调度机位,MVS 与 NeRF 都太慢。3DGS 能在片场以分钟级完成重建并实时渲染,配合 LED 虚拟拍摄实现“所见即所得”。
具体案例:某摄影棚用一组相机阵列同步采集演员与背景,几分钟重建出可交互的场景模型,灯光师实时调整虚拟光源,导演在虚拟引擎中直接预览机位运动效果,大幅缩短预演周期。
Python 演示
import numpy as np H = W = 32N = 40STEPS = 300LR = 0.4 # 目标画作:左上红色落日 + 底部绿色草地 + 顶部淡蓝天空yy, xx = np.mgrid[0:H, 0:W]target = np.zeros((H, W, 3))target[..., 0] = np.exp(-((xx - 20) ** 2 + (yy - 8) ** 2) / 18.0)target[..., 1] = 0.75 * (yy > 24)target[..., 2] = 0.55 * (yy < 7) rng = np.random.default_rng(0)mu = rng.uniform(0, W, (N, 2))sig = rng.uniform(2.0, 4.5, (N, 2))col = rng.uniform(0, 1, (N, 3))opa = rng.uniform(0.3, 1.0, N) def gauss_field(m, s): gx = np.exp(-(xx - m[0]) ** 2 / (2 * s[0] * s[0])) gy = np.exp(-(yy - m[1]) ** 2 / (2 * s[1] * s[1])) return gx * gy def forward(): img = np.zeros((H, W, 3)) trans = np.ones((H, W)) G = [] T = [] for i in range(N): g = gauss_field(mu[i], sig[i]) a = g * opa[i] G.append(g) T.append(trans) img += col[i] * a[..., None] * trans[..., None] trans = trans * (1 - a) return img, G, T def train_step(): img, G, T = forward() err = np.sign(img - target) S = np.zeros((H, W, 3)) for i in range(N - 1, -1, -1): g = G[i] a = g * opa[i] Tr = T[i] gd = err * (Tr[..., None] * col[i] - S / (1 - a[..., None] + 1e-6)) mu[i, 0] -= LR * (gd * g[..., None] * opa[i] * (xx - mu[i, 0])[..., None] / (sig[i, 0] ** 2)).sum() mu[i, 1] -= LR * (gd * g[..., None] * opa[i] * (yy - mu[i, 1])[..., None] / (sig[i, 1] ** 2)).sum() opa[i] = np.clip(opa[i] - LR * (gd * g[..., None]).sum(), 0.0, 1.0) col[i] = np.clip(col[i] - LR * (err * (Tr * a)[..., None]).sum(axis=(0, 1)), 0.0, 1.0) S += a[..., None] * col[i] * Tr[..., None] if __name__ == "__main__": loss0 = np.abs(forward()[0] - target).mean() for step in range(STEPS): train_step() loss1 = np.abs(forward()[0] - target).mean() print("L1 loss: %.4f -> %.4f" % (loss0, loss1)) art = (forward()[0][..., 0] > 0.35).astype(int) for row in art: print("".join("#" if v else "." for v in row))
target[..., 0] = np.exp(-((xx - 20) ** 2 + (yy - 8) ** 2) / 18.0)在画布左上角定义一颗“红色落日”,作为墨点要复刻的目标img += col[i] * a[..., None] * trans[..., None]墨点按“前方先叠、后方被遮挡”的顺序混合,等价于正文的 alpha 混合公式trans = trans * (1 - a)每叠一颗墨点,更新前方剩余透过率err = np.sign(img - target)L1 损失的梯度:只告诉每颗墨点“往哪个方向调”gd = err * (Tr[..., None] * col[i] - S / (1 - a[..., None] + 1e-6))反向计算这颗墨点不透明度对损失的贡献(链式法则)mu[i, 0] -= LR * (gd * g[..., None] * opa[i] * (xx - mu[i, 0])[..., None] / (sig[i, 0] ** 2)).sum()沿梯度挪动墨点圆心,位置越准、光斑越贴col[i] = np.clip(col[i] - LR * (err * (Tr * a)[..., None]).sum(axis=(0, 1)), 0.0, 1.0)更新墨点颜色并夹到 [0,1],防止“颜料溢出”
常见误区
误区听说 3DGS 和 NeRF 一样都属于神经渲染,就以为它内部也有一堆神经网络层,只是把输出从体素换成了椭球。
正解3DGS 完全不用神经网络。它只是把场景表示成显式高斯椭球集合,用可微光栅化渲染,靠梯度优化椭球参数;球谐函数也只是数学上的基函数而已。真正用网络编码场景的是 NeRF。把“可微 + 梯度优化”误当成“神经网络”是初学者最常见的混淆。
为何常见:3DGS 常与 NeRF 放在一起介绍,“神经渲染”这个关键词先入为主,让人想当然以为两者同源。
误区看演示都是手机短视频直接变 3D,以为输入质量不重要,拍个三四张也能重建得很好。
正解高覆盖、高重叠的多视角照片是硬前提。SfM 一旦因模糊或重复纹理估错位姿,初始化就崩;弱纹理、反光区域的高斯会“糊成一团”或产生浮游伪影。演示视频的背后是严谨的采集规范,不是魔法。
为何常见:只看到“快”与“好”,忽略了前期数据采集的功夫,把训练快误当成容错高。
误区3DGS 训练快、渲染快,那它一定比 NeRF 省显存,手机也能边拍边跑。
正解场景常含 100 万~500 万颗高斯,每颗约 240 字节,训练时 Adam 还要存一阶、二阶动量,显存动辄数 GB,与 NeRF 相当甚至更大。训练快与内存小是两回事,“快”说的是计算路径短,“省”说的是存储路子窄。
为何常见:人们习惯把速度、质量、内存三个维度打包评价,忽略了它们各自独立的瓶颈。
误区渲染是实时的,那重建也应该是实时的,自动驾驶或机器人可以一边移动一边重建地图。
正解渲染是训练完成后的前向过程;训练仍要几分钟到几十分钟,而且依赖 SfM 位姿。要动态更新场景需要 4DGS 等扩展,计算更重。“实时渲染”不等于“实时学习”,一个是放映厅,一个是暗房。
为何常见:混淆了推理(inference)与训练(training)两个阶段,被“实时”二字一叶障目。
面试题
Q1. 3DGS 中,以下哪项不是每个高斯椭球的可优化参数?
- A.位置向量
- B.颜色分量
- C.相机参数← 正确答案
- D.不透明度
答案:C。3DGS 优化的只是场景中墨点的参数(位置、颜色、不透明度、形状等),相机参数由 SfM 预先求出并基本固定。相机参数属于拍摄设备,不属于墨点——墨点不会改变镜头。
Q2. 相比 NeRF 的隐式辐射场,3DGS 的核心区别是什么?
- A.用神经网络的权重记录场景信息
- B.用可微光栅化直接渲染显式椭球← 正确答案
- C.用体素网格存储密度与颜色
- D.用点云配准迭代对齐视角
答案:B。NeRF 把场景压缩进神经网络权重,逐像素沿射线采样积分;3DGS 把场景显式存成高斯椭球集合,一次光栅化完成渲染。A 是 NeRF,C 是体素法,D 是 MVS 的思路。
Q3. 3DGS 流程中,SfM(运动恢复结构)主要负责什么?
- A.估计相机位姿并生成初始稀疏点云← 正确答案
- B.直接输出最终的稠密网格模型
- C.训练一个渲染场景的神经网络
- D.对照片做超分辨率与去噪增强
答案:A。SfM 从多张照片中找匹配特征,同时估计每张照片的相机位姿并输出稀疏点云,这些稀疏点正是高斯初始化的“种子墨点”。它不做稠密网格,也不训练任何网络。
Q4. 协方差矩阵分解 Σ=RS SᵀRᵀ 中,R 矩阵由什么参数转换而来?
- A.三维平移向量
- B.四元数旋转参数← 正确答案
- C.球谐系数向量
- D.各向同性缩放值
答案:B。为保证椭球合法(对称正定),论文把 Σ 拆成 RS SᵀRᵀ,其中 R 由四元数参数化,S 是各轴缩放对角阵。平移向量管位置,球谐系数管颜色,都与形状无关。
Q5. 高斯椭球使用球谐函数(SH)表示颜色的好处是什么?
- A.能表达随视角变化的色彩与光泽← 正确答案
- B.能让训练损失收敛得更平稳
- C.能减少照片采集的数量需求
- D.能自动修复缺失的纹理区域
答案:A。真实场景的颜色会随视角变化(高光、珠光、镜面反射),球谐函数用一组正交基系数近似这种方向变化,相当于给墨点涂上珠光漆。它不改变训练稳定性,也不弥补数据采集。
Q6. 3DGS 相比 NeRF 的优势包括哪些?
- A.训练耗时明显更短← 正确答案
- B.渲染帧率接近实时← 正确答案
- C.显存占用显著更小
- D.表示具有显式可编辑性← 正确答案
答案:ABD。3DGS 不用逐射线采样,训练一般几分钟,渲染可达上百帧,且椭球可直接增删改查。但显存占用并不小,反而常是部署瓶颈,C 的说法与事实相反。
Q7. 训练中的“高斯密度控制”对过重建区域(大而模糊的高斯)的常见处理是什么?
- A.将大高斯分裂成多个小高斯← 正确答案
- B.将小高斯克隆填充空洞区域
- C.直接降低整体场景的不透明度
- D.冻结该区域高斯参数的更新
答案:A。密度控制三件套:对“大而糊”的高斯做分裂,对“小而密”的高斯做克隆以补充欠重建,对透明度过低的做剪枝删除。题干问的是过重建,对应分裂。
Q8. 3DGS 在实际应用中存在的局限有哪些?
- A.场景高斯数量多导致显存开销大← 正确答案
- B.极端视角外推时渲染质量下降← 正确答案
- C.透明反光表面往往重建不理想← 正确答案
- D.完全不需要任何相机位姿数据
答案:ABC。数百万颗高斯加 Adam 动量副本身,显存轻松上 GB;对没见过的视角,椭球外推缺少约束;玻璃、水面等透明反光表面难以用不透明椭球逼近。D 完全说反——3DGS 严重依赖 SfM 位姿。
Q9. 3DGS 沿视线从前到后合成高斯颜色的正确公式是哪一个?
- A.C=ΣcᵢαᵢΠ(1-αⱼ) 加权混合← 正确答案
- B.C=ΠcᵢαᵢΣ(1-αⱼ) 累乘混合
- C.C=Σcᵢ(1-αᵢ)Παⱼ 反向混合
- D.C=mean(cᵢαᵢ) 平均混合
答案:A。沿视线排序后,每颗墨点的可见率等于前方所有墨点“都没挡住它”的乘积,最终颜色是 Σ cᵢαᵢΠ(1-αⱼ)。B、C 把求和与连乘的位置弄反,D 的平均混合不符合真实遮挡逻辑。
Q10. 关于 PSNR 指标,下列说法正确的是哪些?
- A.数值越高说明重建越接近真值← 正确答案
- B.数值越低说明图像误差越小
- C.比较前需渲染同角度图像← 正确答案
- D.只能衡量结构相似不能比较亮度
答案:AC。PSNR 由 MSE 换算而来,数值越高=误差越小=越接近真值;比较时必须让渲染视角与真值照片一致。它衡量的是逐像素误差而非结构,所以 D 说反了。