4、相位对焦(PDAF)详解:片上相位检测像素原理、左右相位图生成、视差计算与失焦方向判断
相位对焦,圈里人常叫它PDAF。这玩意儿在手机上已经普及好几年了,但真正把它吃透的工程师其实不多。我当年刚接触PDAF时,总觉得它像个黑盒子——输入RAW图,输出一个对焦方向,中间发生了什么?今天咱们就把这个盒子拆开,从像素结构一路看到视差计算。
4.1 片上相位检测像素原理
先说核心思想。PDAF的本质,是在传感器上造出一对“眼睛”。
普通像素的微透镜下面是一个完整的光电二极管,光线全部汇聚到中心。而相位检测像素不一样——它在微透镜下面放了两块光电二极管,或者用遮挡层把光线一分为二。
两种主流实现方式:
- 双光电二极管(2PD / Dual PD): 一个微透镜覆盖两个独立PD,左右各一个。这是目前最主流方案,索尼IMX系列大量使用。
- 半遮挡像素(Masked PD): 在微透镜或金属层上做遮挡,只让左边或右边光线通过。早期PDAF用得多,现在基本退出了。
我个人习惯把2PD结构叫“原生相位像素”。为什么?因为它不损失画质。半遮挡像素会丢掉一半光线,暗光下基本废了。2PD每个子像素都能参与成像,后期合并成一个完整像素,亮度和普通像素一样。
嗯,这里要注意:2PD虽然不损失亮度,但会损失一点点分辨率——毕竟每个微透镜下有两个PD,像素总数翻倍了。不过手机传感器像素早就过亿了,这点损失根本看不出来。
4.2 左右相位图生成
传感器输出RAW图后,第一步就是把左右相位图拆出来。
假设传感器是2PD结构,每个微透镜下的两个PD分别记为L和R。那么RAW图里,奇数行可能是L像素,偶数行是R像素,或者按列交错排列。具体排列方式取决于传感器厂商的bayer pattern设计。
拆图流程其实很简单:
- 读取RAW图,根据像素坐标判断它是L还是R。
- 把所有L像素抽出来,放到一张图上,位置不变。
- 把所有R像素抽出来,放到另一张图上,位置不变。
- 对两张图做插值,补全缺失的像素位置,得到完整分辨率的左右相位图。
避坑指南: 我曾经在某个项目里直接拿原始L/R图做视差计算,结果发现边缘全是噪声。后来才意识到,L/R图的分辨率只有原图的一半,直接算视差会引入大量假匹配。正确的做法是先做插值,把分辨率恢复上去。
插值方法我推荐双线性插值,简单够用。别用太复杂的算法,相位图本身就有噪声,插值再花哨也救不了信噪比。
4.3 视差计算
有了左右相位图,接下来就是算视差了。说白了,就是找L图和R图之间的偏移量。
视差计算的核心是块匹配。我拿一个窗口在L图上取一块,然后在R图上沿着水平方向滑动,找最相似的位置。两个位置的差值就是视差。
匹配代价计算常用方法:
| 方法 | 公式 | 特点 |
|---|---|---|
| SAD(差和) | Σ|L(i,j) - R(i,j)| | 计算量最小,硬件友好 |
| SSD(平方差和) | Σ(L(i,j) - R(i,j))² | 对大偏差更敏感,精度略高 |
| NCC(归一化互相关) | Σ(L·R) / √(ΣL²·ΣR²) | 抗光照变化,但计算量大 |
手机上我一般用SAD。为什么?因为快。你想想看,每一帧要对几十万个像素做匹配,用NCC的话帧率直接掉到个位数。SAD配合硬件加速,一毫秒内就能搞定。
窗口大小也有讲究。窗口太小,噪声大;窗口太大,会模糊掉细节。我常用的经验值是8x8或16x16,具体看传感器分辨率和场景纹理丰富度。
4.4 失焦方向判断
算完视差,最后一步就是判断镜头该往哪边转。
这里有个关键概念:视差的正负号代表失焦方向。
- 视差为正(L图在R图左边): 镜头当前在焦点的后方,需要向前推。
- 视差为负(L图在R图右边): 镜头当前在焦点的前方,需要向后拉。
- 视差为零: 合焦了,别动。
为什么会这样?我画个图你就明白了。
注意: 视差方向的定义在不同传感器厂商之间可能相反。有些厂商把L在R左边定义为正,有些定义为负。做驱动层对接时,一定要先确认传感器的datasheet,否则对焦方向会反掉。
实际工程中,我们不会只靠一个像素的视差做判断。整张图会分成多个区域,每个区域算一个视差值,然后做加权平均。中心区域权重高,边缘区域权重低——毕竟用户通常关注画面中央。
我曾经遇到过一个坑:在低纹理场景下,整张图的视差都算不准,导致镜头来回震荡。后来加了一个置信度判断——如果某个区域的纹理能量低于阈值,就把它从视差计算中排除掉。这个改动让对焦稳定性提升了一大截。
4.5 工程落地要点总结
| 环节 | 关键点 | 常见问题 |
|---|---|---|
| 像素拆图 | 先插值再计算,别直接用半分辨率图 | 边缘噪声放大 |
| 匹配代价 | SAD优先,硬件加速 | NCC计算量过大 |
| 窗口大小 | 8x8 ~ 16x16,根据场景自适应 | 窗口太小噪声大,太大模糊 |
| 视差方向 | 确认传感器定义,避免反方向 | 驱动层对接错误 |
| 置信度过滤 | 低纹理区域排除 | 镜头震荡 |
相位对焦的原理说完了。说白了,它就是利用传感器上的“双眼”结构,通过视差直接算出失焦方向和大小。相比反差对焦那种“瞎蒙式”的爬山搜索,PDAF一次就能到位,快得多。但它的精度受限于像素尺寸和光线条件——暗光下相位像素的信噪比下降,视差计算就不准了。这也是为什么现在的旗舰机都在搞混合对焦,把PDAF、CDAF、激光对焦揉在一起用。