038、自动对焦AF技术对比:反差对焦CDAF、相位对焦PDAF与双像素对焦的工程实现

038、自动对焦AF技术对比:反差对焦CDAF、相位对焦PDAF与双像素对焦的工程实现 038、自动对焦AF技术对比反差对焦CDAF、相位对焦PDAF与双像素对焦的工程实现一、一个让我熬夜三天的对焦问题2019年某旗舰机项目客户反馈暗光下拍照经常“拉风箱”——镜头来回伸缩就是合不上焦。我拿着样机在实验室反复测试发现一个诡异现象在低照度场景下PDAF相位对焦检测到的相位差数值跳动剧烈从20跳到-15再跳到8导致马达像无头苍蝇一样乱窜。更麻烦的是当场景中有LED灯或荧光灯时这种跳动会加剧——因为50Hz/60Hz的频闪干扰了相位检测像素的积分时间。这个案例让我意识到很多工程师对AF的理解停留在“知道三种对焦方式的名字”但真正遇到工程问题时往往不知道如何权衡和调试。今天这篇笔记我就从底层原理到工程实现把CDAF、PDAF和双像素对焦Dual Pixel AF的坑和技巧全盘托出。二、反差对焦CDAF最笨但最稳的“爬山算法”CDAF的原理简单到让人想笑镜头移动过程中计算每一帧图像的对比度通常用Sobel算子或拉普拉斯算子提取高频分量找到对比度最大的位置就是合焦点。这就像爬山——你闭着眼睛摸山顶每走一步摸一下坡度坡度最大时就是山顶。工程实现上的坑搜索策略不能太死板。很多新手直接写“全局搜索”从微距到无穷远扫一遍这在手机模组上至少需要2-3秒用户早骂娘了。实际工程中用的是“粗搜细搜”两段式先大步长找到对比度峰值的大致区域再小步长精确定位。这里踩过坑——粗搜的步长如果超过景深范围会直接跳过峰值导致对焦失败。我的经验是步长取景深范围的1/3比如景深是100个马达步步长设30步。对比度计算的窗口选择。别傻乎乎用全图计算计算量大不说背景的纹理还会干扰对焦。正确做法是在画面中心区域通常取10%-20%面积开一个矩形窗口但要注意——如果用户把主体放在画面边缘比如三分法构图中心窗口就废了。所以高端方案会做多窗口加权或者结合人脸检测动态调整窗口位置。别这样写死窗口坐标要留接口给上层算法调整。低照度下的信噪比问题。暗光下图像噪声大对比度曲线会变得“毛刺”很多峰值不明显。我常用的技巧是对对比度值做滑动平均滤波窗口大小3-5帧或者用高斯滤波平滑曲线。但滤波太强会引入延迟导致对焦慢——这里需要根据场景动态调整滤波强度比如照度低于10lux时加大滤波高于100lux时减小。三、相位对焦PDAF又快又准但暗光下会“瞎”PDAF的原理是在sensor上放置一些“相位检测像素”——这些像素被遮挡了一半左半或右半形成一对“左眼”和“右眼”像素。当镜头合焦时左右像素的亮度一致离焦时左右像素的亮度存在相位差这个差值正比于离焦量。马达根据相位差直接驱动到合焦位置一步到位不需要像CDAF那样来回搜索。工程实现上的坑相位检测像素的排布方式。早期方案是在sensor上稀疏地放置几组相位像素比如每16x16像素中放一组这导致一个问题相位像素的密度太低遇到纹理稀疏的区域比如白墙、天空相位差计算会失败。我调试过一款sensor在纯色场景下相位差输出全是0AF直接“失明”。解决方案是当相位差置信度低于阈值时自动回退到CDAF模式。这个切换逻辑要平滑否则用户会看到镜头突然“抽搐”一下。相位差与马达步数的映射关系。相位差是一个无量纲数值需要转换成马达的驱动步数。这个映射不是线性的因为镜头的光学特性像差、畸变会影响相位差-离焦量的关系。我踩过的坑是直接用线性映射结果在微距端对焦不准。正确做法是在产线标定阶段采集不同物距下的相位差-马达步数对应表然后用多项式拟合通常3阶就够了。别用高阶拟合过拟合会导致边缘场景崩溃。暗光下的相位差噪声。回到开篇那个案例暗光下相位差跳动是因为相位检测像素的尺寸通常比普通像素小为了留出遮挡区域导致灵敏度下降信噪比恶化。我当时的解决方案是在低照度下对相位差做时间域滤波比如卡尔曼滤波同时增加相位差计算的积分时间从1帧增加到2-3帧。但积分时间增加会降低帧率影响预览流畅度——这里需要权衡我最终的做法是照度低于20lux时帧率从30fps降到15fps换取稳定的相位差输出。四、双像素对焦Dual Pixel AF全像素相位检测的“降维打击”双像素对焦是PDAF的终极进化版——每个像素都被分成左右两个子像素或者上下相当于整个sensor都是相位检测像素。这意味着无论画面中哪个区域都能计算相位差而且精度更高因为每个像素都参与。索尼的IMX260三星S7用是第一个大规模商用的双像素sensor后来几乎所有旗舰机都跟进了。工程实现上的坑双像素的读出带宽压力。每个像素要读出左右两个子像素的数据数据量翻倍对MIPI接口的带宽要求极高。我调试过一款双像素sensor在4K 60fps模式下MIPI带宽直接爆了导致画面出现撕裂。解决方案是在sensor内部做binning合并子像素或者只在高分辨率拍照模式下启用双像素预览模式用普通模式。别这样写死——要根据场景动态切换比如用户打开“专业模式”时强制启用双像素。左右子像素的增益匹配。由于工艺偏差左右子像素的灵敏度可能不一致导致即使合焦时左右子像素的亮度也不相等产生“伪相位差”。这需要在产线做标定对均匀光源拍摄计算每个像素的左右子像素增益比然后写入sensor的OTP一次性可编程寄存器。我遇到过一批sensorOTP数据写错了导致整批手机对焦不准——后来加了产线校验环节标定后立即验证对焦精度。双像素与HDR的冲突。很多sensor支持HDR模式比如交错式HDR长曝光帧和短曝光帧交替输出但双像素的左右子像素读出时序和HDR的帧时序可能冲突。我踩过的坑是在HDR模式下启用双像素结果相位差计算用了长曝光帧的左子像素和短曝光帧的右子像素时间不对齐相位差完全错误。解决方案是在HDR模式下强制双像素只使用同一帧的左右子像素或者干脆禁用双像素回退到CDAF。五、三种对焦方式的工程选择与混合策略在实际产品中没有哪个方案是完美的都是混合使用PDAF主导CDAF兜底这是最常见的方案。PDAF负责快速粗调比如从无穷远调到目标位置附近然后CDAF做精调微调几个步长找到对比度峰值。这里有个细节PDAF的粗调精度要保证落在CDAF的搜索范围内否则CDAF找不到峰值。我一般要求PDAF的粗调误差小于CDAF搜索范围的1/2。双像素深度学习这是目前旗舰机的方向。双像素提供密集的相位差信息然后输入一个轻量级神经网络比如MobileNetV2的变体预测最佳对焦位置。这个方案的好处是可以处理复杂场景比如透过玻璃、有雾气的场景但坏处是模型训练需要大量数据而且推理延迟要控制在5ms以内否则影响预览帧率。我调试过一个方案模型在GPU上跑没问题但移植到DSP上时量化精度不够导致对焦精度下降——后来改用混合精度量化部分层用int8部分层用float16才解决。激光/ToF辅助在极暗光下1luxPDAF和双像素都失效这时候需要激光测距或ToF传感器。但激光的缺点是只能测中心点而且遇到玻璃会反射错误。我见过一个方案激光测距双像素融合激光给出粗距离双像素做精调效果不错但成本高。六、个人经验性建议别迷信“全像素对焦”。双像素虽然好但sensor的读出带宽和功耗是硬约束。如果产品定位中端用稀疏PDAFCDAF混合就足够了把省下的成本用在更好的镜头上效果可能更好。产线标定是AF的灵魂。无论哪种方案标定不好都是白搭。我见过太多项目算法写得天花乱坠但产线标定环节偷工减料——比如只标了5个物距点结果在中间物距段对焦不准。我的建议是至少标定20个物距点从5cm到无穷远均匀分布然后用分段线性插值比多项式拟合更鲁棒。调试AF时先看“置信度”。很多工程师一上来就看相位差数值但忽略了置信度。置信度低时比如纹理稀疏、光照不足强行使用相位差只会让情况更糟。我的调试习惯是在log中同时打印相位差和置信度当置信度低于0.3时自动切换到CDAF。用户场景比实验室数据重要。实验室里用标准灯箱测试AF可能完美无缺但到了用户手里——拍LED屏幕、拍玻璃反光、拍快速移动的宠物——各种问题就冒出来了。我的经验是在调试阶段每天花1小时拿着样机去真实场景地铁、商场、公园拍照记录AF失败的case然后针对性优化。最后别忘记“手感”。AF的速度和精度固然重要但用户感知到的“对焦手感”同样关键。比如对焦过程中镜头移动要平滑不能有“咔哒”声马达的步进声合焦后要有轻微的“锁定感”可以通过马达的阻尼控制实现。这些细节往往决定了用户是否愿意为你的产品买单。