4. 3A算法基础(中):自动对焦(AF)原理
好,我们接着聊3A算法。上一节讲了自动曝光,这一节轮到自动对焦了。说实话,AF是3A里最让我头疼,也最有成就感的一块。你想想看,用户拿起手机拍照,第一件事就是点屏幕对焦。如果对焦慢了、对错了、或者来回拉风箱,用户立马就会觉得这手机不行。
我在项目里遇到过不少次,明明硬件规格很高,但用户就是抱怨拍照模糊。最后查下来,都是AF tuning没做到位。所以这一节,我把AF的核心原理和tuning要点掰开揉碎了讲清楚。
4.1 自动对焦的两种主流方案
目前手机上的自动对焦,说白了就两大流派:反差对焦(CDAF)和相位对焦(PDAF)。
反差对焦是老祖宗了。它的原理很简单——找图像对比度最大的位置。镜头移动过程中,算法实时计算当前画面的对比度值。当对比度达到峰值时,就认为对焦完成了。
但这里有个问题。你想想看,镜头得先走过峰值点,发现对比度开始下降了,才知道刚才那个位置是最好的。这就意味着它一定会“过头”再回来。所以CDAF天生就慢,而且容易来回振荡。
相位对焦就不一样了。它通过在传感器上做特殊像素(PD像素),直接检测光线入射的角度差异。说白了,它能一次告诉你:“镜头该往哪个方向走,走多远。”不需要来回试探。
核心区别一句话:CDAF是“试出来”的,PDAF是“算出来”的。
我刚开始做高通平台时,觉得PDAF这么先进,那CDAF是不是可以扔了?后来发现不行。PDAF在暗光下精度会下降,而且PD像素本身会损失画质。所以实际方案都是两者结合——光线好时用PDAF快速粗调,然后切到CDAF做精调。
4.2 反差对焦的Tuning要点
虽然现在主流是PDAF,但CDAF作为兜底方案,tuning做不好一样翻车。我总结几个关键点:
4.2.1 搜索窗口的选择
算法不会在全图算对比度,那样太慢了。它会选一个或多个窗口。窗口选在哪?选多大?这直接影响对焦准确性。
- 窗口太小:容易受局部纹理影响,比如人脸眼睛对上了,但耳朵是糊的
- 窗口太大:会把背景算进来,比如拍人时背景是白墙,对比度低,算法就懵了
我个人习惯是:人脸场景下,窗口覆盖人脸区域;普通场景下,窗口覆盖画面中央1/3区域。高通平台里有个参数叫af_roi_weight,可以给不同区域分配权重,这个要好好利用。
4.2.2 搜索步长与速度
CDAF的搜索过程,其实就是镜头一步步移动,每步算一次对比度。步长设大了,速度快但容易错过峰值;步长设小了,精度高但慢得像蜗牛。
| 步长策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 大步长粗搜 | 快速定位大致位置 | 可能跳过峰值 | 初始对焦、场景切换 |
| 小步长精搜 | 精度高 | 速度慢 | 微距、近景 |
| 自适应步长 | 兼顾速度和精度 | 算法复杂 | 通用场景 |
我在项目中踩过一个坑:某款机型在微距模式下,CDAF总是对不准。后来发现是步长设得太大了,微距场景下景深极浅,大步长直接跳过了焦平面。改成自适应步长后,问题解决。
避坑指南:我曾经把搜索步长设得过于激进,结果在4K视频录制时,镜头一直在微调,导致画面出现肉眼可见的“呼吸效应”。后来不得不把视频模式的搜索步长单独调小。
4.3 相位对焦的Tuning要点
PDAF的tuning,核心在于PD像素的校准和置信度判断。
4.3.1 PD像素校准
PD像素本质上是一对“半遮光”的像素。左边像素只看到光线的左半部分,右边像素只看到右半部分。当对焦准确时,两个像素的信号应该相等。如果不等,就说明离焦了。
但问题是,PD像素本身存在制造偏差。即使对焦准确,左右像素的输出也可能不一样。这就需要做校准。
高通平台里有个工具叫PD Calibration Tool,用来生成校准表。校准表里记录了每个PD像素的增益补偿值。我建议在产线上做一次完整的PD校准,否则PDAF的精度会大打折扣。
// PD校准表示例(伪代码)
struct pd_calibration_entry {
uint16_t pd_x; // PD像素x坐标
uint16_t pd_y; // PD像素y坐标
int16_t gain_offset; // 增益补偿值
uint8_t confidence; // 置信度
};
4.3.2 置信度判断
PDAF不是万能的。在暗光、纯色区域、或者纹理重复的场景下,PD像素算出来的相位差可能不准。这时候就需要置信度机制来兜底。
高通平台里有个参数叫pd_confidence_threshold。当置信度低于这个阈值时,算法会回退到CDAF模式。这个阈值设多少合适?
- 设高了:PDAF经常被禁用,对焦速度变慢
- 设低了:PDAF在暗光下乱跑,对焦不准
我一般建议:室内正常光照下,阈值设在0.6左右;暗光场景(低于50 lux),阈值降到0.3。当然,具体数值要看传感器表现,没有通用值。
4.4 对焦速度与精度的平衡
这是AF tuning里最核心的命题。速度快了精度差,精度高了速度慢。怎么平衡?
我的做法是:分场景、分模式、分距离。
4.4.1 分场景
不同场景对速度和精度的要求不一样:
| 场景 | 速度要求 | 精度要求 | 推荐策略 |
|---|---|---|---|
| 拍照预览 | 高 | 中 | 优先PDAF,快速锁定 |
| 视频录制 | 中 | 高 | 平滑过渡,避免呼吸效应 |
| 微距 | 低 | 极高 | CDAF精调为主 |
| 夜景 | 低 | 高 | 降低PDAF置信度阈值 |
4.4.2 分模式
高通平台支持多种AF模式:
- CAF(连续自动对焦):视频场景常用,需要平滑跟踪
- SAF(单次自动对焦):拍照场景,追求一次到位
- Touch AF(触摸对焦):用户指定对焦区域,需要快速响应
每种模式的tuning参数都不一样。我见过有人把所有模式用同一套参数,结果CAF模式下镜头抖得厉害,SAF模式下又对不准。
小技巧:在CAF模式下,我习惯把PDAF的更新频率降低到30fps,而不是用满60fps。这样能减少镜头微调带来的画面抖动。
4.4.3 分距离
对焦距离不同,镜头的移动策略也不同。近景(<30cm)时,景深极浅,需要精细控制;远景(>2m)时,景深大,可以粗放一些。
高通平台里有个lens_curve参数,定义了镜头位置和实际对焦距离的映射关系。这个曲线一定要标定准确,否则算法算出来的位置和实际焦平面不匹配。
4.5 AF Tuning的完整流程
说了这么多,我画个流程图,把AF tuning的整体脉络理清楚。
4.6 实战中的常见问题
最后,我分享几个实际项目中遇到的对焦问题,你们以后碰到了可以少走弯路。
4.6.1 近远切换卡顿
从拍近景切换到拍远景时,镜头需要移动很大行程。如果速度控制不好,画面会突然模糊然后慢慢清晰,用户体验很差。
我的做法是:在检测到场景切换时,先用PDAF快速估算目标位置,然后直接跳转过去,再用CDAF微调。这样用户几乎感觉不到对焦过程。
4.6.2 暗光对焦失败
暗光下PDAF置信度低,CDAF对比度也低,算法容易陷入死循环。我建议在暗光场景下,强制使用CDAF并降低搜索终止条件。哪怕对焦不是最准的,也比来回拉风箱强。
4.6.3 人脸对焦不准
人脸检测框和对焦框如果不一致,会导致人脸对上了但眼睛是糊的。高通平台里有个face_af_mode参数,可以让人脸区域优先对焦。这个一定要打开。
注意:我曾经遇到一个case,人脸对焦总是偏后。查了半天发现是镜头曲线标定错了,导致算法认为人脸在50cm,实际镜头对焦在60cm。重新标定后问题解决。所以硬件标定是基础,基础不牢,地动山摇。