2. 自动对焦基础
任务目标
本案例实现一个最小可运行的相位检测自动对焦(PDAF)模拟器:给定左右像素对的相对偏移(即相位差),计算散焦量(Defocus),并据此驱动镜头马达移动到合焦位置。通过该案例理解PDAF的核心闭环:相位差 → 散焦量 → 镜头位移。
核心原理与实现
相位检测自动对焦利用微透镜阵列将光线分离为左右两路图像。当镜头合焦时,左右图像完全重合(相位差为0);当失焦时,左右图像产生偏移,偏移量与散焦程度成正比。本案例用一维数组模拟左右像素对,通过互相关计算相位差,再乘以标定系数得到散焦量,最后驱动镜头步进电机移动对应步数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SENSOR_WIDTH 16 // 传感器像素宽度
#define MAX_SHIFT 8 // 最大可检测偏移量
#define FOCUS_COEFF 2.5f // 相位差→散焦量标定系数(μm/像素)
#define STEP_SIZE 0.5f // 镜头步进电机每步位移(μm)
// 模拟左右像素对信号(一维)
typedef struct {
float left[SENSOR_WIDTH];
float right[SENSOR_WIDTH];
} PhasePair;
// 生成模拟信号:中心位置偏移产生相位差
void generate_signal(PhasePair *p, int shift) {
for (int i = 0; i < SENSOR_WIDTH; i++) {
p->left[i] = (i >= 3 && i < 13) ? 1.0f : 0.0f; // 左图方波
int r_idx = i + shift; // 右图偏移
p->right[i] = (r_idx >= 3 && r_idx < 13) ? 1.0f : 0.0f;
}
}
// 计算相位差:遍历所有可能偏移,找最小差异
int compute_phase_diff(PhasePair *p) {
int best_shift = 0;
float min_diff = 1e9f;
for (int s = -MAX_SHIFT; s <= MAX_SHIFT; s++) {
float diff = 0.0f;
for (int i = 0; i < SENSOR_WIDTH; i++) {
int r_idx = i + s;
float r_val = (r_idx >= 0 && r_idx < SENSOR_WIDTH) ? p->right[r_idx] : 0.0f;
diff += (p->left[i] - r_val) * (p->left[i] - r_val);
}
if (diff < min_diff) {
min_diff = diff;
best_shift = s;
}
}
return best_shift; // 返回使差异最小的偏移量(像素)
}
int main() {
// 模拟真实场景:右图相对左图偏移3像素(失焦状态)
PhasePair pair;
int true_shift = 3;
generate_signal(&pair, true_shift);
// 1. 计算相位差
int phase_diff = compute_phase_diff(&pair);
printf("检测到相位差: %d 像素\n", phase_diff);
// 2. 计算散焦量(正=后焦,负=前焦)
float defocus = phase_diff * FOCUS_COEFF;
printf("散焦量: %+.1f μm\n", defocus);
// 3. 驱动镜头:步数 = 散焦量 / 步长(取整)
int steps = (int)(defocus / STEP_SIZE);
printf("镜头驱动: %d 步\n", steps);
// 4. 模拟合焦验证:镜头移动后重新检测
float lens_pos = 0.0f;
lens_pos += steps * STEP_SIZE; // 镜头实际位移
float residual = defocus - lens_pos; // 残余散焦
printf("残余散焦: %+.1f μm\n", residual);
// 判定是否合焦
if (abs(residual) < STEP_SIZE) {
printf("对焦成功:残余散焦小于一个步长\n");
} else {
printf("对焦未完成:需要继续微调\n");
}
return 0;
}
编译与运行
gcc -o pdaf_demo pdaf_demo.c -lm
./pdaf_demo
验证方法与判定标准
程序输出应满足以下逻辑链:
- 相位差检测:输入偏移3像素,输出应为
3(或接近值,取决于信号边缘效应); - 散焦量计算:3像素 × 2.5μm/像素 =
7.5μm; - 镜头驱动:7.5μm ÷ 0.5μm/步 =
15步; - 合焦判定:镜头移动15步后位移7.5μm,残余散焦为0,输出
对焦成功。
若修改true_shift为其他值(如-2、5),程序应自动计算对应散焦量并驱动镜头,残余散焦始终小于一个步长。该结果由代码逻辑直接推出,可作为预期输出验证实现正确性。
关键说明
- 本案例用方波信号模拟图像特征,实际传感器使用带纹理的灰度图像;互相关算法原理一致。
FOCUS_COEFF和STEP_SIZE为标定参数,实际系统中需通过镜头模组标定获得。- 真实PDAF在硬件中并行计算,本案例用遍历搜索实现,逻辑等价且便于理解。