简介:这份源码包面向希望上手3D Gaussian Splatting(3DGS)的开发者与研究人员,尤其适合在非官方推荐环境下摸索部署的实践者。作者以Python 3.10、CUDA 12.3与PyTorch 2.2.1的组合完成验证,内容覆盖软件环境配置、依赖安装、数据下载与格式转换,并延伸到预训练数据训练、结果查看及自有图片数据训练等环节,还涉及视频抽帧等实用技巧,可作为三维场景重建方向的入门到进阶参考。资源包共3个文件,以inscode工程配置、html页面与gitignore忽略规则为主,整体约7KB,体量轻便,便于快速导入与查阅。目前已有229人学习下载,说明其在同类实践资料中具备一定参考价值。读者可据此理清3DGS从环境搭建到训练跑通的完整链路,减少在版本兼容与依赖配置上的试错成本,并借助数据预处理与抽帧思路,将方法迁移到个人数据集与项目场景中。
1. 3DGS 部署与训练指南:从零跑通到收敛的完整路径
3D Gaussian Splatting(3DGS)这两年在三维重建圈子里热度一直没降过,它用一组带位置、协方差、不透明度和球谐系数的三维高斯基元来表达场景,配合可微光栅化,训练速度比传统 NeRF 快一个数量级,渲染还能做到实时。但真到自己动手部署时,很多人卡在环境编译、CUDA 版本、显存溢出、训练不收敛这几道坎上。这篇笔记面向的是想在自己机器上把 3DGS 完整跑通、并且能针对自己的数据调参的从业者,从环境搭建、数据准备、训练命令、参数含义一路讲到踩坑排查。如果你手里有一组多视角照片或者一段环绕视频,想重建出可实时浏览的三维场景,下面的路径可以直接照着复现。
2. 环境搭建与依赖编译:CUDA、PyTorch 和光栅化扩展怎么配
3DGS 的部署难点不在 Python 层,而在那几个需要现场编译的 CUDA 扩展。官方实现里包含diff-gaussian-rasterization、simple-knn两个核心扩展,它们对 CUDA 版本、PyTorch 版本、编译器版本都有隐性要求。配错一个,轻则编译报错,重则训练时静默出错、渲染结果发灰。
2.1 版本组合的选择逻辑
先讲选型理由。3DGS 的光栅化扩展用到了 CUDA 的原子操作和自定义 kernel,PyTorch 的 C++ 扩展 ABI 在不同大版本之间不兼容,所以「PyTorch 版本 + CUDA 版本 + 显卡驱动」三者必须对齐。我一般会按显卡驱动能支持的最高 CUDA 版本来定,再反推 PyTorch。
| 组件 | 推荐范围 | 说明 |
|---|---|---|
| 显卡驱动 | 支持 CUDA 11.8 及以上 | 用nvidia-smi看右上角 CUDA Version |
| CUDA Toolkit | 11.8 或 12.1 | 与 PyTorch 官方 wheel 对齐 |
| PyTorch | 2.0.x ~ 2.1.x | 太新可能扩展编译失败 |
| Python | 3.8 ~ 3.10 | 3.11 部分依赖轮子缺失 |
| GCC | 9 ~ 11 | 太新会触发 nvcc 不识别 |
提示:不要盲目追最新版。3DGS 这类带自定义 CUDA kernel 的项目,稳定比新特性重要得多。
2.2 用 conda 隔离环境并安装依赖
下面这套命令是我在多次重装后固定下来的流程,先建独立环境,避免污染系统 Python。
# 创建独立环境,指定 Python 版本 conda create -n gs3d python=3.10 -y conda activate gs3d # 安装与 CUDA 11.8 对齐的 PyTorch pip install torch==2.1.0 torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cu118 # 安装项目基础依赖 pip install plyfile tqdm opencv-python numpy # 验证 CUDA 是否可用 python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)"逻辑说明:--index-url指向 PyTorch 官方针对 cu118 编译的 wheel,这一步决定了后面扩展能不能链接到正确的 CUDA 运行时。最后一行验证必须输出True和11.8,如果输出False,说明驱动或 CUDA 版本不匹配,先解决这一步再往下走。
参数说明:torch==2.1.0是经过验证与光栅化扩展兼容的版本;torchvision版本必须与 torch 主版本对应,否则会报符号冲突。
2.3 编译两个 CUDA 扩展
把项目源码拉下来后,进入子模块目录逐个编译。常见做法是先装simple-knn,再装光栅化扩展,因为后者依赖前者的编译产物路径。
# 进入项目根目录后,编译 simple-knn pip install submodules/simple-knn # 编译光栅化扩展,这一步最耗时 pip install submodules/diff-gaussian-rasterization # 若报 nvcc 相关错误,显式指定架构 # TORCH_CUDA_ARCH_LIST="8.6" pip install submodules/diff-gaussian-rasterization逻辑说明:pip install一个本地目录时,会读取其中的setup.py并调用 nvcc 编译。TORCH_CUDA_ARCH_LIST用来指定目标显卡的计算能力,比如 8.6 对应 RTX 30 系,7.5 对应 RTX 20 系。不指定时 PyTorch 会尝试编译所有架构,耗时翻倍还容易失败。
参数说明:计算能力可以在 NVIDIA 官网的 GPU 规格表里查到,或者用torch.cuda.get_device_capability()直接打印。编译报unsupported gpu architecture时,八成就是这个变量没设对。
3. 数据准备与训练启动:从多视角照片到可渲染场景
环境通了之后,下一个卡点是数据。3DGS 不像 NeRF 那样对输入那么宽容,它需要相机位姿,而位姿通常靠 COLMAP 做 SfM 得到。这一步的质量直接决定最终重建的成败。
3.1 用 COLMAP 生成相机位姿
输入是一组多视角照片,输出是sparse/0目录下的cameras.bin、images.bin、points3D.bin。常见做法是先用特征提取加匹配,再跑增量式重建。
# 特征提取 colmap feature_extractor \ --database_path ./database.db \ --image_path ./input \ --ImageReader.single_camera 1 # 特征匹配(视频帧用 sequential,散拍照片用 exhaustive) colmap sequential_matcher --database_path ./database.db # 增量式重建 colmap mapper \ --database_path ./database.db \ --image_path ./input \ --output_path ./sparse逻辑说明:single_camera 1表示所有照片来自同一台相机、内参一致,能显著提升重建稳定性。sequential_matcher适合视频抽帧,因为它只匹配时间相邻的帧,速度快;如果是随机角度拍摄的照片,必须换成exhaustive_matcher,否则匹配不上。
参数说明:重建完成后检查sparse/0下是否有三个 bin 文件,以及images.bin里注册的相机数量。如果注册率低于 70%,说明照片重叠度不够或纹理太弱,需要补拍。
3.2 训练命令与关键参数
数据就绪后,训练命令本身不长,但参数决定了收敛速度和最终画质。
python train.py \ -s ./data/scene \ -m ./output/scene \ --iterations 30000 \ --eval \ --densify_until_iter 15000 \ --densify_grad_threshold 0.0002逻辑说明:-s是数据源目录,里面要有images和sparse/0;-m是输出目录,训练日志、checkpoint、点云都会写到这里。--eval会按论文设定划分训练集和测试集,方便算 PSNR/SSIM。
参数说明:--iterations 30000是默认收敛步数,场景复杂可以加到 40000;--densify_until_iter控制高斯基元增殖的截止步数,设太大显存会爆;--densify_grad_threshold是增殖阈值,调小会让更多区域长出新高斯,细节更丰富但更吃显存。
3.3 训练过程监控与显存控制
训练时终端会打印 loss 和当前高斯数量。高斯数量从几万涨到几百万是正常的,显存占用也随之上升。
# 实时看显存占用 watch -n 1 nvidia-smi # 训练日志里关注这两个指标 # number of points: 高斯总数 # loss: 应在前几千步快速下降后趋于平稳逻辑说明:如果高斯数量在 15000 步之前就冲到 500 万以上,显存很容易爆。这时候要么降低输入分辨率,要么调大densify_grad_threshold抑制增殖。
参数说明:显存不足时优先降分辨率,把图像长边缩到 1600 以内,比换显卡见效快。--resolution参数可以直接控制训练分辨率。
4. 避坑与排查:训练不收敛、显存爆炸、渲染发灰的根因
这一章是我踩坑最多的地方,按「现象 → 原因 → 解决」整理,都是实际遇到过的。
4.1 训练 loss 不下降或直接 NaN
现象:训练开始几百步后 loss 变成 NaN,或者一直卡在高位不动。
原因:多半是相机位姿有问题,或者输入图像里有纯色、过曝的帧污染了 SfM。也有可能是学习率被改坏了。
解决:先用 COLMAP 的可视化工具检查点云和相机位置是否合理,剔除明显漂移的帧。确认train.py里的位置学习率没被误改,默认是随步数指数衰减的。
4.2 显存溢出(CUDA out of memory)
现象:训练到中途报 OOM,或者一开始就爆。
原因:高斯增殖过快,或者输入分辨率太高。30 系 12G 显存跑 1080p 以上分辨率很容易爆。
解决:降低--resolution,调大densify_grad_threshold,或者提前densify_until_iter。实在不行换更大显存的卡,这是硬约束。
4.3 渲染结果发灰、有雾感
现象:训练完渲染出来整体偏灰,像蒙了一层雾。
原因:通常是背景处理没做好。3DGS 对无界场景需要背景建模,如果场景里有大片天空或纯色背景,高斯会乱长。
解决:训练时加--white_background参数,或者对输入图像做背景掩膜。有界场景(比如室内物体)一般不会有这个问题。
4.4 编译扩展时报 nvcc 版本不匹配
现象:pip install submodules/diff-gaussian-rasterization报nvcc fatal: unsupported gpu architecture或no kernel image is available。
原因:CUDA Toolkit 版本和显卡计算能力不匹配,或者TORCH_CUDA_ARCH_LIST没设。
解决:显式设置TORCH_CUDA_ARCH_LIST,值用torch.cuda.get_device_capability()查到的两位数字,比如(8, 6)就写8.6。
4.5 训练完模型加载报错
现象:用render.py加载训练好的模型时报 key 不匹配或文件缺失。
原因:输出目录结构不对,或者训练没跑完就中断了。
解决:确认-m目录下有point_cloud/iteration_30000/point_cloud.ply和cameras.json。中断的训练可以用--start_checkpoint续跑,但要注意迭代数对齐。
5. 进阶技巧:用自定义数据跑出稳定画质的几个习惯
跑通之后,真正拉开差距的是数据质量和参数微调。我一般会先做一轮低分辨率快速训练,看高斯数量和 loss 曲线是否正常,再上全分辨率正式跑。这样能省下大量试错时间。
一个具体技巧是控制输入帧的选取。视频抽帧不要抽太密,相邻帧间隔太小会导致 SfM 退化,一般每秒抽 2 到 4 帧就够。照片拍摄时保证 60% 以上重叠度,环绕物体拍两到三圈,不同高度各来一圈,重建出来的细节会明显更实。
另一个习惯是固定随机种子。3DGS 的增殖过程有随机性,同一份数据两次训练结果会有差异。在train.py里设--seed 42,方便对比不同参数的效果,不然你根本分不清是参数起作用还是玄学。
验证阶段我习惯用测试集的 PSNR 和 SSIM 双指标,单看 PSNR 容易被过拟合骗。如果 PSNR 涨但 SSIM 不涨,说明模型在拟合噪声,该回头检查数据了。
最后说个血泪经验:训练中途别手贱去动输出目录,3DGS 会在固定迭代点写 checkpoint,你挪了文件它找不到路径直接崩,之前的算力全白费。我一般会等它完整跑完再操作,实在要中断就用Ctrl+C让它自己收尾。希望帮到你。
本文还有配套的精品资源,点击获取