☰
3DGS三维高斯泼溅实战:从NeRF到实时渲染的完整指南
2026/10/1 9:32:29 网站建设 项目流程

1. 从NeRF到3DGS:一场渲染效率的降维打击

2023年夏天,当整个三维重建圈子还在为NeRF那套体渲染管线反复调参、苦等几十小时训练结果的时候,SIGGRAPH上冒出来一篇叫3D Gaussian Splatting的论文,直接在圈子里炸了锅。我印象特别深,当时我们组正在做一个室内场景的快速重建项目,用NeRF跑一个普通房间,单卡A100训练了将近二十个小时,渲染一帧还要等好几秒。结果3DGS出来之后,同样的场景,训练时间压缩到十几分钟,渲染帧率直接飙到一百以上。那种感觉就像你一直以为从北京到上海只能坐绿皮火车,突然有人告诉你高铁已经修好了。

3DGS全称3D Gaussian Splatting,中文一般叫三维高斯泼溅或者三维高斯散射。它的核心思路和NeRF完全不同——NeRF用神经网络隐式地表示整个场景的密度场和颜色场,而3DGS用一大堆三维高斯椭球体来显式地表示场景。每个高斯椭球有自己的位置、形状(协方差矩阵)、不透明度和颜色(用球谐函数表示)。渲染的时候,把这些高斯椭球投影到屏幕上,然后做alpha混合,就能得到最终的图像。这个思路其实不新鲜,九十年代就有类似的想法,但当时没有好的优化手段,效果很差。3DGS的贡献在于,它设计了一套完整的可微渲染管线,让这些高斯椭球的参数可以通过反向传播来优化,同时用了一套基于tile的快速光栅化方案,把渲染速度做到了实时。

那它到底解决了什么问题?简单说,它解决了NeRF在实际落地中最要命的三个问题:训练太慢、渲染太慢、编辑太难。NeRF的训练通常需要几小时到几十小时,渲染一帧要几秒甚至几十秒,而且因为场景信息被编码在神经网络的权重里,你想改个东西几乎无从下手。3DGS把训练时间压到几分钟到几十分钟,渲染速度做到实时(1080p下超过100FPS),而且因为场景是显式表示的,你可以直接选中某个高斯椭球去移动、删除、缩放,编辑起来非常直观。这三个问题一解决,三维重建从实验室走向实际应用的门就打开了。

如果你正在做三维重建、SLAM、数字孪生、虚拟现实或者任何需要快速把真实场景搬到数字世界里的项目,3DGS都值得你花时间深入研究。哪怕你之前完全没接触过神经渲染,只要对三维图形学有基本了解,跟着代码跑一遍也能很快上手。接下来我会从它解决的问题出发,把核心原理、实操流程、常见坑点都拆开讲清楚。

2. 核心问题拆解:NeRF到底卡在哪里

2.1 NeRF的隐式表示为什么慢

要理解3DGS解决了什么问题,得先搞清楚NeRF为什么慢。NeRF的核心是一个多层感知机(MLP),输入是一个三维坐标加上一个观察方向,输出是这个点的密度和颜色。渲染一张图的时候,需要从相机光心出发,对每个像素发射一条光线,在这条光线上采样几百个点,每个点都要过一遍MLP,然后做体渲染积分。一张1080p的图有兩百多万个像素,每个像素采样几百个点,那就是几亿次MLP前向推理。这还只是渲染,训练的时候还要反向传播,计算量更大。

我拿一个具体例子来说明。假设你用NeRF跑一个中等复杂度的场景,比如一个摆了几十件物品的客厅。训练集大概一百多张图,分辨率降到800x600。在单张RTX 3090上,用标准的NeRF管线,大概需要12到24小时才能收敛到一个可用的效果。渲染的时候,800x600分辨率下,每帧大概需要0.5到2秒。这个速度做离线渲染勉强能接受,但如果你想做交互式的场景浏览,或者把重建结果用到VR里,那完全不够看。

更麻烦的是,NeRF的隐式表示让场景编辑变得极其困难。你想把场景里的一个椅子挪个位置?对不起,椅子的信息分散在MLP的几十万个权重里,你根本不知道改哪些权重能实现这个操作。你想把场景里的某个物体删掉?同样无从下手。这就导致NeRF虽然重建质量很高,但在需要交互和编辑的场景里几乎没法用。

