简介:面向新手小白的3D高斯(3DGS)复现全流程实战记录,以Linux/Ubuntu 20.04.3 LTS为背景,围绕NVIDIA GeForce RTX 3080 Ti显卡、CUDA 11.8与PyTorch环境,完整记录从零开始跑通gaussian-splatting项目的全过程。文档从环境配置与版本确认入手,覆盖虚拟环境创建、两个子模块安装、colmap编译与安装、显卡驱动更新及图形界面切换等关键环节,并针对新手高频报错逐一给出排查思路,如MP4视频无法播放、PNG文件读入失败、驱动更新后黑屏、colmap报undefined reference to TIFFReadRGBAImage、cudart64_12.dll缺失、点云PLY可视化失败等,均提供具体解决方向。资源共1个doc文档,大小约96.32MB,内容以步骤记录、命令示例和排错截图为主,适合首次接触三维重建或3DGS复现但缺乏经验的学习者参照操作。目前已有5056人学习/下载,按文档顺序执行可显著减少环境搭建与编译安装阶段的试错时间,快速跑通完整复现流程。
1. 新手复现3D高斯与3DGS之前,先想清楚它到底在做什么
第一次复现3DGS(3D Gaussian Splatting,3D高斯场景表示方法)时,大多数人以为最难的是训练模型,实际翻车几乎全在环境编译和数据准备这两步。所谓“复现全流程”,就是拿一组自己拍摄的图片,让程序重建出一个可以从任意视角实时渲染的3D场景,最终得到可旋转查看、可导出点云的高斯模型。这个方向很适合刚接触神经渲染和3D重建的开发者:一张8GB显存的普通显卡就能跑通,但它对工具链版本、目录结构和相机位姿校验的依赖非常强。下面按“原理→环境→数据→训练→排查→进阶”的顺序,把第一次能完整走通的路写出来。
2. 从原理到选型:3DGS为什么值得你花一个周末复现
2.1 3DGS 复现的核心思想:场景是一组会“油漆”像素的高斯
3D Gaussian Splatting 把整个场景表示成一大团3D高斯函数,每个高斯可以理解成一个有位置、有形状、有颜色、有透明度的“软糖球”。渲染时,相机把视野里所有的高斯按从近到远的顺序“溅射”到成像平面上,用alpha合成的方式叠加颜色,最终得到一张完整图像。因为这一步是纯光栅化操作,不需要像NeRF那样沿射线大量采样,所以单帧渲染速度能快到实时。
每个高斯的可学习参数包括:中心坐标(xyz)、协方差(用旋转矩阵和缩放向量表示,决定这个高斯的形状和朝向)、颜色(基色加上球谐系数,用来表达视角变化带来的颜色差异)、以及不透明度。训练时把渲染图与真实照片做像素级对比,梯度会反传到以上所有参数上,让每个高斯一点点挪位置、改形状、调颜色。
训练过程中还有一个非常重要的机制叫“自适应密度控制”:在欠重建的区域自动克隆高斯,在过重建的区域自动分裂高斯,同时定期剔除不透明度接近0的“空壳”高斯。这解释了为什么最终的模型点数不是一个固定值,而是训练过程中动态增长的。复现时理解这个机制就够了,不需要自己改实现。
初始化的第一代高斯并不是随机生成的,而是由COLMAP稀疏重建产生的点云作为种子。这也是新手复现时最容易忽略的因果关系:COLMAP跑得好不好,直接决定训练起点和最终效果,后面专门说。
2.2 为什么首选的复现对象是它而不是 NeRF
对新手来说,第一次复现一个渲染类项目,3DGS 的综合体验比 NeRF 友好太多。NeRF 的体渲染需要对每条光线采样几十上百个点,训练一个场景在单卡上动辄几小时起步,而且推理也要逐像素走前向,做交互预览很吃力。3DGS 的splatting本质上是对每个高斯做一次投影再加透明度合成,官方实现单场景训练十几分钟就能出不错的结果,实时查看器可以流畅旋转视角。
从工程复现角度看,3DGS 的代码结构也相对清楚:核心训练逻辑集中在几个文件里,两个CUDA扩展负责光栅化,数据的输入输出格式明确。NeRF 类项目模型变体多、参数杂,跑通一个 baseline 不难,但搞清楚为什么有效要花更多时间。
下面用一个表把两者在复现角度最关心的差异列出来。
| 对比维度 | NeRF 类方法 | 3D Gaussian Splatting |
|---|---|---|
| 场景表示 | 隐式神经场 | 显式可微高斯集合 |
| 渲染方式 | 体渲染积分,沿光线采样 | 光栅化splatting,逐高斯投影 |
| 单帧渲染速度 | 慢,通常需要多次前向 | 快,可实时交互 |
| 训练速度 | 相对较慢 | 相对快,适合反复验证 |
| 可导出内容 | 网格需要额外提取 | 直接导出ply点云,转网格相对直观 |
| 新手门槛 | 概念简单但调试反馈慢 | 概念要一点功夫,调试反馈直接 |
结论很明确:如果你只有一块主流游戏显卡,想在有限时间得到“能看到、能旋转、能导出点云”的成果,3DGS 是更稳的选择。
2.3 动眼前先盘清楚的三件事:显存、CUDA 与预期产出
第一,显存决定了你能玩多大场景。8GB 显存跑官方仓库默认参数是可以的,但图像分辨率最好限制在 1600 左右,场景图片数量控制在 100 到 200 张;16GB 会从容很多。只有 4GB 的卡,训练大场景基本会炸,要么降分辨率,要么换 GPU,这是最现实的一道门槛。
第二,版本对齐是复现的地基。你需要知道的不多:显卡驱动的版本、CUDA runtime 的版本、PyTorch 预编译包对应的 CUDA 版本,以及 C++ 编译器版本。四者只要有一个对不上,编译扩展的时候就报错。更具体的检测命令下一章直接给。
第三,想清楚自己复现成功的标准是什么。不是模型文件生成出来就算成功,而是要在实时查看器里能看到一个成型的场景,并且能导出一份 point_cloud.ply。对着这个标准,你才知道训练日志里的指标到底意味着什么。接下来直接进入第一道坎:环境搭建。
3. 环境搭建与扩展编译:第一次跑通 train.py 的最短路径
3.1 检查显卡驱动、CUDA 与 Python,让版本先对齐
环境问题的根源在于三个版本要互相匹配:显卡驱动支持的最高 CUDA 版本、本机安装的 CUDA Toolkit 版本、PyTorch 编译链接的 CUDA 版本。新手常犯的误会是:“我装了 PyTorch 的 cu118 版本,是不是就不用管 CUDA 了?” 运行 PyTorch 模型确实可以不管,但编译扩展时需要 nvcc 编译器,它来自 CUDA Toolkit。所以最省心的做法是直接把本机 CUDA Toolkit 装好。
先按下面命令把现状摸清楚:
# 查看显卡型号、驱动版本、驱动支持的最高CUDA版本 nvidia-smi # 查看当前命令行能调用的CUDA编译器版本 nvcc --version # 查看Python版本 python --version # 创建独立环境,避免把系统Python环境搞乱 conda create -n gaussian python=3.10 -y conda activate gaussian # 安装与CUDA对应的PyTorch,示例是CUDA 11.8对应版本 pip install torch==2.1.0 torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cu118命令逻辑说明:nvidia-smi 里的 “CUDA Version” 是驱动支持的上限,不代表本机已经装了对应运行时;nvcc 才是你编译 CUDA 代码会用到的工具。PyTorch 的 cu118 后缀表示这个包是用 CUDA 11.8 编译的,训练时驱动会用 JIT 方式加载它。编译扩展时,系统得能找到 CUDA Toolkit 的 include 和 lib 路径,所以建议把 CUDA Toolkit 安装版本和 PyTorch 的 CUDA 版本保持一致,避免出现头文件版本冲突。
参数说明:Python 版本建议选 3.10,太高或太低都可能遇到某些依赖没有预编译包;torch 版本要结合驱动支持的最高 CUDA 来选择,驱动较老就选 cu118,驱动较新可以选 cu121 甚至 cu124。安装完用python -c "import torch; print(torch.__version__, torch.cuda.is_available())"验证一下,输出 True 再继续。
3.2 创建环境、克隆仓库并安装依赖
环境准备好之后,接下来把官方仓库拉下来。仓库地址以官方实现为准,不建议去拉各种二次修改版,因为你不知道别人改了什么,出了问题连对照文档都难。
# 进入工作目录 cd ~/work # 克隆官方仓库 git clone <官方仓库地址> # 进入仓库目录 cd gaussian-splatting # 安装Python依赖 pip install -r requirements.txt逻辑说明:requirements.txt 里主要包含 plyfile、tqdm、tensorboard 这些常用库,以及训练过程中用来记录指标和写点云文件的工具。依赖安装一般不会报错,如果某一步下载慢或者失败,重复执行 pip install 即可,不需要换什么神秘加速源。
参数说明:实际使用中,requirements.txt 里如果固定了某个子模块版本,请不要手动改动。后续编译的两个 CUDA 扩展不会装到 conda 环境里是正常现象,它们是作为独立包安装,Python 在运行时按名字导入。
3.3 编译两个子模块:diff-gaussian-rasterization 与 simple-knn
这是整个复现流程里新手最头疼的一步。3DGS 的渲染核心是自定义的 CUDA 光栅化算子,官方仓库把它放在 submodules 目录下,需要现场编译成 Python 可调用的扩展。常见做法是仓库根目录下有两个 submodules 文件夹,分别编译安装。
# 编译并安装主要的光栅化CUDA算子 pip install submodules/diff-gaussian-rasterization # 编译并安装辅助的KNN工具(用于训练时近邻查询) pip install submodules/simple-knn # 验证扩展是否导入成功 python -c "import diff_gaussian_rasterization; print('rasterization ok')"逻辑说明:pip install 遇上含 CUDA 代码的目录,会调用本机的 nvcc 和 C++ 编译器现场构建。编译成功时日志里能明显看到 “Building wheel” 和 “Successfully built” 字样。失败时最后几行日志会直接告诉你缺什么,最常见的是 “CUDA_HOME not set” 或 “cuda_runtime.h not found”。
参数说明:如果本机装了多个 CUDA 版本,建议在编译前显式指定 CUDA 路径,例如在 Linux 下执行export CUDA_HOME=/usr/local/cuda-11.8;Windows 下确认环境变量 CUDA_PATH 指向目标版本。Linux 用户还需要保证 gcc 版本在 9 以上,Windows 用户需要安装 Visual Studio 的“使用 C++ 的桌面开发”工作负载,编译器版本太老会直接不认新版 CUDA 头文件。
提示:这一步如果失败,不要反复用同一套环境重试。先把
nvcc --version和 gcc/cmake 版本贴到报错搜索里,或者问身边跑通过的人要一份环境对照。把版本对齐,编译基本一次过。
4. 数据准备与训练全流程:COLMAP 稀疏重建到模型输出
4.1 数据采集要点:用手机也能出好看的重建
训练3DGS的数据就是一组带重叠视角的照片。采集质量比数量重要。当你拿着手机绕着一个物体或场景转一圈拍摄时,记住几个原则:焦距固定不变,不要中途缩放;移动速度放慢,避免运动模糊;相邻两帧画面重叠度保持在70%以上;尽量避开大面积纯色、镜面反射和玻璃;光照不要剧烈变化。满足这些条件,普通手机拍60到150张照片就足够跑通一个场景。
如果你习惯录视频,可以事后抽帧。下面是用 ffmpeg 抽帧的命令,按需调整抽帧频率,保证最终图片数在100张左右最合适。
# 从30秒视频里按每秒2帧抽帧,得到约60张图片 ffmpeg -i input.mp4 -vf fps=2 -qscale:v 2 images/%04d.jpg逻辑说明:fps=2表示每秒抽取2帧,%04d.jpg表示输出文件名按四位数字编号(0001.jpg、0002.jpg)。抽完帧后把明显模糊、光照突变、重复度过高的照片删掉,这一步能帮你避开很多训练翻车问题。
参数说明:qscale:v 2是 JPEG 质量控制参数,数值越小画质越高,2 到 4 都够用。如果拍的是静态物体,抽帧频率可以降低,保证每一帧视角都有明显变化,否则后续 COLMAP 的特征匹配会很尴尬。
采集完成后,把图片统一复制到一个干净的目录,比如data/my_scene/input,后续所有处理都围绕这个目录。
4.2 用 COLMAP 生成相机参数与稀疏点云
3DGS 的训练需要每个视角的相机内外参,以及用于初始化高斯的稀疏点云,这套东西由 COLMAP 提供。新手第一次跑,建议直接用 COLMAP 的图形界面操作一遍,看到每一步产出的中间结果,比纯命令行有感觉。但命令行版本更适合脚本化复现,下面给出标准流程。
COLMAP 的整个流程分三步:特征提取、特征匹配、稀疏重建。实际操作时可以用 COLMAP 的命令行工具,也可以用官方仓库推荐的 convert.py 脚本统一处理。常见做法是:图片放进<data>/input,然后跑命令重建,最后运行仓库里的 convert.py 做畸变校正和目录整理。
# 进入场景目录 cd data/my_scene # 特征提取:为每张图片提取关键点 colmap feature_extractor \ --database_path database.db \ --image_path input \ --ImageReader.single_camera 1 # 特征匹配:找出图片之间的对应关系 colmap exhaustive_matcher \ --database_path database.db # 稀疏重建:估计相机位姿并生成点云 colmap mapper \ --database_path database.db \ --image_path input \ --output_path sparse # 完成畸变校正,并把结果整理成官方仓库要求的目录结构(常见做法) python convert.py -s .逻辑说明:feature_extractor负责从每张图提取特征点,single_camera 1表示所有图片都来自同一台相机,可以共享同一套内参,对手机拍摄场景非常关键,如果漏掉这个参数,每张图都会被当成不同相机,重建极容易分裂。exhaustive_matcher对全图做两两匹配,图片量大时很费内存,但效果最稳。mapper做增量式稀疏重建,生成 bin 格式的相机位姿和点云。
convert.py做的事其实不止整理目录,它会读取 mapper 的输出、做图像畸变校正,最终生成<data>/images和<data>/sparse/0两个目录,这是训练脚本默认读取的结构。如果你不用 convert.py,就必须自己保证 images 目录下的图片和 sparse 目录里的相机参数一一对应,新手很容易在这里踩坑。
参数说明:图片数量较多时,可以把exhaustive_matcher换成sequential_matcher,它对相邻帧做匹配,速度快很多,但前提是你的照片是按拍摄顺序命名的。手机绕场拍摄时推荐 sequential,扫描场景时推荐 exhaustive。
4.3 train.py 训练命令与关键参数
数据准备好后,训练就是一条命令的事。官方仓库根目录下有训练脚本,起步阶段直接用默认参数,不要改优化器和学习率相关的东西。
# 在仓库根目录下执行 python train.py \ -s data/my_scene \ -m output/my_scene \ --iterations 30000 \ --test_iterations 1000 3000 7000 \ --save_iterations 10000 30000逻辑说明:-s指定场景数据根目录,必须包含images和sparse/0;-m指定实验输出目录,训练好的模型和中间结果都会写在这里。--iterations是总迭代次数,官方默认值 30000 对大多数场景都够。--test_iterations表示在这些迭代节点上跑一次测试集评估,输出 PSNR 等指标;--save_iterations表示在这些节点保存检查点文件,方便中途恢复或加载不同阶段的模型。
参数说明:如果显存吃紧,给train.py加-r 0.5,这会按一半分辨率加载图像,显存占用能降到原先的四分之一左右,适合显卡只有 8GB 的情况。另外--sh_degree默认是 3,表示球谐阶数最高到 3 阶,初学者不用动它,只有想压缩模型大小时才会考虑调低。
第一次训练时建议开一台电脑刷着日志。日志里最值得看的信息是:每一轮迭代输出的 PSNR、当前高斯点数量、当前显存占用。如果 PSNR 在前 1000 次迭代里没有上涨的迹象,说明数据准备有问题,而不是模型问题。
4.4 训练输出与结果验证
训练结束后,output/my_scene目录下会有不少文件。新手要学会一眼认出哪些真正有用,不要被中间文件吓到。下面列的是最常见的几类文件。
| 文件或目录 | 内容 | 用途 |
|---|---|---|
| test/ | 测试视角渲染结果与真实图对比 | 快速看重建质量 |
| train/ | 训练视角渲染结果 | 确认训练是否收敛 |
| visual/ | 可视化辅助图 | 帮助定位欠重建区域 |
| point_cloud/iteration_30000/point_cloud.ply | 最终的高斯点云 | 可导入其他工具或二次处理 |
| chkpnt30000.pth | 检查点文件 | 可从中断处继续训练 |
| ckpt_30000.pth | 模型权重 | 加载后做渲染或微调 |
验证训练效果最直接的方式是打开test目录,对比真实照片和渲染图的差异。如果两者在纹理和轮廓上非常接近,基本就算复现成功。初次跑通不要追求指标超过别人,先确认全流程没有断点。
官方仓库还有一个实时查看器,在仓库的 SIBR_viewers 目录下,编译需要额外依赖。第一次复现不要求把查看器编出来,先看静态图,跑通主流程后再回来折腾查看器。查看器能流畅旋转视角时,你才算真正体验到 3DGS 的实时渲染能力。
5. 复现路上的常见问题与排查:让训练稳定出图的5个修复方向
5.1 扩展编译报错,找不到 cuda_runtime.h 或 nvcc
现象:执行pip install submodules/diff-gaussian-rasterization时,日志抛出一大段fatal error: cuda_runtime.h: No such file or directory,或者干脆提示nvcc not found。
原因:CUDA Toolkit 没有安装,或者安装了但命令行当前环境找不到。pip 编译时不会自动去扫描显卡驱动目录,它依赖常规的CUDA_HOME环境变量。
解决:先执行nvcc --version,如果提示没有这个命令,就安装和 PyTorch 版本匹配的 CUDA Toolkit。Linux 下安装后把/usr/local/cuda/bin加进 PATH;Windows 下确认环境变量CUDA_PATH存在。改完环境变量后记得重新打开终端,再重新执行编译。还有一个很容易忽略的坑:如果同时装了多个 CUDA 版本,pip 可能选错,建议安装前显式export CUDA_HOME=/usr/local/cuda-11.8指定一次。
5.2 训练启动后背景发黑,模型只长出一小团东西
现象:训练日志正常刷新,但渲染出来的图几乎全黑,只有正中间有一小团模糊色块。查看器里场景完全不成型。
原因:绝大多数情况下是 COLMAP 稀疏重建失败,导致相机位姿错乱或者点云太稀疏。初始化时高斯数量严重不足,后面的密度控制再怎么补偿也补不回来。还有一种可能是 convert.py 输出目录里sparse/0下的点云文件点数极少,这说明特征匹配环节就出了问题。
解决:回查 COLMAP 的中间产物。最简单的方法是直接看input图片:如果图像之间重叠度不够,或者大量图片几乎是同一视角,特征匹配自然失效。重新采集数据,保证绕场时有明显的视角推进。也可以用 COLMAP 图形界面重新跑一遍,观察右下角点云重建进度。确认稀疏点云有几百几千个点再进训练。
5.3 显存溢出,训练到一半被系统杀掉
现象:训练刚开始还能跑,几百次迭代后终端提示CUDA out of memory,或者直接进程消失,操作系统杀掉了进程。
原因:图像分辨率太高,或场景图片数量太多。默认加载原图分辨率,一张 4000x3000 的照片在训练时非常占显存,同时梯度还要保留多个版本的高斯参数。
解决:给训练命令加-r 0.5,把图片降到一半分辨率,显存占用会大幅下降。如果还是不够,降到-r 0.25也是可以的,只是最终纹理精度会下降。另外检查是否同时开了多个训练任务或别的 GPU 程序。第一次复现,尽量选一个几十张图片的小场景,把流程跑通再上高分辨率。
5.4 COLMAP 生成不了模型,特征点数量极少
现象:COLMAP 的mapper阶段报了No good image pairs found,或者生成的点云只有几十个点。
原因:图片质量或内容的问题。拍摄时运动过快产生模糊、画面全是天空或白墙、室内场景光照太暗,都会导致特征提取失败。还有一个隐蔽原因:图片分辨率太高时 COLMAP 默认降采样,特征点本身也受影响。
解决:回到数据侧。把明显模糊的照片删掉;用手机拍摄时尽量等对焦完成再移动;场景里加上一些有纹理的物体或海报,给特征匹配提供锚点。如果照片是用视频抽帧得到的,试试把抽帧间隔拉大,保证相邻帧视角差异明显。COLMAP 对“视角连续但变化很小”的图像很敏感,重叠度太高反而匹配不出有效约束。
5.5 加载检查点后推图得到全白或乱码
现象:训练完成后,用加载模型渲染视频或导出点时,结果是一片纯色或花屏。
原因:最常见的是训练参数和加载参数不一致。比如训练时用了--sh_degree 3,但加载时脚本里写死了其他阶数;或者直接加载了不同数据集训练出来的检查点,相机内参完全对不上。
解决:加载模型时,保持训练时用的--sh_degree、分辨率等参数一致。如果检查点来自某一次中途中断的训练,还要确认它和当前场景数据目录是同一条数据链。做渲染验证时,尽量用官方仓库自带的渲染脚本,自己写加载逻辑容易漏掉归一化细节。
注意:遇到报错不要先怀疑代码,先怀疑数据和环境版本。血泪经验是,这个项目的报错信息往往不是真正的原因,日志往上翻几行,通常能看到更早暴露的警告。
6. 进阶:把复现结果用起来,才算真正跑通了全流程
训练跑通只是开始,下一步是把模型当成一个可用的场景资产。最直观的验证方式是用实时查看器打开训练产物,如果仓库自带的查看器在你的机器上能编译出来,就编译一次。它会让你迅速理解“可微高斯集合”和“实时渲染”之间的对应关系:原来每个高斯的颜色和位置就是屏幕上那些彩色光斑的真身。
如果查看器编译太费劲,还有一个更轻量的验证技巧:写一段脚本加载训练好的point_cloud.ply,在点云播放器里浏览。虽然看不到高质量渲染效果,但能确认场景结构是完整的。进阶玩法是走一遍自动旋转视角渲染,把模型从多个方位渲染成视频,用这个视频快速判断哪些区域重建得干净、哪些区域有漂浮物,这样不用等查看器就能完成质量评估。
调参方面,我不建议一上手就乱调学习率。值得先调的是两个地方:--densify_grad_threshold控制密度控制触发的敏感度,场景细节不够时把阈值从 0.0002 调到 0.00005,能让模型长出更多高斯;--sparse_density控制初始化时给每个点周围撒的高斯数量,默认 0.01 偏低,如果想加快收敛可以调大。每次只改一个变量,记录 PSNR 和显存变化,不要一次改好几个。
另外一个很实用的习惯:把复现环境的版本信息和训练命令存成run_config.txt。下次隔几天再跑,环境变量可能已经变了,至少能查到当初是什么组合跑通的。3DGS 的坑大多是环境问题,模型本身其实很皮实。我自己的习惯是每次跑新场景前先看一眼之前存的环境记录,不急着重新编译扩展。希望帮到你。
本文还有配套的精品资源,点击获取