高光谱成像与 3D Gaussian Splatting(3DGS)在多数人眼中属于两条不同的技术路线:前者处理几十上百个波段的遥感数据,后者负责 RGB 新视角合成。可当“Hyperspectral”“Bidirectional Reflectance Factor”和“3D Gaussian Splatting”同时出现在一个标题里,事情就不再是简单拼接了。BRF-GS 这类方法要解决的问题,不是给 3DGS 换一个多通道相机,而是尝试让三维显式场景表示直接学出带有物理意义的“方向反射率场”,并基于它生成任意视角下的高光谱图像。这个方向一旦走通,材质研究、遥感反演、精细农业、文物保护等场景都可以把传统逐点 BRF 测量升级为“整场景、多角度、光谱连续”的三维重建。
如果只从 RGB 3DGS 的视角去读 BRF-GS,很容易产生误判:把几十个波段拆开分别训练 3DGS 不就行了?然而 BRF-GS 更关键的变化在于基元属性和渲染目标本身。它意味着每个三维高斯不再只是携带 RGB 球谐系数,而是去表达与波长、观测几何相关的反射因子。也就是说,三维高斯从一个“能画出颜色的粒子”变成了“能描述物理反射属性的一小块表面”。
这篇文章会用场景化的方式,把 BRF、BRDF、高光谱数据立方体、3D Gaussian Splatting 这几个概念之间的链路讲清楚,再分析 BRF-GS 这类方法为什么值得关注、原理上做了哪些取舍、适合什么数据与任务,以及如果要从零复现或做同类实验,需要在数据、代码、验证指标上避开哪些坑。文章不会替代原始论文,也不会凭空给出不存在源码的复现结果;作者会基于公开 3DGS 通用结构和论文标题的技术组合,给出可运行的实验思路与参考实现,供后续开源后对照。
1. 这篇文章真正要解决的问题
先回到一个实际问题:在没有 BRF-GS 这类方案之前,想得到“一个真实三维场景的高光谱 BRF 分布”,通常要怎么做?
传统路线大概是这样:先用分光辐射度计在实验室或野外逐点测量目标的方向反射特性;如果要覆盖不同观测天顶角、方位角和波长,就需要使用具备多角度观测能力的 BRF 测量装置。装置本身昂贵,测量速度慢,而且一次只能测一个样点。对于植被、土壤、岩壁这种空间连续变化的自然场景,逐点测量基本不现实。另一条路线是直接用机载或地面高光谱成像仪从多个角度飞一遍,得到多角度高光谱影像,但各角度影像之间往往是独立的二维图像,没有显式关联到同一套三维场景结构上,后续做 BRF 建模时还要先解决几何配准、角度索引和逐像元反演的问题,流程非常割裂。
NeRF 出现后,人们尝试用神经辐射场把多视角 RGB 图像重建成连续三维场景,并在特定视角下合成新图像。但标准 NeRF 输出的是 RGB 颜色,而不是带有物理意义的双向反射因子。如果要把 NeRF 扩展到高光谱维度,最常见做法是逐波段训练多个辐射场,或者让网络输出一个高维光谱向量。逐波段方案的计算代价随波段数线性增长,而且各个波段独立训练后很难保证空间几何一致:同一个物体的轮廓在不同波段模型里可能在毫米级上有偏移,最终叠加成高光谱数据立方体时会出现空间伪影和光谱不连续。也是在这里,3DGS 的显式离散结构显现出独特价值。3DGS 把场景表示成一组带位置、形状、不透明度和颜色属性的三维高斯,渲染时通过可微分光栅化快速合成图像。相比 NeRF 的连续隐式场,它的优势不只是渲染速度快,更重要的是每个基元的属性可以被替换、扩展、正则化。把 RGB 颜色属性升级成“方向相关、波长连续”的反射属性,是一种很自然的扩展方向。这也是 BRF-GS 的核心动机。
用一句话概括:BRF-GS 试图把三维高斯从一个纯粹的几何外观表示,升级为可反演的物理反射场离散单元,让高光谱 BRF 建模和新视角光谱图像生成在同一个框架里完成。它真正降低的,是“多角度高光谱数据 → 三维结构 → BRF 参数场”这一整条链路的工程复杂度;它改变的,是传统逐点测量和逐波段建模中反复出现的几何一致性、维度爆炸和流程割裂问题。
因此,这篇文章适合三部分读者:第一,做 3DGS 相关研究的开发者,想了解如何把场景表示从 RGB 扩展到光谱物理量;第二,做高光谱遥感与材质反演的科研人员,想知道神经渲染和 3D 显式表示能不能替代部分传统 BRF 测量工作;第三,正在规划多角度高光谱采集与合成数据生产的数据工程师,想确认这套新方法到底能不能落地,坑在哪里。
2. 核心概念:BRF、BRDF、高光谱与 3DGS
BRF-GS 这个词组里包含了三个容易混淆的基础概念。正式分析原理之前,先把它们的关系理顺。很多图形学背景读者把 BRF 直接当成 BRDF,这是最常见的误区;很多遥感背景读者又把 3DGS 当成简单的点云渲染工具,低估了它可微分优化背后的意义。只有把这些术语放在同一个坐标系里,后续的原理拆解才不会出偏差。
2.1 BRF 与 BRDF:不是同一个物理量
BRDF(Bidirectional Reflectance Distribution Function,双向反射分布函数)描述的是微小面元上,某一入射方向的辐照度贡献如何转化为某一出射方向的辐射亮度,单位是 sr⁻¹。BRF 的完整名称是 Bidirectional Reflectance Factor,它通常定义为目标表面在给定入射、观测几何下的反射辐射通量与理想朗伯参考板在相同照明条件下的反射辐射通量之比,是一个无量纲量。
简单说,BRDF 是微分意义上的方向反射属性,BRF 则是相对参考板的“可测量反射因子”。遥感领域大量产品直接使用 BRF,因为实际测量更容易标定:室内用标准白板,野外用太阳作为光源,测量对象是整个像元足印内的平均反射特性。而 BRDF 需要严格的辐射度定义,反演链路更长。
表格对比:
| 维度 | BRDF | BRF |
|---|---|---|
| 全称 | Bidirectional Reflectance Distribution Function | Bidirectional Reflectance Factor |
| 物理含义 | 方向反射率分布函数 | 相对理想朗伯参考板的反射因子 |
| 量纲 | sr⁻¹ | 无量纲 |
| 典型测量方式 | 实验室测角仪,精确辐照度/辐射亮度 | 参考板比较法,更接近遥感反演链路 |
| 常见应用 | 渲染、材质建模、光学设计 | 遥感地表参数反演、植被/土壤方向反射研究 |
从标题判断,BRF-GS 选用 BRF 而不是 BRDF,很可能是因为方法主要面向遥感与地物方向反射建模:最终输出的是波长连续、观测方向连续的反射因子,而不是一个完整意义上的双向反射分布函数。这个措辞差异决定了方法验证时往往会使用光谱角、BRF 曲线、方向反射率等遥感指标,而不只是 RGB 图像的 PSNR 与 SSIM。
2.2 高光谱图像的三维数据立方体
普通 RGB 图像只有红、绿、蓝 3 个通道。高光谱成像仪则把某一光谱区间连续划分为几十到几百个窄波段,每个像素上得到的是一条光谱曲线。把二维空间维度和波长维度叠在一起,得到的就是一个三维数据立方体:高为空间行数、宽为空间列数、通道数为波段数。
高光谱数据最核心的价值在于“图谱合一”。两个物体在 RGB 下可能看起来完全一样,但在近红外或短波红外波段可能差异显著。因为这些波段对应的是分子振动、水分吸收、叶绿素含量等物理化学特征。传统 RGB 3DGS 只能看到“颜色”,难以直接判断材质和理化属性;而高光谱 BRF 建模可以让每个三维基元都携带一条连续光谱反射曲线,并根据观测角度变化。
高光谱数据也给渲染带来实际困难。可见光 3DGS 需要学习 3 个通道的颜色;如果简单扩展到 200 个波段,每个高斯基元就要多管理近 200 个数值。如果每个波段都使用一组独立球谐系数,参数总量可能膨胀几十倍。这也是 BRF-GS 必须在光谱维度和方向维度上做合理压缩的原因。
2.3 3D Gaussian Splatting 为什么适合做属性扩展
3DGS 的基本思想是用大量三维高斯分布表示场景。每个高斯基元拥有一组可学习参数:中心位置、协方差矩阵、不透明度以及颜色。颜色通常用球谐系数表达,这样渲染时可以从不同视角得到略有差异的颜色,近似表达非朗伯反射。
渲染流程大致是:先把三维高斯投影到二维图像平面,再按深度排序,对每个像素进行 alpha blending 合成颜色。由于整个过程可微分,位置、形状、颜色都可以通过梯度下降优化。相比 NeRF 逐像素查询 MLP,3DGS 是离散显式表达,没有隐式网络的全场景耦合,因此用户可以方便地对单个基元做属性修改、分裂、克隆、删除,也可以在不同高斯之间共享某一组参数。
BRF-GS 看中的正是这种可扩展的显式属性结构。一个三维高斯在几何上是一个高频细节可控的椭球,在属性上却可以是任意可微函数。把它内部的 RGB 球谐系数替换为“方向相关 + 波长相关”的 BRF 参数,渲染时按波长切片输出,就形成了一条通往高光谱 BRF 场景建模的最短路径。
2.4 BRF-GS 到底想做什么
从 BRF-GS 这个名称解析,可以拆成两层目标。第一层是 Hyperspectral Bidirectional Reflectance Factor Modeling,即对场景中每个可见表面建立随波长和观测方向变化的反射因子模型;第二层是 Image Generation,即基于这个模型合成指定视角、指定波长范围的高光谱图像。前者是物理量建模,后者是渲染输出。
如果用更工程化的语言来表达:BRF-GS 的输入很可能是多角度、多波段的高光谱图像及对应相机位姿;输出则是两个东西,一个可重投影的显式三维高斯场景,以及一个能与输入视角一致、也能生成未见角度高光谱图像的渲染器。这里的 BRF 参数会以某种连续或离散的形式绑定在高斯基元上,而不是像普通 3DGS 那样只绑定一段视角相关的 RGB 颜色。
需要提醒的是,BRF-GS 并不是要替代真实辐射传输模型。它更偏向数据驱动的“场景级 BRF 重建”,优势在于能够把几何、方向反射和光谱信息一次性统一到同一套表示中。至于它能否从单次光照测量中恢复出完整 BRF,这取决于采集条件,也是全文后几章要反复强调的边界。
3. BRF-GS 的核心原理:从颜色球谐到光谱方向反射场
BRF-GS 与普通 3DGS 的关键差异,可以概括成一句话:普通 3DGS 的基元颜色参数只服务于“像不像目标图像”,BRF-GS 的基元参数则需要同时满足物理合理性和方向光谱一致性。要理解这种差异,可以先看看“逐波段 3DGS”会失败在什么地方。
3.1 为什么不能逐波段训练 3DGS
最直观的高光谱新视角合成方案,就是每个波段单独训练一个标准 3DGS。假设数据集有 100 个波段,那就训练 100 个独立 3DGS 模型。如果场景由 50 万到 200 万个高斯基元组成,100 个模型就意味着上亿个高斯参数,显存和训练时间都非常可观。更麻烦的是几何一致性问题:每个波段独立聚类、分裂、克隆后,基元位置往往会有细微差异;单独看某一个波段,图像都能接受,但把 100 个波段堆叠成高光谱立方体后,边缘会出现空间抖动,像元光谱曲线会有类似噪声的锯齿。对光谱分析而言,这属于严重不可用。
另一种方案是共享同一个几何结构,但为每个波段保存一组颜色系数。这一版比独立训练略好,却仍然没有利用光谱维的连续性。相邻波段之间的反射率通常高度相关,彼此独立存储等于浪费了光谱先验。更致命的是,这种方式没有给高斯基元一个物理上可解释的属性:某个基元在 650nm 和 900nm 的反射系数是孤立的两个数字,它们之间不会自动形成平滑光谱。
BRF-GS 的核心改进之一,应当是“让高斯基元在空间上共享几何,在光谱上共享一组基函数”。每个基元携带的不是一串孤立的波段颜色,而是一组可以把任意波长映射为反射因子的连续光谱系数。渲染时,输入波长 λ,输出对应波段的反射因子;观测方向变化时,这组系数还需要能够表达 BRF 的角度效应。
3.2 参数设计的两种可能思路
从降参数量角度判断,BRF-GS 大概率会在方向维度和光谱维度上采用低秩或函数化建模。因为如果简单地把每个基元的 RGB 球谐扩展为 100 波段球谐,球谐系数会从十几个膨胀到上千个,训练难度和不稳定性都会显著增加。一种合理的思路是用“方向基函数 + 光谱基函数”联合表达:
BRF_g(ω_i, ω_o, λ) = Σ_k Σ_l a_{g,k,l} · D_k(ω_i, ω_o) · S_l(λ)
其中 D_k 是方向基函数,负责表达入射方向与观测方向的变化;S_l 是光谱基函数,负责表达波长连续性;a 是每个高斯基元可学习的张量系数。如果把上面的双线性形式再压缩成共享基函数加逐基元系数的结构,参数规模就可以控制在可接受范围内。
另一种更接近工程实现的做法是保持标准 3DGS 的球谐方向表达,但不直接输出 RGB,而是输出一组光谱基函数的权重。例如每个基元仍维护一套方向球谐系数,该系数对应的是“光谱反射曲线基权重”;渲染时先按视角插值得到当前方向的权重向量,再乘上一个全局光谱基字典,得到当前波长的反射因子。这种方式的好处是方便复用现有 3DGS 光栅化管线,只要把最后颜色拼接部分替换为“权重到光谱的线性映射”即可。
无论采用哪种设计,“方向维度用球谐/方向基表达,光谱维度用连续基函数或小字典表达”都是更稳妥的判断。这也是 BRF-GS 的高光谱建模和逐波段建模形成本质区别的地方。
3.3 渲染与物理量语义的转换
BRF-GS 在渲染时不能照搬 RGB 渲染方程。普通 3DGS 渲染的是“从某个视角看到的辐亮度颜色”,光源能量已经被隐式编码在球谐系数中。BRF-GS 要生成带物理量语义的高光谱 BRF 图,则需要建模一条与波长、入射方向和观测方向相关的反射路径。当场景由多角度高光谱影像重建时,入射方向是已知的太阳方向或实验室光源方向;三维空间中每个高斯块虽然在概念上是椭球粒子,但在属性层面可以承载该位置表面微元的 BRF 信息。
实际渲染时,第 i 个高斯基元先根据当前观测光线方向、已知光照方向与法线信息,计算出该波长下的 BRF 值;再结合不透明度、投影面积和光照入射余弦,得到该基元对像素的辐射贡献;最后按深度顺序 alpha blending。这样,最终每个像素得到的不是伪 RGB 颜色,而是当前观测几何下的高光谱 BRF 向量。如此生成的数据立方体可以直接用于光谱分析,而不是只能拿来看图。
3.4 构图:一个三维高斯,一块微型 BRF 面元
对不熟悉三维高斯的读者,可以把上述过程简化成一个直观类比。每个三维高斯,就像场景中悬浮的一块“微型表面碎片”,它有位置、尺寸、朝向、透明度和与光谱、方向相关的反射属性。无数碎片在像素上的投影叠加,就构成了完整图像。
在 RGB 3DGS 中,这些碎片只负责“看起来像”;在 BRF-GS 中,每一块碎片还需要“在物理上说得通”。如果某块碎片被放置在植被高光谱图像的同一位置,那么它不同波长反射率曲线应当有植被光谱的典型形态:红光附近吸收、近红外平台高反射。如果模型输出完全违背这种光谱形态,哪怕 RGB 可视化看不出问题,BRF-GS 的方向建模也失败了。这也是为什么 BRF-GS 的验证必须引入光谱角和 BRF 曲线等指标,而不是只看渲染图是否清晰。
4. BRF-GS 的适用场景与边界条件
BRF-GS 并不是所有高光谱任务的通用解。它最适合的是“同一场景有多角度、多波段观测”的重建类问题。理解适用边界,可以避免把方法用在错误任务上。
4.1 适合的三类场景
第一类:实验室或工业环境的固定目标多角度扫描。用转台、机械臂或测角系统让目标旋转,配合高光谱相机从不同天顶角和方位角采集影像。这类环境光照可控、几何关系清楚,是 BRF-GS 最容易获得高质量输入的场所。常见应用包括材料分选、表面缺陷检测、文物与艺术品光谱档案建立。
第二类:目标尺度适中的地表场景方向反射研究。例如农田地块、裸土小区、岩壁断面,通过无人机多角度飞行或多平台协同观测获得同一地物的多角度高光谱数据。BRF-GS 能把多角度影像整合成带有三维结构的 BRF 场景,对于反演叶面积指数、植株含水量等参数有直接参考价值。
第三类:三维数字资产与渲染器之间的桥接任务。如果已经有三维几何模型,但缺少真实材质的 BRF 数据,多角度高光谱重建得到的 BRF-GS 场景可以作为物理渲染器的材质库来源,让下游生成任意光照条件下可见光或特定波段图像。
4.2 目前不太适合的场景
首先是单角度、单光照的大范围航空高光谱影像。常见机载高光谱推扫影像通常只提供一次过境的单一观测角度,缺少同一目标在多个方向上的 BRF 样本。单次观测产生的三维重建属于典型的病态问题,BRF-GS 也解决不了“无中生有”的角度外推。
其次是未经辐射定标的自然影像。很多 RGB 数据集没有绝对辐亮度信息,模型无法从像素值中分离出表面方向反射属性。如果把这一类数据直接改成 BRF-GS,得到的结果更可能是“过拟合到特定光照的外观模型”,而不是具备物理迁移能力的反射率产品。
第三是复杂镜面反射物体。高光表面、金属镜面、水面镜面反射强度随角度变化非常剧烈,高斯混合在稀疏优化条件下很难表示微小面元级别的高频反射峰。即便 BRF-GS 在原理上能拟合这种变化,实际优化也容易让高斯基元数量爆炸或产生大量细长伪基元。
4.3 关键局限:光照分离的边界要清醒
BRF-GS 名称非常物理,但任何从图像重建出来的模型都必须面对一个事实:从图像观测到物理反射率的反问题,本质上存在光照与反射属性之间的病态性。同一张图可以由较暗光照下的高反射率表面产生,也可以由较强光照下的低反射率表面产生。只有通过标定板、已知辐照度传感器或其他先验不断约束光照参数,BRF-GS 才能真正输出严格物理意义的反射因子。
因此,对该方法最恰当的解读是:它能够在统一光照条件、经过辐射定标的多角度高光谱输入下,建立场景级别的方向 BRF 模型,并能生成模型可见角度范围内的光谱图像;它不等同于采集一张自然照片就能万能地反演 BRDF 的魔改工具。
5. 复现 BRF-GS 类方案的环境与数据准备
由于 BRF-GS 的官方源码不一定第一时间公开,本节给出的复现建议不是针对某一仓库的安装文档,而是面向“这类流程需要什么环境、数据怎么组织”的通用指南。后续如果论文公开代码,对照环境即可快速替换。
5.1 环境参考
3DGS 的官方实现属于 PyTorch 与 CUDA 深度绑定项目,核心渲染器通常是 C++/CUDA 可微分光栅化扩展。BRF-GS 如果沿用这套架构,参考环境一般包括:
| 组件 | 参考版本或要求 |
|---|---|
| 操作系统 | Linux(Ubuntu 20.04/22.04) |
| GPU | NVIDIA RTX 3090/4090 或更高,显存建议 24GB 以上 |
| CUDA | CUDA 11.8 或更新版本,与 PyTorch 对应 |
| Python | 3.8 至 3.10 |
| PyTorch | 2.x |
| 3DGS 核心 | diff-gaussian-rasterization |
| 稠密化 | 需要与 3DGS 类似的自适应控制逻辑 |
需要注意:标准 3DGS 光栅化器与颜色通道数强相关。很多开源的 CUDA kernel 固定输出 3 通道。BRF-GS 如果直接输出几十个通道,需要修改光栅化内核中的通道数与混色循环。做实验前,先确认目标仓库是否支持任意通道数输出,这会直接影响开发量。
5.2 多角度高光谱数据采集清单
数据准备是 BRF-GS 最容易被低估的环节。RGB 3DGS 大多依赖 COLMAP 从照片中恢复相机位姿;多角度高光谱数据却不一定能直接套用。高光谱相机如果只在某些波段成像质量好,其他波段噪声大,就会影响特征点提取。此外,推扫式高光谱成像需要一个维度的扫描运动,很难像普通相机那样“随手拍一张”。
更稳妥的采集流程是把几何位姿单独确定好:固定目标与相机坐标系,借助转台、机械臂或高精度云台记录每次拍摄的角度,再把高光谱图像按角度索引展开。如果场景没有绝对几何,至少也要用同一光照条件下拍摄的可见光照片跑 COLMAP,并把可见光相机坐标系与高光谱相机坐标系事先标定。
从材料处理流程上看,数据组织大致如下:
1. 辐射定标: 拍摄暗电流、白板参考,把原始 DN 值转换为相对反射率; 2. 空间几何标定: 使用棋盘格或圆点标定板,解算高光谱相机内参与畸变; 3. 多角度观测: 按固定角度网格采集目标高光谱图像,保存角度元数据; 4. 空间重采样: 将所有角度图像裁剪并重采样到相同空间分辨率; 5. 数据划分: 按观测角度划分训练集/验证集,禁止按同一角度图像内随机像素划分; 6. 格式封装: 保存为 ENVI/GeoTIFF/npy 格式,同时写入波长列表和观测角。如果数据来源是公开数据集或仿真渲染合成数据,则应先确认它是否提供了 BRF 真值。真值存在与否决定了 BRF-GS 训练时是“仅图像监督”还是“图像与 BRF 双重监督”。后者收敛更稳定,也更容易判断重建质量。
5.3 输入数据的保存示例
对于自采数据,推荐直接使用.npy或.h5保存图像立方体,并在旁边放一份 JSON 记录元数据:
{ "sensor": "hyperspectral_pushbroom", "wavelengths_nm": [400, 410, 420], "view_zenith_deg": [0, 15, 30], "view_azimuth_deg": [90, 120, 150], "sun_zenith_deg": 45, "sun_azimuth_deg": 180, "radiance_calibrated": true, "reflectance_reference": "spectralon_panel" }这段 JSON 不是代码运行必须项,但对实验管理和论文复现非常重要。BRF 方向建模高度依赖角度元数据,如果角度标签丢失,后面的监督直接失效。
6. 核心实现思路与参考代码
由于 BRF-GS 没有在输入材料中附带源码,下面给出的是“基于 3DGS 通用结构 + 高光谱 BRF 目标”的实现思路推演,目的是帮助读者在官方代码开放前先建立可执行的实验框架。这里提供三段参考代码:第一段读取高光谱数据并进行波段索引,第二段定义带光谱扩展的高斯基元与渲染伪代码,第三段给出高光谱质量指标计算。
6.1 高光谱数据读取与波长索引
BRF-GS 渲染时需要传入连续波长或离散波段索引。与 RGB 不同的是,波段索引不应该被当作普通分类通道,需要理解每个波段对应的物理波长。先写一个通用读取函数:
import numpy as np def load_hs_image(path: str): """ 加载保存在 npy 格式下的高光谱数据立方体。 约定返回值 shape 为 (H, W, C),且按波长升序排列。 """ cube = np.load(path) if cube.ndim != 3: raise ValueError("expected shape (H, W, C), got {}".format(cube.shape)) return cube.astype(np.float32) def wavelength_to_index(wavelength_nm: float, wavelengths: np.ndarray) -> int: """把连续波长映射到最近的离散波段索引。""" idx = int(np.argmin(np.abs(wavelengths - wavelength_nm))) return idx if __name__ == "__main__": # 示例:假设有 50 个波段,波长从 400nm 到 900nm 均匀间隔 wl = np.linspace(400, 900, 50) idx = wavelength_to_index(650.0, wl) print("650nm nearest index:", idx)对 BRF-GS 而言,波长索引的价值不仅在于取训练数据真值,还在于它提供了连续光谱先验的查询入口。如果模型内部采用谱基函数表达,那么输入 620nm 和 630nm 都能输出平滑变化的结果;如果只按离散波段做查询,就会退化成逐波段建模。
6.2 高斯基元属性的光谱扩展思路
标准 3DGS 中,每个高斯基元的颜色由球谐系数表达。BRF-GS 中,可以把“颜色”替换成“光谱权重向量”。
下面用 Python 风格伪代码描述高斯基元扩展的基本属性,实际实现需要把这些属性绑定到 CUDA 可微分光栅化器中:
class BRFGaussianPrimitive: """ 一个支持高光谱 BRF 表达的三维高斯基元。 注意:这是算法逻辑层面的参考描述,不是可直接调用的源码。 """ def __init__(self, num_dir_basis=16, num_spec_basis=8): # 几何属性:与 3DGS 一致 self.position = None # 3D 中心坐标 self.covariance = None # 3x3 协方差 self.opacity = None # 不透明度 # 方向属性:方向基函数权重 self.dir_coeffs = None # shape: (num_dir_basis,) # 光谱属性:对每个方向基权重,存一组光谱基系数 self.spec_coeffs = None # shape: (num_dir_basis, num_spec_basis) def infer_brf(self, view_dir, light_dir, wavelength_nm): """ 根据观测方向、光照方向和波长,输出该基元的 BRF 值。 实际优化中这是一个可微混合函数。 """ dir_feature = 0.0 for k in range(self.dir_coeffs.shape[0]): # 这里应调用方向基函数,例如球谐或半球谐 basis_k = direction_basis(self.dir_coeffs[k], view_dir, light_dir) spec_feature = 0.0 for l in range(self.spec_coeffs.shape[1]): # 这里应调用光谱基函数,也可以查预计算光谱字典 basis_l = spectral_basis(l, wavelength_nm) spec_feature += self.spec_coeffs[k, l] * basis_l dir_feature += basis_k * spec_feature return dir_feature这段代码最核心的设计是“方向与光谱分离”。方向基函数吸收了球谐等角度表达,光谱基函数吸收了连续波长映射,最终 BRF 是二者双线性耦合的结果。比直接给每个波段创建一组球谐系数更节省参数,也能提高相邻波段输出的连续性。
6.3 训练循环中的损失函数
BRF-GS 训练通常使用两类监督:一类是图像重建损失,比较渲染高光谱图与真值高光谱图之间的差异;另一类是可选 BRF 真值监督。由于高光谱反射率值通常处于 0 到 1 区间,但极端波长可能因噪声出现负值,建议损失函数在 L2 基础上增加 L1 正则,以限制光谱曲线震荡。
参考损失计算逻辑如下:
def hyperspectral_loss(pred_rgb, gt_rgb, use_l1=True, use_l2=True): """ pred_rgb 与 gt_rgb 的 shape 都是 (B, C, H, W) 或 (B, H, W, C)。 实际训练时可以按波长分块,避免一次性加载全部波段。 """ if pred_rgb.shape != gt_rgb.shape: raise ValueError("shape mismatch: pred {} gt {}".format( pred_rgb.shape, gt_rgb.shape)) loss = 0.0 if use_l2: loss = loss + ((pred_rgb - gt_rgb) ** 2).mean() if use_l1: loss = loss + 0.1 * (pred_rgb - gt_rgb).abs().mean() # 可选:光谱平滑约束,约束相邻波段差值不要过大 diff_along_wavelength = torch.diff(pred_rgb, dim=-1) # 假设通道维在最后 smooth_loss = (diff_along_wavelength ** 2).mean() * 0.01 loss = loss + smooth_loss return loss这里提到的光谱平滑约束是逐波段训练时重要差异点。把相邻波段输出约束为连续变化,能有效抑制高光谱图像中常见的孤立波段噪声斑点,同时让 BRF 曲线在波长维上更接近真实材料反射率特征。
6.4 渲染管线改造点
如果要在标准的 3DGS 光栅器源码上改造,主要修改位置有三处。第一,颜色属性读取:不再直接读取 RGB 球谐系数后求颜色,而要先由当前高斯的方向权重乘光谱系数,得到指定波长的 BRF 值;第二,alpha blending 循环:需要支持单波长渲染输出;第三,loss 回传:梯度不仅要回传到方向系数,还要回传到光谱系数。如果光栅器一次渲染全部波段,显存会非常吃紧;更稳妥的做法是每次随机采样若干个波长或波长块,递进式训练多组波长输出。
为避免改动 CUDA kernel 导致工程周期过长,还有一个折中方案:保留标准 RGB 光栅化器,每次为某一波长渲染一张“单通道图”。也就是内部仍使用 3 通道输出,但把三个通道改造成“三个不同波长”,循环分批覆盖所有波段。这样虽然训练效率不如全定制实现高,但工程改动最小,适合快速验证算法本身。
以下是分批渲染的伪代码结构:
def render_wavelength_batch(gaussians, cameras, wavelength_chunk): outputs = {} for wave in wavelength_chunk: # 对于每个波长,调用光栅化器得到单通道或三通道渲染结果 rgb_chunk = rasterize_with_wavelength(gaussians, cameras, wave) outputs[wave] = rgb_chunk return outputs核心就是先把“波段采样”抽出来,保证单次光栅化只处理一个波长或少量波长,显存占用可控。这也是多波段方法与普通 RGB 训练在工程上最直接的区别。
7. 运行结果与效果验证:如何判断 BRF-GS 真的成功了
BRF-GS 类方法不能只看 RGB 可视化。因为高光谱数据的本质是物理量,评价体系应当同时包含图像质量、光谱质量、方向外推能力和空间几何一致性四个方向。
7.1 图像质量指标
对每个波段单独计算 PSNR 与 SSIM,最后再取平均,是最常用的方法。计算时要注意,BRF 图像通常接近反射率,值域为 0 到 1;如果数据预处理时做过按波段最大最小值归一化或白板定标,PSNR 的量纲可能不同,同一实验内部应保持一致。
7.2 光谱质量指标
光谱角制图(SAM)是一个非常适合高光谱重建的指标。它把所有像素的波段值看作一个高维光谱向量,计算预测向量与真值向量之间的夹角:
import numpy as np def spectral_angle_mapper(pred, gt): """ 输入 pred 与 gt 的 shape 都为 (H, W, C)。 返回每个像素的光谱角,单位为度。 """ dot = np.sum(pred * gt, axis=-1) norm_pred = np.linalg.norm(pred, axis=-1) norm_gt = np.linalg.norm(gt, axis=-1) denom = np.maximum(norm_pred * norm_gt, 1e-10) cos_angle = np.clip(dot / denom, -1.0, 1.0) angle_rad = np.arccos(cos_angle) angle_deg = np.degrees(angle_rad) return angle_deg # 示例:随机生成两组 10x10x20 的高光谱数据验证 pred = np.random.rand(10, 10, 20) gt = np.random.rand(10, 10, 20) sam_map = spectral_angle_mapper(pred, gt) print("mean SAM:", sam_map.mean())SAM 值越小,说明光谱曲线形态越接近。这个指标非常适合发现“整体颜色接近但波段间形状错误”的场景。比如某一波段整体偏亮、另一波段整体偏暗,PSNR 可能不差,但 SAM 会明显升高。
除了平均 SAM,还应观察 SAM 图的空间分布。如果错误集中在边缘、高光区域或遮挡区域,说明问题来自空间几何或法线方向估计;如果错误均匀分布在全图,则更可能是光谱基函数表达容量不足。
7.3 BRF 方向外推能力测试
BRF-GS 区别于逐波段 3DGS 的最大亮点,是模拟“方向反射”。验证方式建议如下。把多角度数据集按天顶角分为训练组和测试组。比如训练使用 0°、10°、20°、30° 天顶角数据,测试使用 40°、50° 天顶角数据。若在从未见过的观测角下重建高光谱图像,SAM 与 PSNR 仍保持在可接受范围,说明模型学到了有泛化性的 BRF 角度表达,而不只是记住了训练视角下的滤镜。
如果没有多角度真值数据,也可以做量级校验:在同一材质区域附近取不同预测角度下的光谱曲线,观察曲线是否在训练视角之间平滑变化。如果曲线在某个方向出现剧烈跳变,往往说明方向基函数阶数不够,或者该区域的高斯基元数量不足。
7.4 三维场景空间一致性检查
BRF-GS 重建完成后的三维高斯基元应该保持合理空间结构。如果某个波段产生大量长条形高斯,很可能是优化时把光谱差异错当成了几何差异来拟合。常见检查技巧是从一个固定相机视角渲染两个相邻波段的图像,再相减,观察差值是否主要集中在具有真实材质边界的区域。如果差值在整个图像上呈水波纹状分布,就需要增强光谱平滑损失或减少方向系数的自由度。
7.5 失败的通用排除顺序
第一次跑 BRF-GS 类实验失败时,排查顺序建议这样:先检查输入高光谱图像是否经过辐射定标;再检查波长索引是否与存储顺序一致;然后看验证数据集是否按观测角划分;最后才考虑模型结构、学习率和损失权重。很多表面上看是“模型不收敛”的问题,实际都是输入数据或角度元数据错误导致。
8. 常见问题与排查思路
BRF-GS 类实验会同时遇到图形学、遥感和工程三方面的坑。下面是几种高频问题、可能原因、排查方式和解决方案。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 训练损失震荡且不下降 | 高光谱图像值域范围差距过大,未做定标 | 检查各波段的均值与最大值 | 统一除以参考白板或按波段做物理合理缩放 |
| RGB 可视化正常,但 SAM 指标很高 | 模型只拟合了视觉上接近的颜色,没有学到光谱曲线形状 | 逐波段查看差值图与光谱曲线 | 增加 SAM 损失或光谱平滑约束 |
| 某些波段出现大量孤立噪声斑点 | 该波段信噪比低,模型在该通道过拟合 | 查看各波段单通道 PSNR | 降权低信噪比波段,或对输入做光谱平滑 |
| 稠密化后高斯数量爆炸 | 场景高光或复杂反射导致基元过度分裂 | 检查渲染残差空间分布 | 限制稠密化间隔,提高不透明度阈值 |
| 多角度验证集上误差骤增 | 训练角度与测试角度分布差异大,方向表达过拟合 | 对比不同天顶角的损失曲线 | 增大方向基函数阶数,或增加少量中间角度数据 |
| 标准 3DGS 光栅器无法输出多波段 | 光栅化内核只支持 3 通道颜色 | 查看 CUDA kernel 中的通道数定义 | 改造通道循环,或使用分波段渲染方案 |
| 光谱曲线出现非物理负值 | 模型输出没有加反射率约束 | 检查输出值域 | 在最后一层加 sigmoid 或 clip 并用物理先验约束 |
| 几何与光谱同时不收敛 | 场景复杂且 BRF 真值不足 | 检查基元位置梯度 | 先用可见光 3DGS 初始化几何,再微调光谱属性 |
实际实验中最值得提前规避的问题是“RGB 预训练权重直接迁移到高光谱 BRF”。如果先用可见光 3DGS 得到一个几何与外观模型,再试图把它迁移到另一个光照完全不同、波段范围更宽的高光谱数据上继续优化,往往会遇到几何与光谱耦合的问题。严格做法是在同一批多角度数据上做联合初始化,或者只迁移几何不迁移颜色,重新随机初始化光谱与 BRF 属性。
另一个容易忽视的坑是显存。以 100 波段数据为例,如果每次迭代都输入全部波段,单张图可能消耗十几 GB 显存。分波长块训练时,BRF-GS 类模型需要共享方向基函数和光谱基函数,避免不同块训练完后波长边界上出现割裂。实现时可以在优化器中保持同一组参数,只对输入波段做随机采样,而不是真的把几个波段的模型独立存储。
9. 最佳实践与工程建议
BRF-GS 尚属前沿交叉方向,实操经验还没有形成统一标准。如果希望把这类实验做成可复现的工程,下面几点建议可以节省大量时间。
9.1 从最小可闭环场景开始
不要一开始就尝试完整的大场景机载数据。推荐先在一个尺寸适中的物体上做闭环实验:使用实验室转台,角度范围覆盖天顶角 0° 到 45°、方位角 0° 到 360°,按固定间隔采集高光谱图像。这样角度标签天然已知,几何结构简单,BRF 变化相对平滑,便于先跑通方法再扩展复杂度。
最小场景还原到代码层面,意味着只需完成三件事:读入高光谱数据集,把角度写入数据容器;用 3DGS 重建可见光或单波段几何;在几何初始化基础上训练 BRF-GS 光谱与方向参数。闭环跑通后再去解决大尺度场景的位姿恢复、辐射一致性、大气校正等问题。
9.2 数据规范比模型结构更重要
多角度高光谱实验最大的痛苦来源是数据管理混乱。每个文件的维度顺序必须统一,建议固定为(H, W, C);波长与波段索引必须一一对应;相机外参中角度计算不能出现“方位角用弧度,俯仰角用角度”这类单位不一致。建议把每一批数据做成一个 DataInfo 对象,一次性读取所有元数据,然后训练代码不直接操作原始文件夹。
在训练脚本中,至少应记录三方面内容:使用的波长列表、训练与验证对应的观测角度划分、是否对 BRF 输出加了物理值域约束。这些信息建议一并写入训练配置文件,否则后期评估时很可能出现“不知道模型是在哪个波长范围训练出来的”的尴尬情况。
9.3 选择合理的光谱压缩表达
标准 3DGS 使用球谐系数表达方向,RGB 3 通道的球谐数量本身不大。BRF-GS 方向扩展到高光谱时,不建议直接为每个波段各存一组球谐。具体工程落地时,优先尝试“共享方向基函数 + 光谱基函数”或“学习光谱字典”的做法,这样既保证相邻波段的一致性,也避免参数爆炸。
如果暂时没有明确的物理先验,可以在实验早期先做一个简单消融:把高光谱有效波段降采样到 8 到 16 个代表波长训练,观察方向重建与光谱重建质量;如果结果可接受,再逐步增加波长数量。这个策略有助于隔离模型结构问题与数据规模问题。
9.4 区分“离线建模”与“实时渲染”
3DGS 赖以成名的优势之一是实时渲染,但 BRF-GS 的大量应用并不需要实时。如果目标是高光谱 BRF 场景档案和遥感参数反演,建议不要过度追求实时渲染速度,而是把精度、光谱一致性和物理合理性放在首位。等到模型训练完成,如果确需实时渲染,可以把学到的 BRF 参数烘焙成适合 GPU 的纹理或查找表,再供普通渲染器使用。
从工程架构上看,更推荐把三部分拆开:数据采集与定标模块、BRF-GS 训练与重建模块、光谱图像生成与评估模块。每个模块之间通过文件或标准数据结构对接,避免把角度元数据、定标系数和模型参数混在同一个脚本里。
9.5 安全与合规提醒
如果 BRF-GS 应用于航空或卫星遥感,多角度高光谱数据可能涉及地理坐标、特定目标与敏感区域。处理这类数据时必须遵守法律法规和数据授权协议,在授权范围内使用。以下属于基本要求:不在公开环境发布未授权的原始高光谱影像;对包含精确地理位置信息的数据做好脱敏;对涉及工程和生产系统的变更保持最小权限原则;每次实验前先在仿真数据或脱敏数据上验证,不直接在生产设备上执行未经验证的脚本。
10. 总结与后续学习方向
BRF-GS 的价值不在于把高光谱数据“塞进”3DGS,而在于它把三维场景表示的讨论从“如何渲染得更好看”推向“如何重建具有物理意义的反射场”。从技术演进来看,这是 3DGS 从图形学工具向遥感与材质科学工具延伸的自然结果。
以当前公开材料为基础,可以确认的核心判断是:BRF-GS 面向多角度高光谱数据,目标是实现带方向信息的高光谱反射因子场景建模和任意视角光谱图像生成;它在概念上不依赖逐波段独立训练,而是借助高斯基元的显式属性,让方向基函数与光谱基函数联合表达 BRF。相比传统逐点测量或逐波段重建,BRF-GS 在几何一致性、参数效率和新视角光谱图像合成方面有明显潜力。
接下来最值得关注的几个方向包括:如何处理自然场景中光照与 BRF 的耦合;如何把极稀疏角度数据下的方向外推误差控制在可用范围;如何在光栅化内核中真正高效地支持数十到上百个波段的连续渲染。随着官方源码和数据集的公开,这套方法很可能在三维高光谱重建、反射率产品生成、材质库构建和合成遥感数据生产等层面形成新的工具链。
如果你目前正在学习 3DGS,建议先用官方实现跑通一个 RGB 场景,理解高斯基元的创建、分裂与属性回传机制,再在本机设计一个最简化光谱扩展实验;如果结果能达到视觉一致,再去尝试引入 SAM 指标、方向外推实验和物理约束。这条路并不要求你先精通高光谱遥感,但必须认识到:当渲染目标从 RGB 变成物理量之后,“看起来清楚”不再是评判标准,“反演正确”才是。