2.2 3DGS的显式表示如何破局

3DGS换了一个完全不同的思路。它不用神经网络来表示场景,而是用一堆三维高斯椭球。每个高斯椭球有这些参数:位置(三个浮点数)、协方差矩阵(决定椭球的形状和朝向,通常用四元数加缩放来表示,共七个浮点数)、不透明度(一个浮点数)、颜色(用球谐函数表示,根据阶数不同,通常是三到四十八个浮点数)。一个中等复杂度的场景,大概需要一百万到五百万个高斯椭球。这些参数都是显式存储的,你可以直接读取、修改、删除。

渲染的时候,3DGS把这些高斯椭球按照深度排序,然后投影到屏幕上。每个高斯椭球在屏幕上形成一个二维高斯分布,然后按照从后往前的顺序做alpha混合。这个过程可以用GPU的光栅化管线高效实现,因为每个高斯椭球的影响范围是局部的,不需要像NeRF那样对每个像素做几百次MLP推理。这就是为什么3DGS能跑到实时帧率。

训练的时候,3DGS用一组已知相机位姿的图片作为输入。它从一组稀疏点云开始(通常用COLMAP的SfM结果初始化),然后通过可微渲染计算渲染图像和真实图像的差异,反向传播来优化每个高斯椭球的参数。同时,它还设计了一套自适应密度控制机制:在重建不好的区域,分裂或者克隆高斯椭球;在过度重建的区域,删除多余的高斯椭球。这套机制让高斯椭球的分布能自动适应场景的复杂度。

2.3 训练和渲染速度的量化对比

光说快可能不够直观,我拿实际跑过的数据来对比。同一个场景,大概一百二十张图,分辨率1600x1200,用COLMAP做完SfM之后:

指标NeRF(标准管线)3DGS(官方实现)
训练时间18-24小时15-25分钟
渲染帧率(1080p)0.5-2 FPS100-150 FPS
显存占用(训练)8-12 GB6-10 GB
显存占用(渲染)4-6 GB1-2 GB
场景编辑几乎不可能直接操作高斯椭球
重建质量(PSNR)31-33 dB30-32 dB

从表里能看出来,3DGS在训练和渲染速度上是碾压性的优势,重建质量略低一点但差距不大。显存占用也更友好,尤其是渲染阶段,1-2GB的显存意味着你可以在移动端或者VR头显上跑。场景编辑能力更是NeRF完全没法比的。

注意:这里的训练时间对比是基于单张RTX 3090,实际时间会随场景复杂度、图片数量、迭代次数变化。3DGS官方实现默认跑30000次迭代,大概15-25分钟。如果你把迭代次数降到7000次,5-8分钟就能出一个粗略结果,质量会差一些但可以用来快速预览。

3. 3DGS核心技术点深度拆解

3.1 三维高斯椭球的数学表示

3DGS里每个高斯椭球的数学形式是这样的:给定一个三维坐标x,这个高斯椭球在x处的值由下面的公式给出:

G(x) = exp(-0.5 * (x - μ)^T * Σ^(-1) * (x - μ))

其中μ是椭球的中心位置,Σ是协方差矩阵。协方差矩阵必须是半正定的,为了保证这一点,3DGS把Σ分解成Σ = R * S * S^T * R^T,其中R是旋转矩阵(用四元数表示),S是缩放矩阵(对角矩阵,对角线元素是三个轴的缩放因子)。这样优化的时候只需要优化四元数和缩放因子,不用直接优化协方差矩阵,避免了矩阵不正定的问题。

这个分解还有一个好处:它让椭球的形状和朝向变得可解释。四元数控制椭球的旋转,缩放因子控制椭球在三个轴上的长度。你可以直接调整这些参数来改变椭球的形状,比如把一个扁平的椭球拉长,或者旋转一个椭球让它对齐某个平面。

球谐函数用来表示颜色,这是为了处理视角相关的外观变化。比如金属表面在不同角度下颜色不一样,用球谐函数可以表示这种变化。球谐函数的阶数越高,能表示的视角相关效果越复杂。3DGS默认用三阶球谐函数,每个颜色通道有16个系数,三个通道一共48个系数。如果你不需要视角相关效果,可以用零阶球谐函数,每个通道只有一个系数,参数数量大幅减少。

