4. 镜头阴影(Shading)校正:LSC原理、高通LSC tuning流程、网格点与增益计算、常见阴影问题修复

镜头阴影,说白了就是拍出来的照片四角发暗、中间亮。你拿手机对着白墙拍一张,如果四角明显比中心暗,那就是 shading。这个问题在广角镜头、大光圈镜头上尤其明显。我入行那会儿,第一次调 shading 时觉得不就是加个增益嘛,结果调完发现四角是亮了,但噪点也跟着炸了……嗯,从那以后我再也不敢小看 LSC 了。

4.1 镜头阴影的成因与分类

镜头阴影分两种:亮度阴影(Luma Shading)和颜色阴影(Color Shading)。亮度阴影是四角亮度下降,颜色阴影是四角偏色——通常是偏绿或偏紫。

为什么会这样?

  • 亮度阴影:镜头的光学设计导致边缘光线入射角大,传感器接收到的光量减少。说白了就是镜头边缘的“集光能力”不如中心。
  • 颜色阴影:不同波长的光在镜头中的折射率不同,导致 R/G/B 通道的衰减曲线不一致。结果就是四角颜色偏移。

我在项目中遇到过一款手机,广角端拍蓝天,四角直接偏紫。一开始以为是 sensor 问题,后来查了镜头 spec 才发现是红外滤光片和镜头的匹配没做好。所以 shading 问题不全是 ISP 能解决的,有时候得找镜头厂一起看。

核心要点:LSC 校正的本质是对每个像素位置施加不同的增益,补偿镜头的光学衰减。但增益不能乱加,否则会放大噪声。

4.2 LSC 校正原理

LSC 校正的基本思路很简单:测出每个位置的衰减量,然后乘上对应的增益。但实际实现时,ISP 不可能为每个像素单独存一个增益值——那样存储量太大了。所以高通的做法是用网格点(Mesh Grid)来近似。

具体来说:

  1. 把图像分成 M×N 个网格,每个网格的交点就是一个网格点。
  2. 每个网格点存一个增益值(R、G、B 各一个)。
  3. 网格点之间的像素,用双线性插值算出增益。

你想想看,如果网格点太稀疏,插值出来的增益曲线就不平滑,容易出现“网格痕迹”。如果网格点太密,存储和计算开销又大。高通平台一般推荐 9×13 或 13×17 的网格,具体看 sensor 分辨率和镜头特性。

我的经验:网格点数量不是越多越好。我曾经试过 17×21 的网格,结果 tuning 数据量翻倍,但画质提升几乎看不出来。后来我一般从 9×13 开始,如果发现 shading 曲线有高频波动再加密。

4.3 高通 LSC Tuning 流程

高通的 LSC tuning 流程,我总结下来分四步。每一步都有坑,我一个个说。

4.3.1 采集原始数据

你需要拍一张均匀光源下的灰卡或白墙。注意:光源要均匀,灰卡要干净。我见过有人用办公室的白墙做参考,结果墙上有污渍,调出来的 shading 曲线全是假的。

  • 光源:D65 或 D50,色温要稳定。
  • 灰卡:18% 灰卡最好,白卡也行但容易过曝。
  • 格式:RAW 格式,关闭所有 ISP 处理(包括 AWB、CCM、Gamma)。

4.3.2 计算增益矩阵

用采集到的 RAW 图,计算每个像素位置的衰减量。公式很简单:

gain(x, y) = target_value / pixel_value(x, y)

其中 target_value 是图像中心区域的像素均值。然后对 R、G、B 三个通道分别计算。

高通平台有专门的工具(比如 Qualcomm Chromatix)来做这件事。你只需要导入 RAW 图,工具会自动生成增益矩阵。但工具生成的增益不一定最优——我习惯在工具输出后再手动检查一下边缘区域的增益值,防止工具被噪声带偏。

4.3.3 网格点拟合

把计算出的增益矩阵,拟合到 M×N 的网格点上。拟合算法一般是最小二乘法,但要注意:

  • 网格点要覆盖整个图像区域,包括边缘。
  • 拟合后的增益曲线要平滑,不能有突变。
  • 如果镜头有“鱼眼”效应,网格点分布可能需要非均匀。

