2. 自动对焦(AF)基础原理:反差对焦(CDAF)与相位对焦(PDAF)的工作机制
自动对焦这事儿,说白了就是让镜头找到那个最清晰的位置。我入行那会儿,手机摄像头还都是定焦的,后来才慢慢有了AF。今天咱们就聊聊两种最主流的对焦方式——反差对焦和相位对焦。
你想想看,相机怎么知道画面清不清晰?它又不知道你拍的是猫还是花。它只能靠一些数学指标来判断。嗯,这就是CDAF和PDAF的出发点不同了。
2.1 反差对焦(CDAF)——"爬山"找最锐
CDAF的原理特别直观。它就像在爬山——镜头从近到远移动,每到一个位置就计算当前画面的对比度值。对比度最高的地方,就是焦点所在。
核心逻辑:对比度值越高 → 画面越清晰 → 焦点越准。
我在项目中遇到过一个问题:客户反馈某些场景下对焦来回"拉风箱"。其实就是CDAF在对比度变化平缓的区域找不到明显的峰值,镜头在那反复试探。
2.1.1 对比度怎么算?
常用的算法是计算相邻像素的亮度差。比如Sobel算子、Laplacian算子。说白了就是看边缘锐不锐。
// 简化的对比度计算示例
int calc_contrast(uint8_t *frame, int width, int height) {
int sum = 0;
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
int dx = frame[y * width + x + 1] - frame[y * width + x - 1];
int dy = frame[(y + 1) * width + x] - frame[(y - 1) * width + x];
sum += abs(dx) + abs(dy);
}
}
return sum;
}
这段代码虽然简单,但实际ISP里用的差不多就是这个思路。值越大,说明边缘越锐利。
2.1.2 CDAF的"爬山算法"
镜头移动过程中,对比度值会形成一个曲线。算法要做的就是找到这个曲线的顶点。
- 粗搜阶段:大步长移动,快速定位峰值大致区域。
- 细搜阶段:小步长来回,精确找到峰值位置。
- 确认阶段:在峰值附近再采样几次,防止误判。
我曾经踩过的坑:在低光照环境下,CDAF的对比度曲线会变得非常平坦。算法容易把噪声当成峰值。后来我加了一个"最小对比度阈值"判断,低于阈值的场景直接切换到PDAF或者用更大的步长搜索。
2.2 相位对焦(PDAF)——"一眼看穿"距离
PDAF就聪明多了。它不需要来回移动镜头去"试"。它通过相位检测像素,一次就能判断出焦点偏前还是偏后,以及偏了多少。
我记得第一次接触PDAF是在某款旗舰传感器的datasheet上。当时觉得这玩意儿简直是黑科技——它怎么知道镜头该往哪边转?
2.2.1 相位检测像素的结构
普通的像素只有一个光电二极管。PDAF像素则被一分为二——左边和右边各有一个光电二极管,或者用微透镜遮挡一半。
| 类型 | 结构 | 特点 |
|---|---|---|
| 2x1 OCL | 两个像素共享一个微透镜 | 灵敏度高,但分辨率损失 |
| Dual Pixel | 每个像素内部分成两个PD | 全像素相位检测,无分辨率损失 |
| Masked PD | 遮挡一半像素 | 成本低,但暗光性能差 |
2.2.2 相位差的计算
左右两个"半像素"分别成像。如果焦点准确,两个图像完全重合。如果焦点偏前或偏后,两个图像就会错位——这个错位量就是相位差。
个人习惯:我调试PDAF时,会先看"相位差-镜头位置"曲线。这条曲线应该是线性的。如果出现非线性或者跳变,基本可以断定是校准参数出了问题。
// 相位差计算示意
int calc_phase_diff(uint8_t *left_line, uint8_t *right_line, int len) {
int min_diff = INT_MAX;
int best_shift = 0;
for (int shift = -MAX_SHIFT; shift <= MAX_SHIFT; shift++) {
int diff = 0;
for (int i = 0; i < len; i++) {
int l = left_line[i];
int r = (i + shift >= 0 && i + shift < len) ?
right_line[i + shift] : 0;
diff += abs(l - r);
}
if (diff < min_diff) {
min_diff = diff;
best_shift = shift;
}
}
return best_shift; // 返回相位差
}
2.3 CDAF vs PDAF:谁更厉害?
其实没有谁厉害。两者各有各的脾气。
| 维度 | CDAF | PDAF |
|---|---|---|
| 对焦速度 | 慢(需要来回搜索) | 快(一次判断方向) |
| 低光性能 | 差(对比度低) | 中等(相位像素灵敏度低) |
| 精度 | 高(直接基于图像) | 中等(依赖校准) |
| 硬件成本 | 低(纯算法) | 高(需要特殊像素) |
| 适用场景 | 静态场景、高对比度 | 运动场景、低对比度 |
2.4 混合对焦——取长补短
现在的手机摄像头基本都是混合对焦了。PDAF快速拉到大致位置,CDAF做最后的精确微调。
我建议的混合策略是这样的:
- 启动阶段:PDAF先跑一次,给出镜头目标位置。
- 粗调阶段:镜头快速移动到目标位置附近。
- 精调阶段:CDAF在小范围内搜索峰值。
- 锁定阶段:确认峰值稳定后,锁定对焦。
关键点:PDAF给出的位置不能直接作为最终焦点。因为相位像素的校准会随温度、光照变化而漂移。必须用CDAF做最终确认。
2.5 知识结构图
下面这张图把CDAF和PDAF的核心流程串起来了。你可以看到两者如何协同工作。
2.6 调试中的常见问题
最后分享几个我在调试AF时遇到的典型问题,希望能帮你少走弯路。
问题1:PDAF方向判断错误
我曾经遇到一个案子,PDAF总是往反方向跑。查了两天才发现是相位像素的左右标记反了。校准文件里把left和right搞混了。
问题2:CDAF在低对比度场景下"拉风箱"
我的解决办法是:当对比度值低于某个阈值时,强制使用PDAF的结果,不再做CDAF精调。虽然精度会差一点,但至少不会来回抖动。
问题3:混合对焦切换时的"顿挫感"
从PDAF切换到CDAF时,如果镜头位置跳变太大,用户会感觉到画面突然模糊一下。我建议做平滑过渡——用插值的方式让镜头慢慢移动到目标位置。