3.2 可微光栅化管线的实现细节

3DGS的渲染管线是整个方法里最核心的工程贡献。它把三维高斯椭球投影到屏幕上的过程做成了可微的,这样才能通过反向传播来优化参数。具体来说,渲染一张图分这几步:

第一步,视锥剔除。把那些在相机视锥之外的高斯椭球直接扔掉,减少计算量。这一步能过滤掉大概一半到三分之二的高斯椭球,取决于相机朝向。

第二步,投影到屏幕空间。把每个三维高斯椭球的协方差矩阵投影到二维屏幕空间,得到一个二维协方差矩阵。这个投影过程用到了雅可比矩阵,因为透视投影是非线性的,需要用局部线性近似。投影之后,每个高斯椭球在屏幕上就是一个二维高斯分布。

第三步,按tile分块。把屏幕分成16x16的tile,每个tile独立处理。对每个tile,找出所有和这个tile有重叠的高斯椭球,按深度排序。这一步是并行的,每个tile可以独立计算,充分利用GPU的并行能力。

第四步,alpha混合。对每个像素,按照从后往前的顺序,把覆盖这个像素的高斯椭球做alpha混合。混合公式和传统的体渲染类似,但因为是显式表示,不需要采样,直接按排序后的顺序累加就行。

这套管线的关键优化在于tile分块和排序。因为每个tile只处理和自己相关的高斯椭球,计算量大幅减少。而且排序是在tile级别做的,比全局排序快很多。官方实现里,这一步是用CUDA写的自定义光栅化器,速度非常快。

3.3 自适应密度控制的策略

3DGS的另一个核心创新是自适应密度控制。训练过程中,高斯椭球的分布会动态调整,让它们更好地覆盖场景的细节。具体来说,每隔一定迭代次数(默认是100次),会做一次密度控制:

对于重建不好的区域(梯度大的高斯椭球),如果椭球太小,就克隆一个相同大小的椭球;如果椭球太大,就分裂成两个更小的椭球。克隆和分裂的区别在于,克隆是在原位置复制一个椭球,适合那些需要更多细节但位置已经对了的区域;分裂是把一个大的椭球拆成两个小的,适合那些覆盖范围太大导致细节丢失的区域。

对于过度重建的区域(不透明度太低的高斯椭球),直接删除。不透明度太低意味着这个椭球对最终图像的贡献很小,留着只是浪费计算资源。

这套机制让高斯椭球的数量能自动适应场景复杂度。简单场景可能只需要几十万个椭球,复杂场景可能需要几百万个。而且椭球的分布会集中在细节丰富的区域,比如物体的边缘、纹理复杂的表面,而平坦区域只需要少量大椭球就能覆盖。

实操心得:密度控制的参数对最终效果影响很大。默认的densify_grad_threshold是0.0002,如果你发现重建结果在细节区域有模糊,可以把这个值调小,让更多椭球被克隆或分裂。但调太小会导致椭球数量爆炸,训练变慢,显存占用增加。我一般会先跑默认参数,看效果再微调。

4. 实操流程:从图片到实时渲染的完整链路

4.1 环境准备与依赖安装

3DGS的官方实现依赖CUDA,所以你需要一张NVIDIA显卡。官方推荐CUDA 11.8或更高版本,我实测CUDA 12.x也能跑,但需要对应版本的PyTorch。显卡方面,RTX 3060 12GB就能跑中等场景,RTX 4090或者A100跑大场景更从容。显存建议至少8GB,复杂场景建议12GB以上。

安装步骤大概是这样:

# 创建conda环境 conda create -n gaussian_splatting python=3.10 conda activate gaussian_splatting # 安装PyTorch(根据你的CUDA版本选择) pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装其他依赖 pip install plyfile tqdm opencv-python # 克隆官方仓库 git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive # 编译CUDA扩展 cd gaussian-splatting pip install submodules/diff-gaussian-rasterization pip install submodules/simple-knn

