3DGS 深度提取怎么做?从渲染结果中获取深度图的完整方法

来源:HTML教程作者:马来西亚程序员头衔:程序员
导读:本期聚焦于马来西亚程序员创作的《3DGS 深度提取怎么做?从渲染结果中获取深度图的完整方法》,敬请观看详情。3D Gaussian Splatting 渲染出来的通常只是彩色图像,想要拿到每个像素的深度值该怎么做?本文围绕这一常见需求展开,先讲清楚深度信息在光栅化过程中的来龙去脉,说明深度本质上是高斯点沿视线方向的加权累积结果,再介绍修改 CUDA 渲染器输出深度通道的具体思路,包括渲染管线中 alpha 混合公式的扩展、深度排序与累积的实现细节,同时给出基于gsplat和官方代码的两种可行路径,并分析期望深度、中值深度两种计算方式的差异,以及深度图质量评估与常见问题的排查方法,帮助你在自己的3DGS项目里稳定提取可用的深度图。

做 3D Gaussian Splating(以下简称 3DGS)的同学经常会遇到一个需求:模型训练好之后,除了渲染漂亮的 RGB 图像,还希望拿到每个像素的深度值,用于下游的 SLAM、三维重建、场景补全或者前景分割任务。但官方实现默认只输出彩色图,深度信息虽然在光栅化过程中被计算过,却没有被保存下来。这篇文章就来详细聊聊怎么从 3DGS 的渲染结果中提取深度图,包括原理层面的分析和具体代码层面的修改方法。

3DGS 深度提取怎么做?从渲染结果中获取深度图的完整方法

深度是怎么在渲染管线里产生的

要理解深度提取,得先看 3DGS 的渲染公式。3DGS 把场景表示成一组带颜色的三维高斯椭球,渲染某个像素时,把所有投影到该像素上的高斯按深度从近到远排序,然后依次做 alpha 混合。最终的像素颜色可以写成累加形式:

C = sum_i(c_i * alpha_i * T_i)
T_i = prod_j<i (1 - alpha_j)

其中 c_i 是第 i 个高斯的球谐系数计算出的颜色,alpha_i 是这个高斯投影到当前像素后的二维不透明度,T_i 是前面所有高斯的透过率。这个公式大家都很熟悉,而深度提取的核心洞察其实非常简单:既然颜色可以加权累积,深度当然也可以。把公式里的颜色换成分割线到像素的距离,就得到了期望深度:

D = sum_i(d_i * alpha_i * T_i)

这里的 d_i 是第 i 个高斯中心到相机平面的深度值,也就是 view space 下的 z 坐标。渲染完一个像素的所有高斯后,累加得到的 D 就是该像素的深度,最后再除以总不透明度做归一化,保证半透明边缘区域的深度也合理。这个深度通常被称为 expected depth 或者 mean depth,它反映的是该像素视线方向上所有高斯的加权平均位置。

需要特别注意的是,深度提取必须在 CUDA 光栅化内核里完成,而不是事后从 RGB 图反推。因为排序信息和高斯的逐个贡献量只在渲染过程中存在,渲染结束后就丢掉了。这也是为什么几乎所有深度提取方案都要改渲染器代码的原因。

修改官方 CUDA 渲染器输出深度

如果你用的是原版 3DGS 代码,深度修改集中在 submodules/diff-gaussian-rasterization 这个子模块里。核心文件是 render_cuda.cu 和 config.h。第一步是在 config.h 中把渲染通道数从 3 改成 4:

#define NUM_CHANNELS 4  // 原本是3,增加一个深度通道
// 同时在 renderCUDA 内核中:
float accumulated_depth = 0;
// 每处理一个高斯时:
accumulated_depth += (depth_in_view * alpha * con_o.w);
contrib += con_o.w;
// 像素遍历结束后:
out[collected_id] 即深度值 = accumulated_depth / max(contrib, 1e-4);

其中 con_o.w 是 alpha 乘以透过率 T 的合成贡献权重,depth_in_view 可以在投影阶段从 t_view 矩阵变换结果里取 z 分量。由于相机朝向不同坐标系约定可能不同,注意 z 取值方向,必要时取相反数,保证深度为正。

