4. 镜头阴影校正(LSC):从物理根源到工程实现

镜头阴影校正,圈里人常叫 LSC(Lens Shading Correction)。这玩意儿说白了,就是解决照片四角发暗、中心过亮的问题。你拿手机对着白墙拍一张,如果四角明显比中心暗,那就是镜头阴影在作怪。

我刚入行那会儿,第一次看到 raw 图上的亮度分布,还以为是 sensor 坏了。后来才明白,这是物理规律决定的,跟 sensor 本身关系不大。

4.1 镜头阴影的物理成因:余弦四次方定律

为什么会有镜头阴影?核心原因就一个——余弦四次方定律。这个定律告诉我们,像平面上的照度与入射角余弦的四次方成正比。

公式长这样:

E(θ) = E₀ · cos⁴(θ)

其中 θ 是光线与光轴的夹角。你想想看,画面中心的光线几乎是垂直入射的,θ ≈ 0°,cos⁴(0°) = 1,照度最大。但到了画面边缘,光线斜着进来,θ 变大,cos⁴(θ) 急剧下降,照度自然就低了。

我做过一个实验:用 35mm 全画幅镜头配 24mm 焦距,边缘视场角大约 40°,cos⁴(40°) ≈ 0.34。也就是说,边缘的亮度只有中心的 34% 左右。这差距,肉眼一看就非常明显。

关键点:余弦四次方定律是物理极限,任何镜头都无法避免。但通过光学设计(如非球面镜片、微透镜阵列偏移)可以部分缓解,剩下的就得靠 ISP 算法来补。

除了余弦四次方,还有两个次要因素:

  • 渐晕(Vignetting):镜头机械结构遮挡了部分斜光线,尤其是大光圈时更明显。
  • 像素角度响应:sensor 上的微透镜对斜入射光的收集效率下降,这个在 CMOS 上尤其突出。

所以,实际镜头阴影是光学渐晕 + 像素响应衰减的叠加结果。校正时不能只考虑 cos⁴ 模型,得用实测数据来拟合。

4.2 LSC 增益矩阵的生成

校正的思路很简单:给暗的地方补光,亮的地方不动。具体做法就是生成一个增益矩阵(Gain Map),每个像素位置对应一个增益值。

增益矩阵的生成流程,我一般分三步走:

  1. 采集平场图像:用均匀光源(积分球或均匀白板)拍摄一张 raw 图。注意,光源要均匀,曝光要适中,不能过曝也不能太暗。
  2. 计算相对响应:以图像中心为参考,计算每个像素相对于中心的亮度比值。公式很简单:gain(x,y) = center_value / pixel_value(x,y)。
  3. 平滑与压缩:原始增益矩阵有噪声,需要做平滑滤波。然后根据硬件资源,压缩成网格形式(Grid Gain)或多项式系数。

实战技巧:采集平场时,我习惯拍多张(比如 16 张)然后取平均,这样可以消除随机噪声和光源的微小波动。另外,记得把镜头光圈调到常用档位,因为不同光圈下阴影特性不一样。

增益矩阵的存储格式,常见的有两种:

格式 描述 典型大小 适用场景
全分辨率矩阵 每个像素一个增益值 几 MB 到几十 MB 高精度、离线校正
网格增益 均匀采样网格,插值得到全图 几 KB 到几百 KB 实时 ISP、嵌入式系统
多项式系数 用多项式模型拟合增益曲面 几十字节到几百字节 极低资源、固定镜头

我个人最常用的是网格增益,17×13 或者 33×25 的网格,配合双线性插值,精度和资源消耗都比较平衡。

4.3 径向模型与多项式模型

既然镜头阴影是径向对称的(以图像中心为圆心),那我们可以用更简洁的模型来描述它。

径向模型

径向模型假设增益只与像素到图像中心的距离 r 有关。公式如下:

gain(r) = 1 + a₁·r² + a₂·r⁴ + a₃·r⁶

其中 r 是归一化距离(0 到 1)。这个模型的好处是参数少,只需要 3-4 个系数就能描述整个增益曲面。

但有个坑——实际镜头阴影并不完全径向对称。尤其是手机镜头,因为模组组装公差,中心点往往不在图像正中心,而且不同方向的衰减速度也不一样。我曾经遇到过一台设备,左上角和右下角的阴影差了 15%,用纯径向模型怎么调都调不好。

多项式模型

多项式模型更灵活,它用二维多项式来拟合增益曲面:

gain(x,y) = c₀₀ + c₁₀·x + c₀₁·y + c₂₀·x² + c₁₁·x·y + c₀₂·y² + ...

阶数越高,拟合精度越好,但计算量也越大。我一般用 4 阶或 5 阶多项式,再高就容易过拟合了。

注意:多项式模型在图像边缘容易出现“翘曲”现象——增益值突然变得很大或很小。这是因为多项式在边界处缺乏约束。解决办法是加正则项,或者在拟合时对边缘区域加权。

两种模型的对比:

特性 径向模型 多项式模型
参数数量 3-6 个 10-30 个(4-5 阶)
拟合精度 中等(依赖对称性) 高(可拟合非对称)
计算开销 极低 低到中等
适用场景 高质量镜头、对称性好 手机镜头、模组公差大

4.4 校正精度与性能权衡

做 LSC 最头疼的就是精度和性能的取舍。你想想看,一个 4K 图像有 800 多万像素,每个像素都要算一次增益,再乘回去,这计算量可不小。

我总结了几种常见的工程方案:

  • 查表法:预计算好增益值,存成 LUT。速度快,但占存储。适合固定场景。
  • 插值法:存网格增益,运行时双线性或双三次插值。平衡方案,我推荐这个。
  • 实时计算:用多项式或径向模型,每个像素现场算。最省存储,但计算量大。

精度方面,有几个指标要关注:

指标 定义 典型要求
校正残差 校正后图像的最大亮度偏差 < 2%
色差残留 R/G/B 通道校正后的比例偏差 < 1%
块效应 网格插值导致的块状痕迹 不可见

我曾经在一个项目中,为了省存储空间,把网格从 33×25 压缩到 17×13,结果校正后的图像出现了明显的块状条纹。后来改成 25×17 网格 + 双三次插值,块效应才消失。嗯,这里要注意,网格密度和插值算法要匹配,不能一味压缩。

我的建议:如果硬件资源允许,优先用网格增益 + 双线性插值。网格密度选 33×25 或 25×17,每个通道独立存储。这样精度够用,性能也跟得上。如果芯片算力紧张,再考虑多项式模型,但一定要做边缘约束。

4.5 知识结构总览

下面这张图,把 LSC 的核心脉络串起来了:

镜头阴影校正知识结构 镜头阴影校正(LSC)知识结构 镜头阴影校正 物理成因 增益矩阵生成 数学模型 余弦四次方定律 渐晕效应 像素角度响应 平场采集 相对响应计算 平滑与压缩 径向模型 多项式模型 校正精度 vs 性能权衡 查表法(快,占存储) 插值法(平衡方案) 实时计算(省存储,费算力)

这张图把 LSC 的三大块——物理成因、增益矩阵生成、数学模型——以及它们之间的关联都画清楚了。最下面那条“校正精度 vs 性能权衡”,是实际工程中绕不开的决策点。

好了,关于镜头阴影校正,核心内容就这些。记住,理论是基础,但真正落地时,一定要拿实拍数据说话。每个镜头模组都有自己的“脾气”,校准参数得一个一个调,没有万能公式。