编译CUDA扩展的时候最容易出问题。常见错误是CUDA版本和PyTorch版本不匹配,或者gcc版本太新导致编译失败。如果你用的是Ubuntu 20.04,默认gcc是9.4,一般没问题。Ubuntu 22.04默认gcc是11,可能需要降级到10或者9。另外,如果你在WSL2里跑,需要确保WSL2的CUDA驱动装好了,nvidia-smi能正常输出。

注意:编译diff-gaussian-rasterization的时候,如果报错说找不到cuda_runtime.h,检查一下CUDA_HOME环境变量有没有设对。一般是/usr/local/cuda-11.8或者/usr/local/cuda-12.x。设好之后重新编译。

4.2 数据准备与COLMAP位姿估计

3DGS需要输入一组图片和对应的相机位姿。相机位姿通常用COLMAP做SfM来估计。如果你有自己的数据集,比如用手机拍的视频,可以抽帧成图片,然后跑COLMAP。COLMAP的安装可以用apt:

sudo apt install colmap

跑COLMAP的流程是:先做特征提取,然后做特征匹配,最后做增量式SfM。命令行大概是这样:

# 特征提取 colmap feature_extractor --database_path database.db --image_path images # 特征匹配 colmap exhaustive_matcher --database_path database.db # 稀疏重建 mkdir sparse colmap mapper --database_path database.db --image_path images --output_path sparse

跑完之后,sparse/0/目录下会有cameras.bin、images.bin、points3D.bin三个文件。3DGS的官方代码里有一个convert.py脚本,可以把COLMAP的输出转成3DGS需要的格式。转换之后,数据目录下会有images/和sparse/0/两个子目录。

如果你没有自己的数据,可以用官方提供的示例数据集,比如Mip-NeRF 360或者Tanks and Temples。这些数据集已经做好了COLMAP,直接下载就能用。

实操心得:COLMAP的位姿估计质量直接影响3DGS的重建效果。如果COLMAP跑出来的位姿不准,3DGS训练出来的结果会模糊或者有鬼影。我一般会检查COLMAP的reprojection error,如果平均误差超过1个像素,就要考虑重新跑或者调整COLMAP的参数。另外,拍摄的时候尽量保证图片有足够的重叠,相邻图片之间至少要有60%的重叠区域。

4.3 训练参数配置与启动

3DGS的训练脚本是train.py,基本用法:

python train.py -s /path/to/data -m /path/to/output

其中-s指定数据目录,-m指定输出目录。训练过程中,每7000次迭代会保存一次checkpoint,最终输出是point_cloud/iteration_30000/point_cloud.ply,这个文件包含了所有高斯椭球的参数。

关键参数有几个:

  • --iterations:总迭代次数,默认30000。降到7000可以快速预览,质量会差一些。
  • --densify_grad_threshold:密度控制的梯度阈值,默认0.0002。调小会让更多椭球被克隆或分裂。
  • --densify_until_iter:在多少次迭代之前做密度控制,默认15000。之后不再增加椭球数量,只优化参数。
  • --position_lr_init:位置的学习率,默认0.00016。如果训练不稳定,可以调小。
  • --sh_degree:球谐函数阶数,默认3。降到0可以大幅减少参数数量,但会丢失视角相关效果。

训练过程中可以用TensorBoard监控loss曲线:

tensorboard --logdir /path/to/output

loss曲线一般会在前几千次迭代快速下降,然后逐渐趋于平稳。如果loss震荡很厉害,可能是学习率太大;如果loss下降很慢,可能是学习率太小或者密度控制参数不合适。

4.4 渲染与可视化

训练完之后,可以用官方提供的render.py来渲染测试视角:

python render.py -m /path/to/output

渲染结果会保存在output目录下的train/和test/子目录里。如果你想实时交互式查看,可以用SIBR Viewer,这是官方提供的一个实时查看器,支持Windows和Linux。编译SIBR Viewer需要CMake和OpenGL,编译过程稍微麻烦一点,但编译好之后用起来很爽,可以实时旋转、缩放、平移视角,帧率能跑到100以上。

如果你不想编译SIBR Viewer,也可以用一些第三方的查看器,比如antimatter15的splat viewer,是一个基于WebGL的网页查看器,直接把ply文件拖进去就能看。不过网页查看器的性能不如原生查看器,复杂场景可能会卡。