避坑指南:我曾经在拟合时发现边缘网格点的增益值异常高(超过 4.0)。查了半天,发现是 RAW 图边缘区域过暗,信噪比太低,导致计算出的增益值不可靠。后来我改用多帧平均的 RAW 图,问题就解决了。

4.3.4 验证与微调

把生成的 LSC 参数烧进 ISP,然后拍实景验证。验证时要注意:

  • 拍白墙看均匀性。
  • 拍自然场景看颜色一致性。
  • 拍低照度场景看噪声是否被放大。

如果发现四角偏色,可以单独调整 R 或 B 通道的增益曲线。我一般先调 G 通道(亮度),再调 R/B 通道(颜色)。

4.4 网格点与增益计算详解

网格点的计算,很多人以为就是简单的除法。其实没那么简单。高通平台里,网格点的增益值是以 Q8 格式存储的——说白了就是定点数,1 表示 1.0 倍增益,256 表示 2.0 倍增益。

举个例子:

// 假设中心区域像素均值为 200
// 边缘某个像素值为 150
// 那么该位置的增益为 200 / 150 = 1.333
// 在 Q8 格式下,存储值为 1.333 * 256 ≈ 341

网格点之间的插值,高通用的是双线性插值。公式如下:

G(x, y) = (1 - dx) * (1 - dy) * G00 + dx * (1 - dy) * G10 + (1 - dx) * dy * G01 + dx * dy * G11

其中 G00、G10、G01、G11 是四个相邻网格点的增益值,dx、dy 是像素到左上角网格点的归一化距离。

这里有个细节:网格点的坐标是整数,但像素坐标是浮点数。所以插值时需要把像素坐标映射到网格坐标系。高通平台里,这个映射关系由 mesh_rolloff_size 和 mesh_rolloff_offset 两个参数控制。

我的习惯:在 tuning 时,我会把网格点的增益值打印出来,画成 3D 曲面图。如果曲面有“尖刺”或“凹陷”,说明某个网格点的增益值异常,需要手动修正。

4.5 常见阴影问题修复

在实际项目中,我遇到过各种各样的 shading 问题。下面列几个典型的,以及我的修复思路。

问题现象 可能原因 修复方法
四角明显偏暗 LSC 增益不足,或网格点太稀疏 增加网格点密度,重新拟合增益曲线
四角偏绿/偏紫 R/B 通道的增益曲线不匹配 单独调整 R 或 B 通道的增益,使颜色恢复中性
图像出现网格痕迹 网格点太稀疏,或插值算法精度不够 加密网格点,或改用更高精度的插值算法
低照度下噪声明显 LSC 增益过大,放大了噪声 降低增益上限,或配合去噪算法一起调
不同色温下 shading 不一致 镜头对不同色温的光衰减不同 在多个色温下分别采集数据,生成多组 LSC 参数

我印象最深的一次,是某款手机在低照度下拍夜景,四角全是噪点。查了半天,发现是 LSC 增益在边缘区域达到了 3.5 倍,把 sensor 的暗电流噪声也放大了。后来我限制了增益上限(不超过 2.5 倍),同时配合高通的多帧降噪,才把问题解决。

注意:LSC 不是万能的。如果镜头本身的 shading 超过 50%(即边缘亮度不到中心的一半),靠 LSC 硬拉会带来严重的噪声和颜色失真。这时候应该先找镜头厂优化镜头设计,而不是在 ISP 端硬扛。

4.6 LSC 调试的 SV G 流程图

下面这张图是我自己总结的 LSC tuning 流程,每次做新项目我都会照着走一遍。

LSC Tuning 流程图 LSC Tuning 流程图 采集 RAW 图 计算增益矩阵 网格点拟合 烧录验证 是否满足要求? 是 完成 否,重新调整 说明: 如果验证不通过,需要回到“计算增益矩阵”或“网格点拟合”步骤重新调整。我一般会先检查 RAW 图质量,再调整网格点密度。

4.7 小结

LSC 校正看起来简单,但要做好其实不容易。我个人的经验是:数据质量决定 tuning 质量。如果 RAW 图拍得不好,后面再怎么调也是白费。另外,LSC 不是孤立存在的,它和 AWB、CCM、去噪都有耦合关系。调 LSC 时,最好先把其他模块关掉,等 LSC 调好了再逐步打开其他模块。

嗯,这一章就到这里。记住:shading 问题不可怕,可怕的是不知道 shading 从哪里来。