资讯详情

3D Gaussian Splatting 模型保存/加载全解:PLY 属性扩展与优化器断点续训

📅 2026/10/29 10:53:34 | 华诺云谱 👁 阅读
3D Gaussian Splatting 模型保存/加载全解:PLY 属性扩展与优化器断点续训
3D Gaussian Splatting 模型保存/加载全解PLY 属性扩展与优化器断点续训【免费下载链接】gaussian-splattingOriginal reference implementation of 3D Gaussian Splatting for Real-Time Radiance Field Rendering项目地址: https://gitcode.com/gh_mirrors/ga/gaussian-splatting训练跑了几小时眼看快收尾机器却宕机、进程被 kill——40 万步的进度怎么不丢这正是 3D Gaussian Splatting3DGS模型保存/加载问题的核心官方实现把答案写在两种文件里一份扩展了高斯参数的 PLY一份捕获优化器完整状态的 .pth。本文以 3DGS 官方参考实现 gaussian-splatting 为准核心代码集中在scene/gaussian_model.py的GaussianModel类保存与加载的触发点在train.py的训练循环里下面把整条链路拆开走一遍。3DGS 到底要存什么——参数全景先盘家底。一个高斯不只是一个点它带着一整组连续参数位置、协方差官方拆成三轴缩放 旋转四元数表达、逐视角颜色球谐 SH 系数、不透明度。在代码里它们是六组张量_xyz、_features_dc、_features_rest、_opacity、_scaling、_rotationPLY 的顶点属性表就是按它们的形状逐项生成的。字段前缀数量物理含义存储阶段x / y / z3高斯中心三维坐标原始优化值f_dc_3SH 0 阶DC系数即基色原始优化值f_rest_3×(L²−1)SH 高阶系数L 为 max_sh_degree原始优化值scale_3三轴缩放存对数空间对数空间原始值rot_4未归一化旋转四元数归一化前原始值opacity1每个高斯的不透明度sigmoid 前原始值重点在存储阶段这一列全部是原始优化值。gaussian_model.py的setup_functions里激活函数是单独注册的self.scaling_activation torch.exp # _scaling 存的是对数空间原始值 self.opacity_activation torch.sigmoid # _opacity 存的是 sigmoid 前原始值 self.rotation_activation torch.nn.functional.normalize真实的缩放、不透明度、归一化四元数都是渲染时经过get_scaling、get_opacity、get_rotation这些 property 即时激活出来的。这样设计有两层好处其一磁盘里的值和内存里的值完全一致加载后直接requires_grad_(True)就能继续训练无需任何换算其二优化器Adam存的是针对原始值的梯度一、二阶矩估计只有存原始值动量链才能一致恢复。存激活后的值矩状态和恢复出来的参数就对不上了续训越训越发散。标准 PLY 属性为什么不够用标准 PLY 是为多边形网格设计的顶点字段基本是 x/y/z、法向和颜色。3DGS 的球谐系数、对数缩放、四元数没有标准字段可放官方实现就把它们全部塞进 vertex 元素的自定义 float 属性下游查看器和工具都得自行识别这些扩展字段。法向那三个字段则是纯占位——高斯本身没有法向概念放着只是为了凑格式。 写出磁盘save_ply 三步拆解save_ply只干三件事顺序是提取张量、拼接属性、写 PlyElement。第一步张量提取所有参数.detach().cpu().numpy()搬离 GPU法向槽位补零xyz self._xyz.detach().cpu().numpy() normals np.zeros_like(xyz) # 补 0 占住法向槽位 f_dc self._features_dc.detach().transpose(1, 2).flatten(start_dim1).cpu().numpy()注意 transpose(1, 2) flatten 这两步SH 系数的张量布局是 (N, 3 通道, C 系数)PLY 是行式数据必须转置成每个高斯一行 (N, 3C)否则通道轴和系数轴就串了。第二步属性拼接字段名列表与 dtype 由construct_list_of_attributes按张量形状动态生成拼接顺序固定dtype_full [(a, f4) for a in self.construct_list_of_attributes()] attributes np.concatenate((xyz, normals, f_dc, f_rest, opacities, scale, rotation), axis1) elements[:] list(map(tuple, attributes))这里所有字段统一 f4float32f_rest_ 的个数会随 sh_degree 自然变多PLY 文件里因此隐含记录了当时的球谐阶数。第三步PlyElement 写入el PlyElement.describe(elements, vertex) PlyData([el]).write(path) 量级感知默认 SH 3 阶时每个高斯 62 个 float32 字段含 3 个法向占位约 248 B百万高斯的模型 PLY 在 250 MB 量级若降到 1 阶每个高斯缩到约 104 B百万高斯文件约 100 MB。读回内存load_ply 怎么重组 SH 系数、capture/restore 怎么续训读回最费劲的是 SH 高阶系数。DC 分量固定 3 个直接填就行f_rest_ 的个数却取决于max_sh_degree且 PLY 头里属性的顺序并不保证和保存时一致所以load_ply按前缀扫属性、按下标排序先做断言assert len(extra_f_names) 3 * (self.max_sh_degree 1) ** 2 - 3 features_extra features_extra.reshape((features_extra.shape[0], 3, (self.max_sh_degree 1) ** 2 - 1))这一行把 (N, 3×15) 拍回 (N, 3, 15)是加载后颜色异常问题的根源所在。scale_ 和 rot_ 字段同样按前缀收集排序最后所有参数包成nn.Parameter并requires_grad_(True)方法收尾处还有self.active_sh_degree self.max_sh_degree——意思是加载后模型立即全阶激活不再逐步升阶。但 PLY 只有参数、没有优化器续训靠它不够。官方实现有第二条通道capture()把六组参数、max_radii2D、稠密化记账张量xyz_gradient_accum/denom连同optimizer.state_dict()一起打成元组train.py里存成 checkpointtorch.save((gaussians.capture(), iteration), scene.model_path /chkpnt str(iteration) .pth)恢复时restore先重新跑一遍training_setup建出新的 Adam然后self.optimizer.load_state_dict(opt_dict) # exp_avg / exp_avg_sq 全部还原注意 checkpoint 里连带 iteration 一起存了train.py读回后训练循环直接从该步继续restore还会把xyz_gradient_accum和denom放回来这两个是稠密化策略的记账变量漏掉它们 clone/split 的节奏会乱。两条通道定位一目了然维度save_ply.plycapture → .pth存的内容6 组模型参数参数 optimizer state_dict 稠密化记账面向场景部署渲染、模型交换仅断点续训触发时机train.py的 saving_iterationstrain.py的 checkpoint_iterations恢复入口load_ply无优化器restoreload_state_dict上规模之后的存储与加载优化量化降精度先压 SH 系数SH 系数是体量大头3 阶时 f_rest 占 62 个字段中的 45 个且对精度最不敏感坐标和缩放敏感保留 float32。先试features.astype(np.float16)把 f_dc / f_rest 压半精度存储直接减半再往下做 int8 定点则要带零点和 scalePLY 头里的 f4 类型也要一并改。空间分块大场景切成多个子 PLY千万高斯一个 PLY 超过 2 GB写和读都难受。思路是按空间网格或八叉树分区输出多个自包含的子 PLY命名成model_part_{i}.ply之类渲染时按视锥剔除挑块加载。可以参照scene/dataset_readers.py整场加载点云的做法扩展成按块编号加载块文件之间可并行读写与传输。内存映射np.memmap 按需读PLY 是文本头 二进制 float 体解析完头之后不必走PlyData.read整块入内存直接映射数据区np.memmap(path, dtypenp.float32, moder, offsetheader_size, shape(N, F))用哪行读哪行。极端情况下先只读 xyz 列做粗剔除再对可见高斯回读完整字段。⚠️ 踩坑速查现象根因处理加载后报 assert / 颜色发灰、偏色加载与保存的 sh_degree 不一致f_rest_ 个数对不上 3(L1)²−3保证--sh_degree与保存时一致重训或重新导出load_state_dictshape mismatch高斯数量变过稠密化/剪枝PLY 与 .pth 不同步只用 .pth 续训参数与优化器同源别拿 PLY 配旧优化器状态PLY 文件过大默认 SH 3 阶保存、百万级高斯每高斯【免费下载链接】gaussian-splattingOriginal reference implementation of 3D Gaussian Splatting for Real-Time Radiance Field Rendering项目地址: https://gitcode.com/gh_mirrors/ga/gaussian-splatting创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