注意:渲染的时候,如果发现某些视角下有明显的伪影或者漂浮物,可能是训练不充分或者密度控制没做好。可以尝试增加迭代次数,或者调整densify_grad_threshold。另外,如果场景里有大面积的无纹理区域(比如白墙),3DGS可能会在这些区域产生一些漂浮的高斯椭球,这是正常现象,可以通过后处理过滤掉。

5. 常见问题与排查技巧实录

5.1 训练不收敛或者loss震荡

这是最常见的问题之一。表现是loss曲线上下震荡,或者loss下降很慢,最终重建结果模糊。原因可能有几个:

学习率太大。3DGS的位置学习率默认是0.00016,如果场景尺度比较大,这个学习率可能偏大。可以尝试降到0.0001或者0.00008。另外,位置学习率有一个指数衰减策略,默认每1000次迭代衰减到原来的0.01倍,这个衰减策略对训练稳定性很重要,不要随便改。

密度控制太激进。如果densify_grad_threshold设得太小,大量椭球被克隆或分裂,参数数量爆炸,训练会变得不稳定。建议先用默认值0.0002跑一遍,看效果再调。

COLMAP位姿不准。如果COLMAP的位姿有较大误差,3DGS训练的时候会试图用高斯椭球去补偿位姿误差,导致重建结果模糊。检查COLMAP的reprojection error,如果太大就重新跑COLMAP。

5.2 显存不足(OOM)

3DGS训练的时候显存占用和场景复杂度、图片分辨率、椭球数量都有关系。如果显存不够,可以尝试这些方法:

降低图片分辨率。3DGS默认会把图片降采样到1600像素宽,你可以改成1200或者800。在train.py里有一个--resolution参数,设成-1表示用原始分辨率,设成1表示降采样到1/2,设成2表示降采样到1/4。

减少椭球数量。把densify_grad_threshold调大,比如从0.0002调到0.0004,让更少的椭球被克隆或分裂。或者把densify_until_iter调小,比如从15000调到10000,提前停止密度控制。

用更小的球谐函数阶数。把sh_degree从3降到1或者0,参数数量大幅减少。零阶球谐函数每个颜色通道只有一个系数,相比三阶的16个系数,参数数量减少了90%以上。

5.3 渲染结果有漂浮物或伪影

漂浮物是3DGS的一个常见问题,尤其是在场景边缘或者无纹理区域。这些漂浮的高斯椭球通常是因为训练不充分或者密度控制不合理产生的。解决方法:

增加训练迭代次数。默认30000次可能不够,可以加到40000或者50000。但要注意,迭代次数太多可能会导致过拟合,测试视角的效果反而变差。

调整密度控制参数。把densify_grad_threshold调大,减少不必要的克隆和分裂。或者把densify_until_iter调小,让椭球数量早点稳定下来。

后处理过滤。训练完之后,可以写一个脚本过滤掉那些不透明度太低或者尺寸异常的高斯椭球。官方代码里有一个filter.py的示例,可以参考。

5.4 CUDA版本兼容性问题

CUDA版本兼容性是3DGS部署中最头疼的问题之一。官方代码是在CUDA 11.8下开发的,如果你用CUDA 12.x,可能会遇到编译错误或者运行时错误。常见问题和解决方法:

编译diff-gaussian-rasterization时报错。检查PyTorch的CUDA版本和系统CUDA版本是否一致。用python -c "import torch; print(torch.version.cuda)"查看PyTorch的CUDA版本,用nvcc --version查看系统CUDA版本。如果不一致,重新安装对应版本的PyTorch。

运行时提示CUDA error: no kernel image is available for execution on the device。这是因为编译的时候用的CUDA架构和你的显卡架构不匹配。在setup.py里有一个compute_capability参数,需要设成你显卡的架构。比如RTX 4090是8.9,RTX 3090是8.6,RTX 2080是7.5。设好之后重新编译。

WSL2下CUDA不可用。确保WSL2的CUDA驱动装好了,nvidia-smi能正常输出。如果nvidia-smi报错,可能需要更新Windows端的NVIDIA驱动,或者重新安装WSL2的CUDA toolkit。

5.5 常见问题速查表

