ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

AF自动对焦算法深入解析:从评价函数到马达控制

AF自动对焦算法深入解析:从评价函数到马达控制 拍照这件事大家每天都在做但真正让按一下快门就出清晰照片这个体验成立的背后其实是一整套 AF 自动聚焦算法的功劳。无论是手机摄像头、运动相机、安防监控还是车载摄像头只要是涉及成像的系统AF 都是最基础也最容易被忽视的模块。它解决的问题很直接镜头怎么动、动多少才能让目标物体在传感器上清晰成像。这件事听起来简单但真正落地到工程项目里涉及清晰度评价、搜索策略、马达控制、模组标定、环境补偿等多个环节任何一个环节没做到位用户拿到的就是对焦慢、犹豫、拉风箱、偶尔还糊的体验。这篇文章是我做摄像头模组调试和 ISP 算法集成这些年积累下来的经验总结围绕 AF 自动聚焦算法的原理、工程实现和常见坑点展开。适合刚要接触摄像头驱动的嵌入式工程师、做 ISP/算法集成的同学也适合在产线端负责模组标定和不良分析的朋友参考。我会按照从整体架构到细节实现再到实际调试案例的顺序来讲尽量把我踩过的坑和验证过有效的做法都写清楚。1. AF 系统整体架构与核心流程1.1 自动对焦的本质把模糊变成可计算的指标自动对焦的本质是要回答两个问题当前画面清不清楚如果不清楚镜头该往哪个方向挪、挪多远人眼判断清楚很容易但机器没有感觉。机器只能靠传感器拿到的图像数据来算。于是整个 AF 算法就被拆成了两条线一条是清晰度评价也就是把清晰程度量化成一个可比较的数值另一条是搜索控制也就是根据这些数值的变化趋势决定马达怎么走。在工程实现上AF 通常由三部分组成镜头模组含马达和驱动 IC、图像传感器、以及运行在 ISP 或主控里的 AF 算法。算法每算一次会对当前图像帧做一个清晰度评分然后告诉马达下一步往哪走。整个过程循环进行直到评分满足条件或者到达边界。对用户来说这个过程越短越好最好察觉不到对算法来说这个过程的收敛性和稳定性比速度更重要——宁可慢一点也不能来回震荡。我之前遇到过一个典型的案例在室内灯光下对焦一切正常但把摄像头对着窗外拍天空时AF 就开始反复拉风箱。原因就是天空画面纹理太少清晰度评价函数算出来的数值在很大一段镜头行程内几乎不变算法失去了参考信息。这就是 AF 系统设计的核心挑战之一你不仅要懂算法还要懂场景、懂镜头、懂马达才能把问题定位准。1.2 主流对焦方案选型CDAF、PDAF 与混合对焦先说说市面上常见的几种 AF 方案各有各的原理和适用场景。对比度对焦CDAFContrast Detection Auto Focus是最经典的方案原理最简单镜头从近端往远端移动在移动过程中持续采集图像计算每个位置的清晰度评分评分最高的位置就是合焦点。它的优点是结构简单、成本低只需要图像数据不需要额外的硬件缺点是速度相对慢因为需要先走过、再回来或者边移动边判断本质上是一个搜索过程。相位对焦PDAFPhase Detection Auto Focus是被手机厂商用得很成熟的方案。原理是在传感器上做一些特殊的像素掩蔽像素让这些像素只接收来自某一方向的光线从而形成一个微型相位差信号。当画面清晰时左右相位差为零失焦时相位差的大小可以换算成失焦方向和程度。它的优势是速度快基本一拍就知道该往哪走、走多远不需要反复搜索缺点是需要在传感器里做特殊像素硬件成本高而且低照度环境下相位信号会变差。激光对焦用红外激光测距直接得到物体距离然后通过镜头行程表查表得到马达位置。优点是暗光下表现好缺点是只能测一个点对焦范围有限且对透明物体和强反光物体效果不好。实际产品里中高端方案基本都是混合对焦先用 PDAF 快速跳到大致位置再用 CDAF 精调收敛。这样既有速度又有精度。设计混合对焦算法时要特别注意两个模块之间的衔接——什么时候从 PDAF 切到 CDAF、切换时镜头位置怎么平滑过渡处理不好会在画面里看到明显的一跳。1.3 一条完整的 AF 搜索链路不管用哪种方案一次典型的 AF 流程大概是这样的第一步触发对焦。可能是用户按下了快门也可能是系统检测到画面变化主动触发。第二步如果是 PDAF先做一次相位计算得到一个初步的目标位置驱动马达快速到位。第三步进入 CDAF 的精细搜索阶段在当前位附近做小范围步进扫描记录每个位置的清晰度评分。第四步找到评分变化的极值点驱动马达回到峰值位置。第五步输出对焦完成的状态ISP 侧可以做降噪、锐化等后处理。这套流程看起来简单但每一步都有很多细节可以展开。比如 PDAF 算出来的位置和真实合焦位置之间可能有偏差因为相位差转换距离依赖镜头的出厂标定参数比如 CDAF 搜索时步长选太大可能跳过峰值点导致精度不够选太小又会拖慢速度。这些我都放在后面几个小节里详细说。2. 核心算法拆解清晰度评价函数如何工作2.1 为什么不能直接看图片清不清楚先说一个常见的误区很多刚接触 AF 的同学会问为什么不直接在图像上跑一个目标检测或者边缘检测来判断画面清不清楚理论上可行但工程上基本不会这么做。原因主要有三个一是目标检测算法太重在嵌入式平台一帧跑几十毫秒甚至上百毫秒AF 完全跟不上二是 AF 需要对整个画面的清晰度做整体评价而不是针对某个目标否则场景切换时容易误判三是对焦评价需要连续、单调、单峰的特性深度学习特征不保证这些性质容易在多处出现局部极值导致镜头停在不该停的位置。所以在真实产品里清晰度评价函数绝大多数都是基于图像梯度的统计特征。核心思想是图像越清晰相邻像素之间的灰度变化越剧烈梯度值越大。2.2 常用评价函数梯度类、频率类与统计类具体来说常用函数可以分三类。梯度类函数是最常用的。Brenner 函数计算的是相隔两个像素的灰度差平方用差分代替微分对高频信息敏感而且计算量很小。Laplacian 函数用二阶微分算子对边缘的响应更强烈但也更容易受噪声影响。SMD灰度方差函数算的是相邻像素灰度差的绝对值之和实现最简单在纹理不丰富的场景下也还能用。Tenengrad 函数用 Sobel 算子提取水平和垂直梯度鲁棒性更好但计算量会大不少。频率类函数是另一条路线对图像做傅里叶变换或者小波变换清晰图像的高频分量更多所以高频能量可以作为清晰度指标。这类函数理论最漂亮但实际嵌入式平台很少直接用 FFT因为计算量太大一般只在评测阶段用来做标准答案。统计类函数基于灰度直方图或者自相关特性。比如直方图对比度评价清晰图像的灰度分布通常更分散对比度更高。这类函数抗噪性好但对轻微失焦不敏感所以一般不用来做精调适合做大范围初判。我在实际项目里用得最多的是 Brenner 加 Sobel 的组合粗搜阶段用 Brenner 快速扫描精调阶段用 Sobel 版 Tenengrad 做细定位。原因是 Brenner 计算快适合扫描Tenengrad 抗噪好适合精确峰值定位。2.3 选评价函数时的工程权衡选评价函数不能只看理论性能还得考虑平台算力、噪声水平、场景特点这些因素。算力是硬约束。假设画面是 1080P也就是约 200 万像素Brenner 算子对全图每个像素做一次减法和一次乘法换算成指令数大概是每秒需要处理几十到上百 MIPS。如果还要同时跑其他 ISP 算法留给 AF 的算力预算可能只有几 MIPS这时候就得考虑缩小评价窗口、降采样或者用更简单的算子。噪声影响是另一个大坑。图像噪声在梯度计算里会被放大造成评价函数出现大量毛刺AF 容易把噪声当成清晰度峰值。常规做法是先做一步轻量降噪比如 3x3 均值或者高斯模糊再做梯度计算或者选用对孤立噪点不敏感的算子比如 Sobel 比 Laplacian 对噪声更稳一些。还有一个容易被忽视的点评价窗口的选择。全画面参与计算容易受到前景背景同时存在的影响比如画面前景有个人、背景是天空如果窗口覆盖到天空部分对焦评分就容易被天空的低纹理区域拉低。比较好的做法是支持配置多个对焦窗口默认在画面中央区域同时允许上层根据需要调整窗口位置和大小。人脸对焦就是把检测到的人脸框设为对焦窗口的。3. 对焦搜索策略与马达控制细节3.1 爬山算法与全局扫描怎么找峰值有了清晰度评价函数接下来就是怎么找峰值的问题。最常见的思路是爬山算法。爬山算法的逻辑很简单先朝一个方向移动镜头如果清晰度评分在上升说明方向正确继续走如果开始下降说明越过了峰值回调到评分最高的位置。听起来很直观但工程上有几个问题要处理。第一个问题是步长。步长太大容易跳过真正的峰值停在峰旁边导致对焦精度不足步长太小搜索次数多速度慢。实际做法通常是用变步长大步长粗搜定位区间再小步长细搜收敛。第二个问题是起点。如果镜头当前停在无穷远而物体在微距爬山算法需要走很长的路才能找到峰值速度就慢了。所以很多方案会在触发对焦后先判断一下场景或者结合 PDAF/激光测距的结果给一个合理的起始位置。第三个问题是局部极值。清晰度评价函数并不总是单峰的在特定纹理下可能出现次峰爬山算法容易困在次峰。针对这个问题可以在搜索过程中加一个记录全局最大值的逻辑哪怕当前评分在下降也保留历史最大值的位置这样就算被局部极值扰动最终也能回到最优位置。3.2 粗搜加细搜的两阶段策略实际产品里我建议把搜索策略固定为两阶段粗搜加细搜。粗搜阶段的目标是快速缩小范围。以步长较大的方式从当前位或者起始位出发走完整个镜头行程记录每个采样点的评分找出评分最高的区间。假设镜头总行程是 300 微米粗搜步长 30 微米那只需要采样 10 个点假设每帧评测耗时 16 毫秒总耗时大约 160 毫秒可以接受。细搜阶段在粗搜找到的最佳区间内进行步长减小到 5 微米左右采样 6 到 8 个点找精确峰值这个阶段再花 100 毫秒左右。整体对焦时间在 300 毫秒以内已经接近人眼的感知阈值。这里有个细节粗搜阶段采样点之间的距离要和镜头的景深匹配。景深越浅采样的步长就要越密否则直接跳过整个合焦区间。景深和镜头光圈大小直接相关光圈越大F 值越小景深越浅对焦精度要求越高粗搜步长就要相应减小。定焦小光圈相机对焦压力小大光圈人像模式对焦压力大就是这个原因。3.3 马达控制VCM 开环、闭环与 DAC 曲线算法算出了目标位置最后执行是靠马达。手机上最常见的对焦马达是 VCM也就是音圈马达原理和扬声器类似给线圈通电在磁场中产生力推动镜头移动。VCM 最原始的工作方式是开环控制给一个 DAC 值对应一个电流电流产生一个力镜头移动到某个位置。问题是这个行程和 DAC 值之间不是完美的线性关系尤其是靠近两端时会有非线性另外镜头模组有机械摩擦和弹簧回位会造成迟滞——同一个 DAC 值从近端走过来和从远端走过来最终停留的位置可能不一样。解决迟滞问题有两种思路。一种是闭环控制在镜头旁边加霍尔传感器实时读取镜头位置将目标位置和当前位置做 PID 运算用反馈来消除迟滞和漂移。这也是目前主流手机摄像头的做法。另一种是不加传感器但通过软件做迟滞补偿表。校准过程中记录近→远和远→近两组 DAC-行程映射表实际控制时根据镜头运动方向查不同方向的表再把目标 DAC 值做一个偏移修正。这个做法省钱但补偿精度有限而且随温度变化会漂移。我自己调试时发现VCM 的驱动值不能只给一个目标 DAC 就完事还需要配合驱动波形。短时间内快速加一个高的驱动电压可以让镜头快速启动接近目标位置时提前减速避免过冲。这个快启动、慢到位的波形控制对提升对焦速度帮助很大也是很多项目里容易忽略的细节。3.4 迟滞补偿和温度补偿最容易翻车的环节迟滞补偿这个话题值得单独拿出来讲。VCM 的迟滞量一般在 5 到 20 微米左右而大光圈镜头的景深可能只有 20 到 30 微米这意味着如果不做补偿迟滞误差很可能直接让对焦结果落在景深边缘甚至景深之外。做迟滞补偿的第一步是拿到模组的迟滞特性曲线。这个一般在产线标定时测让镜头从 Macro微距端往 Infinity无穷远端走每 N 个 DAC 记录一次实际位置再从 Infinity 往 Macro 走同样记录。两组数据之间的差值就是迟滞量。因为迟滞量和运动方向相关所以在算法里要维护一个上次运动方向的状态据此查对应的补偿表。这一步逻辑很简单但容易被忽略尤其在从单摄方案切到双摄/多摄方案时不同模组厂家的迟滞特性差异很大补偿表必须重新标定。温度补偿是另一个坑。VCM 的磁钢在高温下磁通密度会下降导致同样的 DAC 值对应的位移变小弹簧的弹性系数也会随温度变化。结果就是常温下标定的行程表在低温或高温下会偏移。我在一个车载项目里遇到过夏天装车没问题冬天一开机对焦总差一点排查到最后是温度引起的行程漂移。解决方法是加温度传感器做行程表的温度插值补偿或者干脆用闭环马达硬件上自动消掉这部分漂移。4. 实操从模组标定到 AF 参数调稳4.1 镜头模组标定拿到底层数据调 AF 算法之前第一步永远是标定。没有准确的镜头行程数据算法写得再好也是空中楼阁。标定的核心是得到 DAC 值和实际对焦距离的对应关系。最常用的方法是拍图法把测试图卡放在已知距离比如 10cm、30cm、1m、无穷远对每个距离跑一次全行程搜索找到清晰度评分最高时对应的 DAC 值。把这些点连起来就是镜头的行程-距离曲线。实际操作中要注意几个细节。测试环境的光照要均匀稳定最好用标准光源避免频闪图卡要选用高频纹理丰富的比如西门子星图或者是 ISO 12233 分辨率测试卡图卡平面要和传感器平面平行否则边缘和中心的合焦位置不一致测出来的峰会被拉宽。还有一点标定过程中镜头要从一个固定方向到达目标位置比如每次都从近端往远端推这样迟滞的影响是一致的标定的数据才可重复。标定结果通常存成一个表放在模组的 OTP 或者系统配置里AF 算法启动时加载。除了行程表还要标定马达的启动 DAC 和饱和 DAC。这两个值决定了镜头的实际可移动范围如果设置不对会出现近焦清楚远焦模糊或者反过来。4.2 在平台上配置 AF 参数拿到模组标定数据后下一步就是把这些数据填到算法配置里。这部分工作烦琐但很重要每个参数都有它的含义调不好就出问题。常见的配置项包括镜头行程范围macro DAC 和 infinity DAC、搜索步长粗搜和细搜、对焦窗口位置和大小、评价函数类型、峰值确认阈值、超时时间、温度补偿开关等。我建议每次改动只动一个参数并且做好记录否则出了问题根本不知道是哪次改动引起的。我自己习惯用一个统一的配置文件管理所有 AF 参数并且每个参数后面都写注释注明改动日期和原因这个习惯在项目后期排障时帮了大忙。配置完成后跑一遍基本的对焦性能测试对焦时间、对焦精度、重复性。对焦精度用拍出来的图看边缘锐度重复性就是同一场景反复对焦 20 次看每次的镜头位置和清晰度评分是否稳定。如果重复性差优先检查是不是步长太小导致评分曲线太平或者马达有异常振动。4.3 三类常见的对焦失败案例我把调试中遇到的对焦失败归纳成三类方便大家对照排查。第一类是拉风箱也就是镜头反复移动停不下来。常见原因是评价窗口里没有足够纹理评分函数一直给不出有效峰值。对策扩大窗口、切换到对比度更明显的区域或者引入 PDAF/激光测距先锁定大概位置。第二类是对错目标。画面里同时有近处物体和远处背景时算法可能停在背景上。对策用多个窗口加权重或者依赖上层的人脸/物体检测结果将检测框对应的窗口权重调高。第三类是暗光下对焦慢甚至失败。低照度下图像噪声大梯度计算不稳定评分函数抖动厉害。对策先做降噪或者延长单帧曝光时间和帧率让评价图像更干净再不行加辅助照明或者切换到激光对焦。我印象特别深的一次是在做运动相机时用户反馈夜跑时牌照总糊。排查发现夜跑场景里有大量来回晃动的树枝和灯杆画面内容变化太快AF 每帧算出的评分都在变算法完全跟不上。最后方案是把 AF 触发策略改成持续缓慢微调而不是检测到变化就大幅搜索并在评分时做了时间域平滑这才把问题解决。这说明 AF 调优不光是算法内部的事和触发策略、系统调度也密切相关。4.4 性能测试与验收指标AF 调得好不好不能靠感觉要有一套可量化的验收指标。对焦时间是最直接的体验指标从触发对焦到输出合焦的耗时一般手机要求在 300 毫秒以内高端旗舰要求 150 毫秒以内。对焦精度用失焦量来衡量通常要求合焦后画面边缘的 MTF50 值不低于该镜头最优值的 80%。重复性要求同一场景连续对焦 20 次镜头最终位置的极差不超过细搜步长的 2 倍。低照度性能要单独测在 1 lux 到 50 lux 的不同亮度下分别测试对焦时间和成功率成功率一般要求不低于 95%。温度性能也要测-20 度到 60 度范围内对焦精度的变化不能超出景深范围。这些指标在实验室里用标准图卡测也要在真实场景里做主观评测。我的习惯是找几个不同纹理丰富度的场景白墙、书架、人像、夜景、绿植每个场景拍几百张样张再人工挑出糊片率。主观评测往往能发现实验室里发现不了的场景相关问题。5. 常见问题速查AF 调试避坑表调试过程里遇到的很多问题其实都可以靠经验和规范来规避。我把常见的现象、可能原因和解决思路整理成了一个速查表方便大家在实际项目中快速定位。现象可能原因排查方向与解决建议对焦反复拉风箱、不收敛评价窗口纹理不足评分无峰值扩大窗口、切换对焦区域或用 PDAF 先定位对焦对到背景而非主体单窗口覆盖前后景权重冲突配置多窗口结合人脸/物体检测框调权重暗光下对焦慢或失败图像噪声大梯度评分抖动先降噪、延长帧率必要时启用辅助光源同一个 DAC 值位置不一致VCM 迟滞未补偿或补偿失效重新标定迟滞表按运动方向选择补偿表冬天对焦精度下降温度引起行程漂移增加温度传感器做行程表温度插值补偿大光圈下对焦精度不够景深太浅搜索步长过大减小细搜步长缩短粗搜步长增加细搜精度连续对焦时偶发抖动触发策略过于敏感增加触发阈值和评分时间域平滑更换模组厂家后对焦异常行程表、迟滞表不通用每个模组型号重新跑一轮标定流程拍摄白墙等低纹理场景失败评价函数没有有效信息引入激光测距或 PDAF 作为辅助参考对焦后图像轻微前后移动马达回程间隙或者闭环过冲调整驱动波形检查闭环 PID 参数这张表是通用排查路径具体到某一个项目还需要结合模组规格和平台日志去定位。调试 AF 一定要养成看日志的习惯把每次搜索的 DAC 位置、评分值、方向都记录下来问题发生时有数据可查比瞎猜效率高得多。最后再分享一个我自己的习惯每次收到一个新模组我一定会先手工把全行程扫一遍画出一条清晰度评分曲线贴在调试记录里。这个曲线能告诉你很多信息——峰值是否尖锐、是否有次峰、两端是否翘起、噪声水平如何。看懂了这条曲线AF 调参的基本盘就稳了。后续不管是换镜头、换马达、换平台我都建议从这一步重新开始。
返回列表