相位对焦原理:微透镜阵列与像素分光结构,相位差计算基础

相位对焦,说白了就是让相机自己当“测距仪”。它不靠猜,而是靠算。我当年第一次拆开一颗专业级 CMOS 时,看到像素表面那层密密麻麻的微透镜阵列,才真正理解——原来对焦这件事,从硬件层面就已经被“设计”好了。

2.1 微透镜阵列:光线的“分岔路口”

传统像素上方只有一个微透镜,光线汇聚后直接进入感光区。但相位对焦像素不同——每个微透镜下方,被一堵“墙”隔成了左右两个光电二极管。

核心结构:一个微透镜 + 两个光电二极管(左/右) = 一个相位检测像素对。

你想想看,光线穿过微透镜后,会被这堵墙“劈开”。如果镜头合焦,左右两个二极管接收到的光强完全一致。如果镜头前移或后移,光线就会偏向某一侧。这个“偏向”就是相位差。

我在项目中遇到过一种情况:某款传感器的微透镜阵列与片上透镜距离偏差了 0.3μm,结果整批模组的对焦精度都飘了。后来我们重新校准了微透镜的曲率半径,才把相位一致性拉回来。

2.2 像素分光结构:左眼与右眼

相位检测像素的分光结构,本质上是在模拟“双眼视差”。

结构类型 实现方式 典型应用
半遮挡式 像素上方金属遮光层只开左半/右半 早期 DSLR 相位模块
双光电二极管式 同一微透镜下两个独立 PD 索尼 2PD、佳能双核
片上透镜偏移式 微透镜中心相对 PD 偏移 部分安森美传感器

我个人习惯把双光电二极管式叫做“真·相位对焦”。因为它不牺牲像素数量,每个像素都能同时成像和对焦。嗯,代价就是工艺难度翻倍。

避坑指南:我曾经调试过一款 48MP 传感器,它的相位像素只分布在 30% 的阵列区域。结果在低照度下,非相位区域和相位区域的响应曲线不一致,导致对焦时出现“跳焦”。后来我强制在 ISP 里做了增益补偿,才稳住。

2.3 相位差计算基础:从光强到偏移量

相位差的计算,本质上是一个“相关性搜索”问题。我们来看最基础的实现流程:

  1. 提取左右信号:从相位像素对中读出左眼序列 L(x) 和右眼序列 R(x)。
  2. 计算相关曲线:将 R(x) 逐像素平移,计算与 L(x) 的差值值之和(SAD)。
  3. 找到谷底:SAD 最小的平移量,就是相位差。
// 简化的 SAD 相位差计算(C 风格伪代码)
float computePhaseShift(int16_t* L, int16_t* R, int len) {
    float minSAD = INFINITY;
    int bestShift = 0;
    for (int shift = -len/2; shift < len/2; shift++) {
        float sad = 0.0f;
        for (int i = 0; i < len; i++) {
            int idxR = i + shift;
            if (idxR < 0 || idxR >= len) continue;
            sad += abs(L[i] - R[idxR]);
        }
        if (sad < minSAD) {
            minSAD = sad;
            bestShift = shift;
        }
    }
    return bestShift; // 单位:像素
}

这段代码看着简单,但实际工程里坑很多。比如边界处理、噪声抑制、亚像素插值。我见过有人直接用整数平移,结果对焦精度永远卡在 1 个像素以内——说白了就是没做亚像素拟合。

注意:相位差计算对信号质量极其敏感。如果左右通道的增益不一致,或者存在固定模式噪声(FPN),相关曲线的谷底会变“平”,导致对焦犹豫。我曾经在实验室用均匀光源照射传感器,发现左右通道的暗电流差了 12%,后来通过双通道校准表才解决。

2.4 相位差与镜头移动量的关系

相位差算出来了,怎么转成镜头步进?这里有个关键参数:基线长度。

基线长度 = 左右相位像素的光学中心距离。它决定了相位差对离焦量的灵敏度。

基线长度 灵敏度 适用场景
短基线(< 10μm) 低 大光圈、低照度
中基线(10~30μm) 中 日常拍摄
长基线(> 30μm) 高 长焦、高精度对焦

公式很简单:镜头移动量 = 相位差 × 像素间距 / 基线长度 × 镜头灵敏度系数。但实际调试时,这个系数往往不是理论值。我习惯在产线做一次“全行程标定”——从最近到最远,记录每个位置的相位差,然后拟合出一条映射曲线。

我的经验:相位差映射曲线通常不是线性的。尤其是微距端,由于光学像差的影响,相位差和实际离焦量会偏离线性关系。我建议至少用 5 阶多项式拟合,或者分段线性插值。

2.5 相位对焦的典型流程

下面这张 SVG 图展示了从像素读出到镜头驱动的完整链路:

相位对焦信号处理流程 相位像素阵列 微透镜+双PD 读出电路 L/R通道分离 相位差计算 SAD/SSD相关 映射与滤波 基线+灵敏度 镜头驱动 VCM/步进电机 合焦判断 相位差<阈值 反馈回路:未合焦时,相位差重新计算并驱动镜头,直到相位差小于合焦阈值

这个流程里,我最想强调的就是那条虚线反馈回路。很多工程师只关注前向链路,忽略了“迭代收敛”的重要性。我调试过一款模组,相位差计算本身很准,但每次驱动镜头后不做二次校验,结果在微距端反复震荡——说白了就是缺了闭环。

2.6 相位对焦的局限与补偿

相位对焦不是万能的。我列几个常见问题:

  • 光线不足:左右信号信噪比下降,相关曲线谷底变浅。我建议在 EV < 2 时切换到对比度对焦辅助。
  • 重复纹理:比如百叶窗、网格,相关曲线会出现多个谷底。我曾经用“峰值置信度”指标来过滤这种歧义。
  • 镜头像差:尤其是大光圈边缘,光线斜入射导致左右通道响应不一致。嗯,这个只能靠标定表补偿。

小技巧:在产线标定时,不要只用均匀光源。我习惯用“星图”或“斜边”靶标,这样能同时标定相位差映射和 MTF 响应。一次标定,两套数据。

相位对焦的核心,就是利用微透镜阵列和像素分光结构,把“对焦”这个模糊问题变成了一个精确的“偏移量测量”问题。你只要把左右信号算准、把映射关系标定好,剩下的就是让镜头乖乖听话。