有意思的地方不是"又一个 3D LUT",而是它动了 ISP 里最保守的一块:白平衡之后、把 raw-RGB 映射到 CIE XYZ 的那一步。这一步在绝大多数量产相机里至今仍是 Adobe DNG 规范的做法——预先在 D65 和 A 光源下标两个 3×3 矩阵,拍照时估个 CCT,在两者之间插值。C²LUT 的主张是:这套设计的两个假设已经同时不成立了。
两个假设怎么塌的
一是光源描述子。CCT 本质是把光源色度投影到普朗克轨迹上的一维坐标,对日光、白炽灯还行,但现在到处是 LED——窄带、SPD 极不平滑,色度可以离轨迹很远。两盏 CCT 相同的 LED 实际光谱可以差得离谱,用同一个插值权重取矩阵,起点就错了。
二是变换是线性的。3×3 矩阵精确工作的前提是 Luther 条件:相机光谱响应必须是 CIE 配色函数的线性组合。真实 sensor 基本都不满足,于是无论矩阵怎么标,在任意「光源 × 反射率」组合下都有系统性残差。
以往工作只补一边:Tedla 等人把 CCT 换成 xy 色度预测 CCM(补了第一个洞,仍线性);多项式 / root-polynomial / 逐像素 MLP 提升非线性(补了第二个洞,光源仍用 CCT)。C²LUT 的转折点是两边一起补。
方法的关键转折
流程很朴素:raw-RGB 先用光源白点做对角白平衡,再过一张 3D LUT 得到 XYZ。设计在 LUT 从哪来——不是固定一张,而是由光源色度现场生成:一个轻量 MLP 读入光源 rg 色度输出插值系数,把"基核(basis cores)“库线性组合成一个核,再经 Tucker 重建与因子矩阵上采样装配成 LUT。光源不再挑选一个矩阵,而是形变一整张查找表。
Tucker 分解不是数学装饰,是可落地性的关键:3D LUT 的存储与带宽随格点数三次方增长,直接存一族 LUT 在 ISP 里放不下;分解成小核 + 因子矩阵后压到能进相机硬件,而查表 + 三线性插值本就是 ISP 已有的算子。得和前几天读的 StatLUT 划清界限:那篇从 Lab 统计量生成 LUT 做风格调色,是审美侧;C²LUT 做到 XYZ 的比色映射,是还原侧,指标是 ΔE00 而不是"好不好看”。
数据侧也补了一块:从公开测量库汇了 1,473 条 SPD(标准光源、荧光灯、LED),与反射率库(41M、KAUST 高光谱、Macbeth 色卡)和三台相机的光谱响应做光谱渲染,合成 RAW–XYZ 对;训练只用 41M 的 train split,KAUST 和色卡纯测试。论文报告 ΔE00 最多降 20%、角度误差最多降 18%,LED 下增益最大。
它可能怎么进入真实工作流
最直接的是手机与工业相机的 ISP 标定流程:今天标定成本很大一块花在"多标几个光源下的 CCM"上,C²LUT 换成一次离线训练出基核库,现场只需一个色度估计,对室内 LED + 窗口日光这类混合光照尤其有意义。其次是跨设备颜色一致性:跨相机泛化虽被列为 future work,但把"光源条件"和"相机响应"拆成两个独立输入,本身就是朝那走的结构。
第三条和这个专栏直接相关:越来越多的下游是大模型——生成式修图、VLM 读图、神经 ISP,几乎都建在 ISP 输出之上。颜色一旦在比色映射这步偏了,后面无论多大的模型都只是在一个偏掉的坐标系里工作。它划了一条界线:比色映射这一段,恰恰是不该交给大模型去猜的部分,要的是物理正确和可标定,不是似然最大。
局限与存疑
- 每台相机一套模型。三台相机(Canon 40D、Sony A6100、华为 Mate 20 Pro)分别训练,换 sensor 要重训;作者已承认这是主要缺口。
- 强依赖上游光源估计。入口是光源 rg 色度,AWB 错了 LUT 就选错形状。论文做了误差鲁棒性分析,但那是受控扰动,不等于真实 AWB 的失败模式(如大面积单色物体导致的系统性偏移)。
- 训练数据几乎全靠光谱渲染合成。1,473 条 SPD 听着多,但市售 LED 的 SPD 空间覆盖多少、是否偏向某几类白光 LED,值得等数据集放出后自己核。
- LUT 格点数与容量的取舍交代不清。极端饱和色与近黑区的插值行为、会否引入分块伪影,是真上 ISP 先撞到的。
代码与数据集:https://github.com/claudiom4sir/C2LUT (截至 2026-08-07 仅有 README,内容未放出)。