色彩阴影(Color Shading)校正原理

色彩阴影,说白了就是画面中间和边缘颜色不一样。你拍一张纯灰卡,中间发红,边缘发绿,这就是典型的 Color Shading。我刚开始调这个的时候,总觉得是镜头没装好,后来才发现——这是 sensor 和 lens 共同作用的结果。

今天咱们就把它拆开揉碎了讲。核心就三个东西:R/G、B/G 比率校正,色彩偏移补偿,还有那个让人头疼的色温依赖性。

R/G、B/G 比率校正

先问个问题:为什么是 R/G 和 B/G,而不是直接用 R、G、B?

因为 G 通道最稳。在 Bayer 阵列里,G 像素数量是 R 和 B 的两倍,信噪比天然高。所以业内习惯用 G 做基准,看 R 和 B 相对 G 的偏移量。

核心公式:

  • R/G 增益 = 目标 R/G 值 ÷ 当前 R/G 值
  • B/G 增益 = 目标 B/G 值 ÷ 当前 B/G 值

目标值通常取画面中心区域的 R/G、B/G 均值。

校正流程分三步:

  1. 采集原始数据——拍一张均匀光照下的灰卡,提取每个像素位置的 R、G、B 值
  2. 计算比率矩阵——对每个像素算 R/G 和 B/G,生成两张二维增益图
  3. 应用校正——用增益图对原始图像逐像素乘回去

我在项目中遇到过一个问题:灰卡本身不够均匀。你想想看,如果灰卡本身就有 1% 的色差,那校正出来的增益图就是错的。后来我改用积分球加标准白板,才把这个问题压下去。

我的习惯:校正前先拍一张暗场,确认 sensor 本身没有固定模式噪声。否则你校正的是噪声,不是 shading。

色彩偏移补偿

R/G、B/G 比率校正能解决大部分问题,但还不够。为什么?因为镜头对不同波长的光衰减不一样。比如蓝光衰减快,红光衰减慢,这就导致边缘偏红。

色彩偏移补偿,就是针对每个像素位置,再做一个精细的色差修正。具体做法是:

  • 把图像分成 M×N 个网格(常见 9×9 或 17×17)
  • 每个网格中心点算一个 R/G、B/G 目标值
  • 网格之间用双线性插值平滑过渡

嗯,这里要注意:网格太密会引入噪声,太疏又校正不干净。我一般从 9×9 开始试,看边缘色差是否收敛。

网格密度 优点 缺点 适用场景
5×5 计算量小 边缘校正粗糙 低分辨率、低端 sensor
9×9 平衡性好 中等计算量 大多数手机、安防摄像头
17×17 校正精度高 计算量大,易引入噪声 高端单反、医疗影像

我曾经踩过的坑:网格校正后,画面出现明显的块状色差。排查了半天,发现是插值算法没处理好边界。后来在网格边界加了 2 个像素的 overlap,问题就解决了。

色温依赖性分析

这是最让人头疼的部分。同一个镜头,同一个 sensor,在 D65(6500K)下校正得好好的,换到 A 光源(2856K)就偏色了。为什么会这样?

因为 lens 的色散特性随波长变化。低色温下红光成分多,高色温下蓝光成分多,镜头对不同波段的透过率曲线不一样。说白了,Color Shading 是跟光谱绑定的。

我建议的做法是:

  • 至少采集 3 个色温点的 shading 数据:D65、TL84、A 光
  • 每个色温点生成独立的 R/G、B/G 增益图
  • 运行时根据 AWB 估算的色温,在增益图之间做线性插值

举个例子:如果当前色温是 4000K,介于 D65(6500K)和 TL84(4000K)之间,那就用 TL84 的增益图为主,稍微 blend 一点 D65 的数据。

色温插值公式(简化版):

gain = gain_TL84 * (1 - α) + gain_D65 * α
其中 α = (CCT - 4000) / (6500 - 4000)

α 范围 0~1,CCT 是当前相关色温。

我在项目中遇到过极端情况:某款镜头在 2700K 和 6500K 下的 shading 曲线完全相反。中间色温怎么插都不对。后来没办法,只能把色温点加密到 5 个,才把问题压住。

一个小技巧:如果 sensor 支持多增益模式(HDR 合成),每个增益档位的 shading 也要单独标定。因为 sensor 内部模拟增益会改变 R、G、B 的相对响应。

下面这张图总结了 Color Shading 校正的完整流程:

Color Shading 校正流程 原始 Bayer 图像 多色温灰卡采集 R/G、B/G 增益图计算 网格色彩偏移补偿 色温依赖性插值 校正后图像 注意 每个色温点独立 生成增益图 运行时插值融合

最后说一句:Color Shading 没有一劳永逸的解法。换一颗镜头、换一个 sensor、甚至换一个 IR cut filter,shading 曲线都会变。我的经验是——标定流程自动化,每次换物料重新跑一遍,别偷懒。