4. 相位对焦(PDAF):片上相位检测像素、左右相位差计算、散焦量映射

相位对焦,圈里人常叫它PDAF。这玩意儿在单反上已经用了很多年,后来被搬到手机摄像头里。说白了,它比反差对焦快得多,不来回“拉风箱”,直接告诉你镜头该往哪转、转多少。

我最早接触PDAF是在做一款旗舰机摄像头调试的时候。当时客户要求对焦速度必须控制在200ms以内,反差对焦死活做不到,最后全靠PDAF救场。嗯,咱们今天就把它拆开看看。

4.1 片上相位检测像素

传统CMOS传感器每个像素就是一个光电二极管,只管收集光子。但PDAF传感器不一样,它在像素阵列里“藏”了一些特殊的像素对——相位检测像素。

每个相位检测像素其实只“看”到一半的光线。怎么做到的?

  • 左半遮挡像素:微透镜下面只露出光电二极管的左半边,右半边被金属遮光层挡住。
  • 右半遮挡像素:反过来,只露出右半边,左半边被挡住。

这两个像素挨在一起,组成一个“相位检测对”。左像素只接收从镜头左侧进入的光线,右像素只接收从右侧进入的光线。你想想看,这不就相当于在传感器上造了两个“小眼睛”吗?

关键点:相位检测像素牺牲了部分感光面积,所以它们比普通像素暗一些。后期ISP需要做增益补偿,否则图像上会出现“网格状”的亮度不均。

我在项目中遇到过一个问题:某款传感器的相位像素排布太密,导致预览画面有明显的“棋盘格”噪声。后来调整了补偿算法,才把这个问题压下去。

4.2 左右相位差计算

有了左右像素的信号,接下来就是算差值。这个计算过程其实不复杂,但细节挺多。

基本流程是这样的:

  1. 提取左右信号:从传感器原始数据中,把左半遮挡像素和右半遮挡像素的值分别提取出来,形成两个一维信号序列。
  2. 计算相关曲线:把左信号作为参考,右信号在水平方向上逐像素平移,每平移一次计算一次匹配度(通常用SAD或SSD)。
  3. 找到最佳匹配:相关曲线的最低点(SAD最小)对应的平移量,就是左右信号的相位差。

这里有个细节——亚像素精度。整像素级别的相位差精度不够,镜头对焦会来回抖动。我习惯用抛物线插值法,在最佳匹配点附近取三个点,拟合一条抛物线,顶点位置就是亚像素级别的相位差。

// 亚像素插值示例(C语言风格伪代码)
float phase_delta_subpixel(int16_t *corr, int best_idx) {
    int16_t c0 = corr[best_idx - 1];
    int16_t c1 = corr[best_idx];
    int16_t c2 = corr[best_idx + 1];
    float denom = 2.0f * (c0 - 2.0f * c1 + c2);
    if (fabs(denom) < 1e-6f) return (float)best_idx;
    float subpixel_offset = (c0 - c2) / denom;
    return (float)best_idx + subpixel_offset;
}

避坑指南:我曾经在低照度场景下发现相位差计算抖动很大。原因是左右信号的信噪比太低。后来加了时域滤波——把连续几帧的相位差做加权平均,效果立竿见影。

4.3 散焦量映射

相位差算出来了,但它是一个像素偏移量,单位是“像素”。镜头马达需要知道的是“镜头该转多少步”,单位是“μm”或“步数”。这就需要一个映射关系。

映射公式其实是个线性模型:

defocus_amount = phase_delta * conversion_gain + offset

其中:

  • phase_delta:上一步算出的相位差(亚像素精度)
  • conversion_gain:转换增益,单位是“μm/像素”
  • offset:零位偏移,用于校准

这个转换增益怎么来的?标定出来的。我一般在产线上拍一组不同物距的图卡,记录每个物距下的相位差,然后拟合出线性关系。

物距 (cm) 相位差 (像素) 镜头位置 (μm) 转换增益 (μm/像素)
10 +12.3 150 12.2
20 +6.1 75 12.3
50 +2.0 25 12.5
100 0.0 0 —

你看,转换增益基本稳定在12.2~12.5之间。实际项目中我会取平均值,再根据温度做一次补偿——温度变化会影响微透镜的折射率,导致增益漂移。

注意:散焦量映射不是一成不变的。镜头模组有公差,每个模组的转换增益都不一样。量产时必须逐台标定,否则会出现“这台对焦快,那台对焦慢”的尴尬情况。

最后一步,把散焦量发给马达驱动。如果是VCM马达,直接换算成电流值;如果是步进马达,换算成步数。镜头就“嗖”一下推到目标位置,对焦完成。

整个PDAF流程,从像素读出到马达驱动,必须在单帧时间内完成——通常是16ms到33ms。我做过一个优化:把相位差计算和散焦量映射放在ISP的垂直消隐区里跑,不额外占用帧时间。嗯,效果很好。

PDAF 核心流程 片上相位检测像素 左/右半遮挡像素对 左右信号提取 分离L/R通道数据 相位差计算 SAD/SSD + 亚像素插值 散焦量映射 增益 × 相位差 + 偏移 马达驱动 VCM电流 / 步进步数 关键指标 • 相位差精度:0.1像素 • 转换增益:12~13 μm/像素 • 处理时间:< 16ms

这张图把PDAF的五个核心环节串起来了。从传感器上的相位检测像素开始,到最终马达推动镜头到位,每一步都有它的物理意义和算法细节。你想想看,整个对焦过程在几十毫秒内完成,背后是光学、半导体、信号处理、控制理论的协同工作。

我个人觉得,PDAF最妙的地方在于它把“对焦”这个看似模糊的问题,转化成了一个精确的数学计算。只要相位差算得准,散焦量映射标定得稳,对焦就是一次到位,不需要反复试探。