
如果你最近刷GitHub或arXiv大概率能感受到3DGS3D Gaussian Splatting这股热浪有多猛。作为2023年诞生、2024年彻底爆发、2025年依然霸榜的3D重建与新视角合成技术它用实时的渲染速度和让人直呼“这怕不是照片”的细节还原度把NeRF按在地上摩擦了一轮又一轮。但我发现一个现象网上讨论3DGS的人不少真正能从零开始把环境配好、把训练跑通的人却不多。很多人卡在CUDA版本不匹配、子模块拉不下来、COLMAP数据格式报错这些坎上最后草草放弃。这篇文章就是来填这个坑的。我会从“一张显卡到底够不够用”讲起走完环境准备、源码编译、数据制作、训练调参、质量评估的全部流程最后把我在实操里踩过的编译错误、显存溢出、数据格式问题一并拿出来说清楚。内容面向的是“想真正用3DGS做出结果”的人无论你是搞科研、做数字人、还是纯粹想重建自己拍的照片这份指南都应该能帮你少走很多弯路。1. 为什么是3DGS从NeRF到实时渲染的路线转折1.1 完全不同的场景表达方式3DGS的全称是3D Gaussian Splatting核心思想并不难理解用一个一个三维高斯分布的小“椭球”来拼接出完整的场景。每一个高斯球都带有自己的位置、旋转、缩放、颜色和不透明度属性成千上万个这样的球叠在一起就构成了对场景的连续表达。渲染的时候这些高斯球会被投影到2D像平面上按照深度排序后做alpha blending合成颜色。这个过程是可微的所以模型可以通过梯度下降不断调整每个高斯球的参数让渲染图和真实照片越来越接近。我第一次看这篇论文3D Gaussian Splatting for Real-Time Radiance Field RenderingKerbl等人SIGGRAPH 2023时的感受是这几乎是“暴力美学”的典范——不搞隐式神经场那套复杂推理直接把场景拆成一堆可学习的小单元然后用传统光栅化管线做渲染。但正是这种设计让它同时拿下了两个看似矛盾的优势训练速度快分钟到小时级、渲染速度极快实时。相比之下NeRF是隐式表达渲染时要沿光线采样几百个点逐个查询MLP网络一张图就要算很久。3DGS则完全绕开了这条路径把问题转化成了“优化一堆显式高斯球的参数”渲染管线高度接近传统图形学自然快得飞起。1.2 从算法到工程3DGS技术栈的这几层现在讨论3DGS已经不能只看原版论文了。经过两年多的发展围绕它的技术栈已经非常厚实我简单梳理一下原版3DGS最经典的baseline训练和渲染管线稳定适合入门研究算法细节。前馈式3DGS用深度神经网络直接从多视角图片预测3DGS参数省去逐场景优化代表工作如SplatFormer、MVSplat等。这是目前学术界最热的方向之一。高效压缩版3DGS原版一个场景可能要几百MB压缩工作能压到几MB级别代表如CompGS、Scaffold-GS等。动态3DGS把时间维度引入高斯球用于动态场景重建和4D渲染。这篇文章会以原版3DGS为主线因为它是理解所有衍生工作的基础也是大多数人在训练自己的数据集时最常用的方案。1.3 一个关键认知3DGS不是“深度学习”那一套这里我想先说一个容易误导新手的地方。虽然3DGS用到了PyTorch、梯度下降、自动微分这些深度学习工具但它本质上更像是一个“每场景优化”的图形学问题——每个场景都需要单独训练一组高斯球训练好的模型不能泛化到新场景。这意味着两件事第一你不需要像训练目标检测模型那样准备成千上万张图的训练集一个场景通常几十到几百张照片就够了第二每个新场景都要重新训练一次没有“预训练模型”可以直接部署。把这个认知框定好后面理解整个安装和训练流程就顺了。2. 先别急着敲命令显卡、驱动和CUDA版本的匹配策略2.1 4060到底够不够用——显存焦虑的真相热词榜上“做3dgs用4060够吗”这个问题我得正面回答一下够而且相当够。但前提是你要清楚自己在什么分辨率、什么迭代次数下训练。3DGS训练时的显存需求主要取决于三块高斯球的数量、训练图像的分辨率、以及渲染过程中的梯度缓存。拿一个典型的Mip-NeRF 360风格数据集来说场景大概用100~300张图迭代30k次8GB显存是可以跑完的只是偶尔会碰到显存告急。如果你用的是4060 Ti 16GB或者4070那基本可以放心造。我实测下来的一组参考数据显卡显存可处理的最大图像分辨率建议迭代次数GTX 1660 / 20606~8GB1602x1170左右20k~30kRTX 4060 / 4060 Ti 8G8GB1602x117030kRTX 4070 / 4070 Ti12GB2048x153630k~40kRTX 4090 / A500024GB4096x3072以上40k需要说明的是分辨率不是越高越好。3DGS对图像分辨率非常敏感分辨率不足会导致场景细节丢失分辨率过高又会让显存瞬间爆炸。1602x1170是官方默认数据集的常见尺寸对于绝大多数场景已经够用。2.2 CUDA版本选择的“三角关系”3DGS的安装有一个绕不开的三角关系显卡驱动版本、CUDA版本、PyTorch版本。这三者必须相互匹配否则编译阶段就会翻车。我的建议是先确定你的显卡驱动支持的最高CUDA版本然后往下选一个稳定的版本号。比如驱动是545或以上那CUDA 11.8和12.1都可以用如果驱动是530以下建议老老实实装CUDA 11.8。检查驱动支持的CUDA版本在终端运行nvidia-smi看右上角的“CUDA Version”就是驱动支持的最高版本。这个数值是上限你装的CUDA Toolkit版本不能超过它。2.3 Ubuntu系统的推荐配置虽然3DGS官方没有强制指定系统版本但我个人强烈推荐Ubuntu 20.04或22.04配上Python 3.8~3.10。不是说我歧视Windows而是3DGS的几个CUDA扩展模块diff-gaussian-rasterization、simple-knn在Linux下的编译路径最成熟出问题也最好查。Windows下编译有一定概率踩到MSVC和C标准库的坑新手会非常痛苦。如果你手头只有Windows机器有两个选择装WSL2跑Ubuntu或者用Docker镜像。前者更简单直接后者环境隔离更干净。无论哪种建议先看一遍官方README的System Requirements小节再动手。3. 源码安装实战克隆、子模块与CUDA扩展编译3.1 拿到官方代码仓库的完整方式原版代码在GitHub上的地址是graphdeco-inria/gaussian-splatting。这里必须提醒一个关键操作这个仓库用了submodule来管理依赖直接git clone会把依赖目录留空后面编译必挂。正确克隆方式git clone https://github.com/graphdeco-inria/gaussian-splatting.git --recursive如果你已经clone了主仓库但漏了--recursive也可以用这个命令补救git submodule update --init --recursive3.2 conda环境创建Python版本的隐性要求官方推荐Python 3.7但结合我自己和周围人的经验Python 3.8到3.10是最稳的区间。3.11编译时偶尔会遇到某些依赖包没有预编译wheel的问题3.7则太老部分依赖已经放弃支持。创建环境的命令conda create -n gaussian_splatting python3.10 conda activate gaussian_splatting3.3 安装依赖包从这里开始就有坑官方在requirements.txt里列了PyTorch、torchvision、submodules等依赖。但如果你直接无脑执行pip install -r requirements.txt大概率会踩到两个坑一是PyTorch版本和CUDA版本不匹配二是CUDA扩展编译时找不到.cu文件的编译头。我建议的安装顺序是# 先安装PyTorch用conda装而不是pip装 conda install pytorch2.0.0 torchvision0.15.0 pytorch-cuda11.8 -c pytorch -c nvidia为什么用conda因为conda会自动处理CUDA依赖库后面编译扩展时少很多麻烦。PyTorch装好之后再装官方requirementspip install -r requirements.txt这套顺序的好处是PyTorch这个最大的第三方依赖先被固定住后面编译CUDA扩展时不会因为PyTorch版本变动引发ABI兼容问题。3.4 编译两个CUDA扩展diff-gaussian-rasterization和simple-knn这是整个安装过程最核心、也最容易卡住的一步。官方把两个C/CUDA扩展放成了Python子包pip install submodules/diff-gaussian-rasterization pip install submodules/simple-knn这两个包都会触发本机CUDA编译。如果前面的CUDA和PyTorch版本匹配没问题编译一般可以在几分钟内完成。但一旦版本不匹配报错信息五花八门最常见的几类我放在后面“踩坑实录”里统一说。编译完成的标志是出现“Successfully installed diff-gaussian-rasterization”类似提示。如果你看到ninja: build stopped: subcommand failed不要慌大概率是CUDA_HOME环境变量没设对或者头文件路径缺失。3.5 安装完成后怎么验证这一步很多人会跳过但我觉得非常有价值。在conda环境里运行python -c import diff_gaussian_rasterization; print(ok) python -c import simple_knn; print(ok)如果没有报错说明扩展编译成功、且能被Python正确导入。这一步能提前暴露80%的安装问题比直接跑完整训练快得多。4. 喂给模型的数据长什么样COLMAP重建与数据集规范4.1 3DGS的数据需求与NeRF的不同训练3DGS你需要的是一个场景的一组照片以及每张照片对应的相机位姿。相机位姿通常由COLMAP一个开源的SfM/MVS工具从照片中自动估计出来。和NeRF有些不同3DGS特别在意“场景被充分覆盖”。因为高斯球的优化没有全局约束如果某个区域照片太少那里的高斯球就会胡乱漂移渲染时出现严重的拖影或“漂浮物”。所以拍摄时要有意识地绕着场景走一圈确保每个角度的纹理都被捕捉到相邻照片的重叠率最好超过70%。4.2 COLMAP的安装与使用COLMAP可以通过apt直接安装也可以从源码编译。对于只是想跑通3DGS的朋友用apt装就够了sudo apt-get install colmap但需要注意一点3DGS官方代码里集成了调用COLMAP的脚本会自动完成特征提取、特征匹配、稀疏重建和相机位姿估计的完整流程。你只需要把图片放在指定目录然后运行训练命令时加上--colmap_executable /usr/bin/colmap参数即可。如果你用的是Windows或者COLMAP路径特殊需要手动指定可执行文件路径。找不到路径时直接which colmap查看。4.3 数据目录结构的标准组织方式3DGS的数据目录格式是在NeRF-Synthetic基础上扩展来的。以官方数据集为例一个合法的目录结构是这样的data/ └── scene_name/ ├── images/ # 原始拍摄图片 │ ├── IMG_0001.jpg │ ├── IMG_0002.jpg │ └── ... ├── sparse/ # COLMAP输出的稀疏重建结果 │ └── 0/ │ ├── cameras.bin │ ├── images.bin │ └── points3D.bin └── (可选) input/ # 如果使用官方convert.py脚本产生如果你的图片已经拍好但还没有用COLMAP处理直接运行训练脚本时3DGS会自动调用COLMAP处理。但如果照片质量太差比如大量模糊、光照突变、重复纹理COLMAP可能找不到足够特征点就会报“Low/Not enough memory”之类的错。我的经验是场景中最好避免大片白墙、玻璃反光、水面这类特征稀少的区域否则要给后续debug留够时间。4.4 用自己的照片做数据集的具体步骤假设你已经有一堆照片在my_photos/目录下想转成3DGS可用的数据# 创建项目目录 mkdir -p data/my_scene/images cp my_photos/*.jpg data/my_scene/images/ # 训练时自动调用COLMAP python train.py -s data/my_scene --colmap_executable /usr/bin/colmaptrain.py会自动完成后续所有COLMAP步骤。但我建议第一次使用时手动跑一遍COLMAP这样能更清楚地理解整个过程出问题时也知道卡在哪一步。手动跑COLMAP的关键命令cd data/my_scene colmap feature_extractor --database_path database.db --image_path images colmap exhaustive_matcher --database_path database.db mkdir -p sparse/0 colmap mapper --database_path database.db --image_path images --output_path sparse跑完后检查一下sparse/0/里有没有cameras.bin、images.bin、points3D.bin这三个文件有的话就说明COLMAP重建成功。文件是二进制格式不要试着用文本编辑器打开会乱码。5. 训练命令与参数拆解从首次跑通到质量调优5.1 第一次训练别动参数先跑通再说环境装好、数据就位后第一次训练我强烈建议你只做一件事用默认参数跑通。不要调学习率、不要改迭代次数、更不要加任何花哨的mask先让整个流水线转起来确认数据、代码、显卡全都没问题。python train.py -s data/my_scene -m output/my_scene --colmap_executable /usr/bin/colmap参数解释-s数据目录-m输出目录模型和渲染结果会存在这里--colmap_executableCOLMAP可执行文件路径如果你提前手动跑过COLMAP并且数据目录下已经有sparse/0/那么不需要再加--colmap_executable参数代码会直接读取已有的稀疏重建结果。5.2 训练日志里到底在刷什么训练一开始终端会持续输出类似这样的日志... Iteration: 1000 Loss: 0.0123 PSNR: 23.45 Iteration: 2000 Loss: 0.0087 PSNR: 25.12 ...重点关注PSNR这个指标它是峰值信噪比数值越高说明渲染图和原图越接近。第一次训练时PSNR通常从10几起步然后快速爬升到20多后期涨速放缓。一般到30k迭代时PSNR能到28~32的区间具体看场景复杂度继续训练收益就不大了。这里有个容易让人误解的地方Loss在下降到一定程度后会出现周期性跳变看起来好像“坏了”。其实这是3DGS的densification策略在起作用——每隔若干轮它会根据梯度信息增加或删除高斯球Loss会因此暂时上升然后再继续下降。这是正常现象不是模型崩了。5.3 核心训练参数怎么调迭代次数、学习率、densification原版训练脚本有两个主要参数--iterations和--densify_until_iter。默认值是30k和15k意思是到15k轮后停止高斯球增密后续只优化现有球的属性。如果场景比较大比如一整栋建筑或一个广阔的室外场景30k可能不够。我一般会先跑到30k看PSNR曲线如果还在明显上升就继续加迭代比如python train.py -s data/my_scene -m output/my_scene --iterations 40000 --densify_until_iter 20000关于学习率官方默认值已经非常适配大多数场景不建议新手改动。3DGS对学习率比较敏感调得太大容易产生“飞点”漂浮的高斯球调得太小则收敛极慢。5.4 训练过程中如何监控质量TensorBoard和自定义日志3DGS官方代码继承了一套可视化日志逻辑会生成TensorBoard事件文件。训练完或者训练中途你可以用TensorBoard实时看进度tensorboard --logdir output/my_sceneTensorBoard里能看到Loss曲线、PSNR曲线、每个高斯球的属性分布、以及当前视角下的渲染图。对我而言看渲染图比看数值曲线更直观——PSNR高不代表场景细节好有时数值看着正常但某个视角下会出现明显的人工痕迹或漂浮物。如果发现某个视角有明显问题可以手动检查该视角的源照片看看是不是拍摄时抖动、对焦失败或者该区域被其他物体遮挡了。5.5 训练中断了怎么办断点续训的正确姿势训练到一半断电、显存溢出被杀进程这些情况太常见了。3DGS支持从检查点恢复训练命令是python train.py -s data/my_scene -m output/my_scene --start_checkpoint output/my_scene/chkpnt30000.pth官方每7000次迭代保存一次检查点文件名为chkpnt迭代数.pth。恢复训练时它会从检查点继续而不是从头开始。这个功能非常重要尤其当你用很慢的显卡训练长迭代时。有一点需要注意恢复训练时要保持原来的--iterations参数不变否则代码会在新设置的迭代数处停止可能导致总迭代数不符合预期。6. 质量评估PSNR、SSIM、LPIPS以及那些容易被忽视的坑6.1 三个指标分别说明什么、怎么算训练完模型后怎么判断好还是不好3DGS常用的指标有三个PSNR峰值信噪比逐像素差异的指标越高越好。它衡量的是整体像素重建误差但对纹理细节和感知质量不敏感。数值通常在20~35之间。SSIM结构相似性指标衡量局部结构的相似度越高越好接近1。它比PSNR更能反映人类对结构失真的感知。LPIPS学习感知图像块相似度基于深度特征计算的感知距离越低越好。它更贴近人类对真实感的判断——两张图虽然像素级差异不大但LPIPS能分出哪个更“像真的”。这三个指标搭配使用基本能全面覆盖像素准确性、结构保真度、感知真实度三个维度。只看PSNR是远远不够的——我曾经遇到一个模型PSNR从28提到30但肉眼可见地出现了过度平滑那其实不是提升而是高斯球被过度优化成“平均色块”了。6.2 用官方render.py和metrics.py评估模型训练完成后官方提供了渲染和评估脚本python render.py -m output/my_scene python metrics.py -m output/my_scenerender.py会对训练集和测试集的每个视角渲染图像并把结果存到output/my_scene/test/和train/目录下。metrics.py会计算每个视角的PSNR/SSIM/LPIPS汇总输出均值。有一点要特别注意3DGS默认情况下把所有输入图片当作训练数据没有自动划分测试集。如果你需要留一部分照片做测试集必须在数据准备阶段自己划分好否则评估结果会偏乐观——模型见过这些视角了指标自然高。6.3 指标不错但视觉效果奇怪PSNR陷阱这是我最想说的一点在3DGS上PSNR高不等于渲染结果好。我在一个纹理重复的室内场景里遇到过模型在训练集上PSNR高达31但换到新视角时就出现了严重的结构扭曲——因为重复纹理让高斯球混淆了不同的空间位置模型对相机位姿轻微扰动非常敏感。怎么避免我的经验有两条训练后一定要在“没见过的视角”上看效果。实操中就是渲染一段相机轨迹视频仔细看每个角度是否有漂浮、变形、闪烁。用LPIPS做辅助判断。如果PSNR很高但LPIPS也高即感知质量差说明模型虽然和原图逐像素接近但结构上不对。官方也提供了渲染视频的脚本可以根据相机路径生成视频python render.py -m output/my_scene --skip_train --skip_test --render_video这个功能适合用来快速检查模型在连续视角下的稳定性。7. 实操报错排查我踩过的编译、显存与数据坑7.1 CUDA编译失败nvcc not found与路径配置如果你在pip安装diff-gaussian-rasterization时看到类似Command nvcc not found的报错说明系统没找到CUDA编译器。有两种可能一是CUDA Toolkit没有安装二是安装了但环境变量没配。解决方式export CUDA_HOME/usr/local/cuda-11.8 export PATH/usr/local/cuda-11.8/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH建议把这些写进~/.bashrc之后每次重新打开终端都不用手动敲。如果你的CUDA不是装在/usr/local/cuda下可以用which nvcc找真实路径。7.2 编译过程中报cuda_runtime.h not found这个报错本质上是CUDA头文件路径缺失通常是因为你的CUDA安装不完整或者PyTorch自带的CUDA和你系统里的CUDA相互冲突。最有效的解决办法是换一种安装思路直接用conda install cuda把整套CUDA放进conda环境而不是依赖系统CUDA。这样PyTorch、扩展编译、运行时用的都是同一套CUDA库三个环节的版本完全一致问题少一大半。具体做法先创建环境再安装conda create -n gaussian_splatting python3.10 conda activate gaussian_splatting conda install pytorch2.0.0 torchvision0.15.0 pytorch-cuda11.8 -c pytorch -c nvidia7.3CUDA out of memory小显存显卡的生存指南训练到一半爆显存是最常见的事故之一。4060 8G在默认设置下跑到20k次迭代时显存占用通常已经接近极限再加一个测试集的渲染任务就直接爆。我的经验策略是下调训练图像分辨率在数据准备阶段把图片resize到1280或1600官方代码会自动读取图像尺寸不需要额外改参数。关闭无关的visualization服务TensorBoard的日志记录本身占显存如果爆显存可以临时关掉。降低--densification_interval里的batch size虽然这个参数比较底层一般不动。分辨率下调带来的质量损失其实不大——很多场景从1600降到1280PSNR只掉0.5左右但显存占用能减少30%以上。7.4 COLMAP建图失败特征点太少或场景结构不够如果你发现COLMAP输出的points3D.bin里的点云非常稀疏或者干脆报Could not find a good initial pair基本可以肯定是照片质量或拍摄方式出了问题。常见原因有图片过度压缩、运动模糊严重、光照剧烈变化、场景特征重复率高。解决办法也简单直接拍摄时尽量固定曝光、缩小光圈、保证画面清晰。避免只拍近距离特写适当加入中景和远景让COLMAP有足够的parallax来估计深度。如果场景确实是白墙大平顶这类低纹理环境手动添加一些特征物比如海报、绿植能极大提升重建成功率。7.5 训练一切正常但渲染结果有“雨滴”密度控制参数没有生效最后讲一个容易让人困惑的现象训练Loss稳定下降、PSNR也不算低但渲染出来的视频在某个视角下有密集的“雨滴状”伪影尤其在高光区域附近明显。这通常是densification阶段的高斯球分裂条件设置不当导致大量微小高斯球聚集在同一区域。解决办法是检查--densify_grad_threshold参数官方默认是0.0002。如果场景高光非常多这个阈值可能要略微调高让扰动不那么敏感。但注意别调太高否则高斯球数量过少细节会丢失。这类问题没有通用标准答案只能看在具体场景上的表现慢慢微调。我自己的习惯是每次只改一个参数训练几步后看TensorBoard里高斯球的空间分布再决定下一步怎么调。写在最后关于3DGS我的几点个人经验做到这一步你应该已经能独立完成从环境搭建到训练评估的完整流程了。最后分享几条这段时间实操下来的体会。第一3DGS的“训练快”说的是收敛速度快但不要因此忽略数据质量。一组清晰、充分覆盖、位姿分布均匀的照片比一堆凑数的照片训练出来的模型强太多。哪怕你用4090垃圾数据训出来的就是垃圾结果硬件救不了数据。第二官方代码之所以用COLMAP是因为它稳定、可控、可复现。虽然近一年出现了很多端到端或前馈式的位姿估计方案但当你研究3DGS本身时官方流程仍然是最不容易出问题的起点。先把这套基础打牢再去碰新方案你会更容易判断问题出在“位姿估计”还是“3DGS优化”。第三也是最重要的一条任何算法框架都有它的适用边界。3DGS在静态、纹理丰富、光线可控的场景下效果惊艳但在动态场景、极端光照、大范围空旷区域这些场景下会暴露问题。别指望一套参数打遍天下遇到特殊场景时回到基础原理去分析问题远比盲目调参更有效。希望大家都能跑出自己的第一个高质量场景。如果训练过程中遇到这篇文章没提到的报错欢迎在评论区带上完整日志交流——很多时候一张报错截图比自己闷头折腾一天都有用。