1. AF基础概念

1.1 自动对焦——相机为什么要“动”起来?

自动对焦,说白了就是让镜头自己找到最清晰的位置。你按下快门,相机内部就开始“思考”:当前画面清不清晰?如果不清晰,该往哪个方向调?

我刚开始接触高通平台时,觉得AF就是个简单的“找最大值”过程。后来才发现,这里面门道很深。你想想看,如果画面本身就很模糊,或者光线很暗,系统怎么知道往哪个方向走才是对的?

自动对焦的核心,其实就三件事:

  • 测量——当前画面的清晰度是多少?
  • 判断——该往近处调还是远处调?
  • 驱动——让马达走到目标位置。

这三步循环执行,直到找到最清晰的那个点。嗯,听起来简单,但实际做起来,坑不少。

1.2 VCM马达——让镜头“动起来”的功臣

VCM(Voice Coil Motor,音圈马达)是目前手机摄像头最常用的驱动方案。它的原理其实和扬声器很像——通电线圈在磁场中受力,带动镜头上下移动。

我个人习惯把VCM马达的工作方式总结成一张表:

参数 说明 典型值
驱动电流 控制镜头位移的输入信号 0 ~ 100 mA
行程范围 镜头从最近到最远的物理移动距离 0.2 ~ 0.5 mm
分辨率 最小可控制的位移步长 1 ~ 10 μm
响应时间 从指令发出到位置稳定的时间 5 ~ 20 ms
谐振频率 马达自身的机械共振点 50 ~ 200 Hz

我在项目中遇到过一个问题:某款模组的VCM马达在特定频率下会剧烈抖动,导致AF反复震荡。后来发现是驱动波形没做平滑处理,触发了谐振。从那以后,我每次调AF都会先测一下马达的谐振点。

注意:VCM马达的行程不是线性的。靠近两端时,同样的电流变化,位移量会变小。这就是所谓的“饱和区”。AF搜索策略必须避开这个区域,否则精度会大打折扣。

1.3 AF评价函数——怎么判断“清晰”?

评价函数,就是给画面清晰度打分的工具。高通平台主要支持两种:对比度法和相位差法。

1.3.1 对比度法(Contrast AF)

对比度法的逻辑很直观:清晰的图像,边缘锐利,相邻像素的亮度差异大;模糊的图像,边缘平滑,差异小。

常见的对比度评价函数有:

  • Tenengrad函数——基于Sobel算子计算梯度幅值,然后求和。我比较喜欢用这个,因为它对边缘敏感,而且计算量适中。
  • Laplacian函数——用二阶微分检测边缘。优点是响应快,缺点是对噪声敏感。
  • 方差函数——计算像素灰度值的方差。简单粗暴,但在纹理丰富的场景下效果不错。

举个例子,Tenengrad函数的计算过程大致是这样:

// 伪代码:Tenengrad 对比度计算
float computeTenengrad(uint8_t* image, int width, int height) {
    float sum = 0.0f;
    for (int y = 1; y < height - 1; y++) {
        for (int x = 1; x < width - 1; x++) {
            // Sobel 水平梯度
            int gx = -image[(y-1)*width + (x-1)] + image[(y-1)*width + (x+1)]
                     -2*image[y*width + (x-1)] + 2*image[y*width + (x+1)]
                     -image[(y+1)*width + (x-1)] + image[(y+1)*width + (x+1)];
            // Sobel 垂直梯度
            int gy = -image[(y-1)*width + (x-1)] -2*image[(y-1)*width + x] - image[(y-1)*width + (x+1)]
                     +image[(y+1)*width + (x-1)] +2*image[(y+1)*width + x] + image[(y+1)*width + (x+1)];
            sum += sqrtf(gx*gx + gy*gy);
        }
    }
    return sum;
}

对比度法的优点是实现简单,不需要额外硬件。但缺点也很明显:

  • 需要来回搜索,速度慢
  • 在低对比度场景(如白墙)下容易失效
  • 容易陷入局部最大值

1.3.2 相位差法(Phase Detection AF)

相位差法就高级一些了。它通过传感器上的专用像素(PD像素)来检测光线入射角度,直接判断当前是“前焦”还是“后焦”。

高通平台上的PDAF实现,我总结下来有几个关键点:

  • PD像素分布——通常以2x2或4x4的pattern嵌入在正常像素中
  • 相位差计算——左右两组PD像素的亮度曲线错位量,就是相位差
  • 换算关系——相位差 = 0 表示合焦;正值表示前焦;负值表示后焦
核心区别:对比度法只能告诉你“当前清不清晰”,但不知道“该往哪走”。相位差法直接告诉你“偏了多少、往哪偏”。所以PDAF的搜索速度通常比对比度法快3~5倍。

不过,相位差法也有自己的问题。我曾经调试过一款模组,PDAF在暗光下误差很大,相位差和实际离焦量不成线性关系。后来发现是PD像素的灵敏度匹配没做好,左右通道的增益不一致。

1.4 两种方法的融合——Hybrid AF

高通平台实际用的是混合对焦:先用PDAF快速跳到大致位置,再用对比度法做精细微调。这样既保证了速度,又保证了精度。

下面这张图展示了Hybrid AF的基本流程:

Hybrid AF 工作流程 Hybrid AF 工作流程 开始对焦 PDAF 粗调 计算相位差 → 快速跳到合焦附近 是否合焦? (相位差 ≈ 0) 是 对焦完成 否 对比度法 精调 搜索对比度峰值 说明 PDAF 负责快速粗定位 对比度法负责精确微调 两者互补,缺一不可

1.5 高通平台上的AF架构

在高通平台上,AF相关的模块主要分布在三个层级:

层级 模块 职责
应用层 Camera HAL / AF Algorithm 策略决策、搜索算法、场景判断
框架层 CamX / Chi UAF(用户AF)和IAF(内部AF)调度
驱动层 Kernel VCM Driver / ISP 马达控制、PD数据采集、统计信息上报

我个人习惯把AF算法看作一个“黑盒”,输入是ISP上报的统计信息(对比度值、相位差值),输出是马达的目标位置。至于中间怎么搜、怎么跳,那就是后面章节要讲的内容了。

小经验:调试AF时,我建议先把ISP上报的原始数据打出来看看。很多问题其实出在数据源上——比如对比度值被截断了,或者相位差符号反了。先确认数据是对的,再调算法,能省不少时间。

1.6 本章小结

这一章我们聊了自动对焦的基本概念:

  • AF的本质是“测量→判断→驱动”的闭环
  • VCM马达通过电流控制镜头位移,但要注意饱和区和谐振
  • 对比度法靠图像梯度打分,相位差法靠PD像素测方向
  • 高通平台用Hybrid AF,先粗后精