色差校正基础理论:色差(CA)的成因、类型与数学模型

各位同学,今天我们来聊聊色差校正。说实话,这是ISP pipeline里一个很容易被忽视、但实际效果又非常明显的模块。我最早接触色差是在一个手机双摄项目上,当时拍出来的照片边缘总有一圈紫边,怎么调都调不掉。后来才发现,不是算法不行,是我根本没理解色差到底是怎么来的。

好,咱们今天就把这个基础打牢。你只有理解了色差的物理本质,后面写代码、调参数的时候才不会抓瞎。

色差是怎么产生的?

色差,英文叫Chromatic Aberration,简称CA。说白了,就是镜头对不同颜色的光“偏折”的程度不一样。

你想想看,可见光从红到紫,波长从760nm一直降到380nm。镜头本质上是一块玻璃,玻璃对不同波长的光,折射率是不同的。蓝光波长短,折射率大,偏折得厉害;红光波长长,折射率小,偏折得轻。结果就是,同一个物点发出的不同颜色的光,经过镜头后没法汇聚到同一个像点上。

这就是色差的物理根源。我在项目中遇到过一种情况:用大光圈镜头拍高反差物体,比如树叶缝隙里的天空,紫边特别明显。当时我以为是传感器的问题,查了半天,最后发现就是镜头色散太大,跟传感器一点关系都没有。

核心结论:色差是镜头的光学属性,不是传感器噪声。你可以在镜头设计阶段尽量抑制,但完全消除几乎不可能。ISP的色差校正,做的就是“事后补救”。

两种色差:横向与纵向

色差分两类:纵向色差和横向色差。这两者的物理机制不同,校正方法也完全不同。我建议你先把它们的区别刻在脑子里。

类型 英文 成因 表现 校正难度
纵向色差 Longitudinal CA / Axial CA 不同波长光在光轴方向上的焦点位置不同 画面中心区域出现色晕,紫边/绿边 相对容易,依赖光圈值
横向色差 Lateral CA / Transverse CA 不同波长光在像平面上的放大率不同 画面边缘区域出现红蓝偏移,越靠边越严重 较难,依赖视场角

纵向色差(Axial CA)

纵向色差,也叫轴向色差。它的特点是:不同颜色的光在光轴方向上聚焦的位置不一样。蓝光聚焦得近,红光聚焦得远。结果就是,你在焦平面上看到的不是一个清晰的点,而是一个带颜色的光斑。

这种色差在画面中心区域最明显。为什么?因为中心区域的光线基本沿着光轴传播,纵向色差的影响最大。我见过一些低端镜头,光圈全开的时候,中心紫边能占到好几个像素,缩一档光圈就好很多。嗯,这里要注意:纵向色差跟光圈大小强相关,光圈越大越明显。

横向色差(Lateral CA)

横向色差就更有意思了。它不是因为焦点位置不同,而是因为不同波长的光在像平面上的“放大率”不一样。蓝光的放大率比红光略大,所以蓝色通道的图像比红色通道“大”一点点。

这种差异在画面中心几乎看不出来,但到了边缘,一点点放大率的差异就会被放大成明显的像素偏移。你拍一张黑白格子图,边缘的格子会看到一侧偏红、另一侧偏蓝。这就是横向色差的典型表现。

我在一个广角镜头项目里吃过横向色差的亏。当时做标定,中心区域校正得很好,但边缘总是有残留的色边。后来才发现,横向色差是视场角的函数,不能用同一个参数校正全图。必须分区域、分视场做校正。

实战经验:横向色差校正通常需要依赖镜头标定数据。你需要在不同视场角下测量R/G/B通道的偏移量,然后生成一张校正映射表。高通平台上的CA校正模块,核心就是这张表。

色差的数学模型

聊完了物理成因,咱们来看看怎么用数学描述它。这部分是写代码的基础,我尽量讲得直观一些。

纵向色差的模型

纵向色差可以建模为不同波长在光轴方向上的焦点偏移。假设参考波长(通常是绿色,550nm)的像距为 \( v_0 \),那么波长 \( \lambda \) 的像距可以写成:

v(λ) = v₀ + Δv(λ)

其中 \( \Delta v(\lambda) \) 是波长相关的偏移量。在像平面上,这个偏移表现为一个模糊圆(Circle of Confusion)的半径变化。说白了,就是不同颜色的点扩散函数(PSF)的尺寸不一样。

实际工程中,我们很少直接去算PSF。更常见的做法是用一个高斯模糊核来近似色散效果。蓝通道的模糊半径比绿通道大一些,红通道比绿通道小一些。校正的时候,对蓝通道做去卷积或者锐化,对红通道做轻微模糊,让三个通道的清晰度对齐。

横向色差的模型

横向色差的模型更直接。它表现为不同颜色通道之间的几何偏移。假设绿色通道的图像坐标是 \( (x_g, y_g) \),那么红色和蓝色通道的坐标可以写成:

x_r = x_g + Δx_r(x_g, y_g)
y_r = y_g + Δy_r(x_g, y_g)

x_b = x_g + Δx_b(x_g, y_g)
y_b = y_g + Δy_b(x_g, y_g)

这里的 \( \Delta x \) 和 \( \Delta y \) 就是偏移量。它们通常是视场角的函数,离中心越远,偏移越大。而且偏移方向是径向的——从画面中心指向边缘。

我习惯用一个多项式来拟合这个偏移量:

Δx_r(r) = a₁·r + a₂·r² + a₃·r³
Δy_r(r) = a₁·r + a₂·r² + a₃·r³

其中 \( r \) 是像素到画面中心的归一化距离。系数 \( a_1, a_2, a_3 \) 就是我们需要标定的参数。高通平台的CA标定工具,输出的就是这组系数。

注意:多项式模型在视场角很大的时候(比如超广角镜头,FOV > 120°),拟合精度会下降。我曾经在一个鱼眼镜头项目里试过,三阶多项式根本不够用,最后换成了五阶多项式加分段插值才搞定。如果你的镜头视场角很大,建议提前评估模型阶数。

色差校正的整体思路

理解了模型,校正思路就很清晰了:

  1. 纵向色差校正:对R/G/B三个通道分别做不同程度的锐化或模糊,让它们的PSF对齐。高通平台通常用Luma Sharpening配合Chroma Blur来实现。
  2. 横向色差校正:根据标定得到的偏移映射表,对R/B通道做几何重采样,让它们与G通道对齐。这一步本质上是一个图像warp操作。

下面这张图展示了横向色差校正的完整流程:

横向色差校正流程图 横向色差校正流程 原始Bayer图像 R/G/B通道分离 R通道 多项式偏移校正 G通道 参考通道(不处理) B通道 多项式偏移校正 R/G/B通道合并 校正后图像 说明:G通道作为参考通道不做几何变换,R/B通道根据标定系数做径向偏移校正,最后三通道合并输出。

小结

色差校正这件事,说难不难,说简单也不简单。核心就三点:

  • 搞清楚类型:纵向还是横向?中心还是边缘?不同情况处理方式完全不同。
  • 拿到标定数据:没有准确的镜头标定,再好的算法也是白搭。我见过太多团队在算法上花了大把时间,结果发现是标定数据不准。
  • 选对模型:普通手机镜头三阶多项式就够了,超广角或鱼眼镜头需要更高阶的模型或者分段处理。