问题现象可能原因解决方法
训练loss震荡学习率太大降低position_lr_init到0.0001
重建结果模糊COLMAP位姿不准检查reprojection error,重新跑COLMAP
显存不足椭球数量太多降低分辨率,调大densify_grad_threshold
渲染有漂浮物训练不充分增加迭代次数,后处理过滤
CUDA编译报错版本不匹配检查PyTorch和系统CUDA版本
渲染帧率低椭球数量太多降低sh_degree,过滤不透明度低的椭球
场景边缘有伪影密度控制太激进调大densify_grad_threshold
训练时间太长迭代次数太多降到7000次快速预览

6. 3DGS在SLAM和机器人领域的落地思考

6.1 3DGS与SLAM的结合点

SLAM(同步定位与建图)和3DGS的结合是最近的一个热门方向。传统的视觉SLAM用稀疏点云或者稠密点云来建图,地图的表示能力有限,渲染出来的效果比较粗糙。3DGS的显式表示和实时渲染能力,让SLAM系统可以构建出高质量、可实时渲染的稠密地图。

具体来说,3DGS可以用在SLAM的几个环节:一是建图,用3DGS替代传统的点云地图,构建出更逼真的三维场景;二是渲染,用3DGS的实时渲染能力做AR/VR应用,把虚拟物体叠加到真实场景里;三是重定位,用3DGS渲染出来的图像做特征匹配,提高重定位的鲁棒性。

不过3DGS和SLAM的结合还面临一些挑战。3DGS的训练需要已知的相机位姿,而SLAM的位姿估计是在线的,两者需要联合优化。另外,3DGS的训练速度虽然比NeRF快很多,但要做到在线增量式训练,还需要进一步优化。目前有一些工作在做这方面的探索,比如用滑动窗口的方式增量式地更新高斯椭球,或者用因子图把位姿估计和3DGS训练联合起来优化。

6.2 在机器人导航中的应用潜力

机器人导航需要实时的环境感知和地图构建。传统的激光雷达SLAM或者视觉SLAM构建的地图通常是栅格地图或者点云地图,对于路径规划和避障够用,但对于人机交互或者远程操作来说,地图的可视化效果不够直观。3DGS构建的高质量三维地图,可以让操作员通过VR头显沉浸式地查看机器人周围的环境,提高远程操作的效率和安全性。

另外,3DGS的实时渲染能力也可以用在机器人的仿真环境里。传统的机器人仿真用CAD模型或者网格模型,构建成本高,而且和真实环境的差距大。用3DGS重建真实环境,可以快速构建出高保真的仿真场景,用于强化学习训练或者算法验证。

不过3DGS在机器人上的部署还面临算力限制。机器人的计算平台通常是嵌入式GPU或者NPU,算力有限。3DGS的渲染虽然比NeRF快很多,但在嵌入式平台上跑实时渲染还是有压力。目前有一些工作在优化3DGS的渲染效率,比如用更紧凑的高斯表示、更高效的光栅化算法,或者用模型压缩技术减少椭球数量。

6.3 自己制作数据集的实操建议

如果你想用自己的数据跑3DGS,比如用手机拍一段视频然后重建,有几个实操建议:

拍摄的时候尽量保持相机稳定,避免剧烈晃动。3DGS对位姿误差比较敏感,晃动太厉害会导致COLMAP位姿估计不准。可以用手机稳定器或者手持云台。

拍摄轨迹尽量覆盖场景的各个角度。3DGS需要从多个视角观察同一个区域才能重建出好的效果。如果只从一个方向拍,背面的区域重建质量会很差。

光线尽量均匀,避免强烈的阴影或者高光。3DGS对光照变化比较敏感,如果拍摄过程中光照变化太大,重建结果会有颜色不一致的问题。

图片数量控制在100到300张之间。太少会导致覆盖不足,太多会导致COLMAP和3DGS的训练时间变长。如果场景比较大,可以分区域拍摄,然后分别重建再合并。

抽帧的时候,相邻帧之间要有足够的重叠。一般建议每秒钟抽2到5帧,具体取决于相机的移动速度。移动快就多抽几帧,移动慢就少抽几帧。

实操心得:我自己用iPhone拍过几个场景,发现用4K 60fps拍摄然后每0.5秒抽一帧,效果比较好。抽帧之后用COLMAP跑SfM,一般能跑到0.5到1个像素的reprojection error。如果error太大,可以尝试用COLMAP的bundle adjustment重新优化,或者手动剔除一些质量差的图片。