第二步是修改 python 端的 rasterize_gaussians 调用,为输出分配四通道的 tensor,渲染完成后再把前三通道拆成 RGB、第四通道拆成深度。深度图一般会用伪彩色可视化,比如用 matplotlib 的 viridis 或者 turbo 色图,先做 min-max 归一化再映射,视觉效果会比较直观。修改完成后重新编译子模块:

cd submodules/diff-gaussian-rasterization
pip install .

这个方案的好处是你完全掌控渲染逻辑,可以在累积深度的同时把 final_T、中值深度、最小深度等辅助信息一并输出,灵活性最高。缺点是每次改代码都要重新编译,而且和官方仓库的更新会产生冲突,维护成本略高。

使用 gsplat 等第三方库的现成支持

如果不想自己动 CUDA 代码,可以借助 nerfstudio 团队维护的 gsplat 库。这个库对深度渲染做了原生支持,调用 rasterization 函数时直接提供了几个相关参数:render_mode 可以设为 RGB+D 模式,一次渲染同时输出颜色和深度;另外还支持 depth_mode 参数,可选 expected 模式和 median 模式。典型的调用方式如下:

from gsplat import rasterization
render_colors, render_alphas, meta = rasterization(
    means=gaussians.means,
    quats=gaussians.quats,
    scales=gaussians.scales,
   opacities=gaussians.opacities,
    colors=sh_degree_0_colors,
    viewmats=view_matrix,
    Ks=intrinsics,
    width=W, height=H,
    render_mode="RGB+D",   # 输出四通道,前3为RGB,第4为深度
)

gsplat 的安装也简单,pip install gsplat 即可,它会自动编译对应 CUDA 架构的内核。如果你在训练阶段就需要深度监督,比如结合单目深度估计模型做正则化,gsplat 的可微分深度输出可以直接接进 loss,训练和推理阶段都不需要额外的代码改动。

除了 gsplat,还有一些社区维护的 3DGS 深度变体仓库,比如支持 COLMAP 深度监督的 Depth-Regularized GS 项目,它在训练时用单目深度网络估计的深度图约束渲染深度,能明显改善弱纹理区域的几何质量。如果你提取深度的目的就是为了让重建更准,可以参考这类项目的训练策略,而不只是事后提取。

期望深度与中值深度的差异及常见问题

同样是深度图,expected depth 和 median depth 的含义并不一样。期望深度是所有高斯贡献的加权平均,在半透明区域会被前景和背景拉扯,出现夹在中间的过渡值;中值深度则是累积不透明度首次超过 0.5 时对应的那个高斯的深度,更接近深度图的传统定义,边缘更锐利。做表面重建或和 COLMAP 稀疏深度对齐时,中值深度通常更稳;做场景融合或视角插值时,期望深度更平滑自然。gsplat 两种都支持,自己改 CUDA 的话建议两个都输出,按需选用。

实际使用中还有几个常见坑值得提醒。一是坐标系问题,3DGS 默认在 world space 训练,深度提取必须在 view space 做,忘乘 view matrix 得到的深度图会完全错乱;二是背景区域没有高斯覆盖时,深度值可能为零或 NaN,需要用 alpha 通道做 mask,把无效像素过滤掉再用于下游任务;三是浮动伪影会污染深度图,训练不充分或白点噪声没清理时,深度图上会出现贴着相机的异常小值,建议训练完成后先用 3DGS-MCMC 或者简单的密度阈值清理一遍高斯再提深度。

最后提一下深度质量的评估。如果有 LiDAR 或者 COLMAP 稀疏点云作为参考,可以在有效像素上计算尺度对齐后的 L1 误差和相对误差;没有参考数据时,也可以做多视角一致性检查:同一区域从不同视角提取的深度反投影回三维空间,理想情况下点云应该重合,偏差大的区域往往就是几何质量差的地方。通过这些检查手段,你就能确认提取出的深度图是否真正可用,而不是只看起来好看。

总结一下,3DGS 的深度提取本质上是把 alpha 混合公式从颜色扩展到深度的过程,要么自己修改 CUDA 渲染器增加一个输出通道,要么直接用 gsplat 这类支持深度渲染的库。理解了期望深度和中值深度的区别,处理好坐标系和无效像素问题,就能在自己的项目里稳定拿到高质量的深度图了。

3DGS深度提取深度图渲染Splatting修改时间:2026-09-16 00:44:42

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0916/57604.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。