7. 我踩过的坑和最后分享的几个技巧

7.1 那些让我熬夜的坑

第一个坑是CUDA版本。我第一次装3DGS的时候,系统里装的是CUDA 12.1,PyTorch装的是CUDA 11.8的版本,编译diff-gaussian-rasterization的时候一直报错。折腾了大半天才发现是版本不匹配。后来把PyTorch换成CUDA 12.1的版本,重新编译就好了。所以一定要确保PyTorch的CUDA版本和系统CUDA版本一致。

第二个坑是COLMAP的位姿质量。有一次我用手机拍了一个房间,跑完COLMAP之后直接扔给3DGS训练,结果重建出来全是模糊的。后来检查COLMAP的reprojection error,发现平均误差有2.3个像素,明显偏大。重新跑了一遍COLMAP,把一些模糊的图片剔除了,error降到0.8个像素,3DGS的重建效果就好了很多。

第三个坑是显存不足。有一次跑一个比较大的场景,图片分辨率是4000x3000,椭球数量涨到八百万,24GB的RTX 3090都爆显存了。后来把分辨率降到1600x1200,椭球数量控制在三百万以内,就顺利跑完了。所以分辨率不是越高越好,要根据显存和场景复杂度权衡。

7.2 几个提升效果的小技巧

第一个技巧是分阶段训练。先用低分辨率(比如800x600)快速跑7000次迭代,得到一个粗略的场景结构,然后再用高分辨率(1600x1200)跑30000次迭代做精细优化。这样比直接跑高分辨率快很多,而且最终效果差不多。

第二个技巧是手动调整密度控制参数。默认的densify_grad_threshold是0.0002,对于细节丰富的场景,可以降到0.0001,让更多椭球被克隆或分裂。对于大面积平坦的场景,可以升到0.0004,减少不必要的椭球。我一般会先跑默认参数,看重建结果,如果细节区域模糊就调小,如果椭球数量太多就调大。

第三个技巧是后处理过滤漂浮物。训练完之后,可以写一个简单的脚本,读取point_cloud.ply,过滤掉那些不透明度低于0.05或者尺寸异常(比如某个轴的缩放因子大于场景尺度的10%)的高斯椭球。过滤之后重新保存,渲染效果会干净很多。

第四个技巧是用TensorBoard监控训练过程。除了loss曲线,还可以监控椭球数量的变化。正常情况下,椭球数量会在前15000次迭代逐渐增加,然后趋于稳定。如果椭球数量一直增长不收敛,说明密度控制参数太激进,需要调大densify_grad_threshold。

7.3 后续可以扩展的方向

3DGS本身还有很多可以优化的地方。比如动态场景的重建,目前3DGS主要针对静态场景,如果要处理动态场景,需要引入时间维度,让高斯椭球的位置和形状随时间变化。已经有一些工作在探索这个方向,比如用变形场或者时间条件的高斯椭球。

另一个方向是压缩。3DGS的模型文件通常比较大,一个中等场景的point_cloud.ply可能有几百MB到几GB。如果要部署到移动端或者网页端,需要压缩。目前有一些工作在用量化、剪枝、熵编码等方法来压缩3DGS模型,可以把模型大小压缩到原来的十分之一甚至更小。

还有一个方向是和SLAM的深度融合。目前3DGS和SLAM的结合还比较初步,大部分工作是把SLAM的位姿输出给3DGS做离线重建。未来如果能把3DGS的训练嵌入到SLAM的在线流程里,实现实时的增量式重建,那对于AR/VR和机器人应用来说会非常有价值。

我个人在实际操作中的体会是,3DGS最大的价值在于它把高质量三维重建的门槛降到了普通开发者也能接受的程度。以前做三维重建要么用昂贵的激光扫描设备,要么用复杂的多视图立体视觉管线,要么用训练慢到让人崩溃的NeRF。3DGS用一张消费级显卡、几十分钟的训练时间,就能得到一个可以实时渲染的高质量三维场景。这个效率提升是革命性的,它让三维重建从实验室走向了实际应用。如果你还没试过3DGS,强烈建议找一个周末跑一遍官方示例,感受一下从图片到实时三维场景的完整流程。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询