一、自动对焦基础:AF系统概述、对焦评价函数与清晰度计算原理

各位同学,欢迎来到《自动对焦搜索策略与模组匹配实战》的第一章。

做嵌入式视觉这些年,我接触过不少对焦方案。从最早的手机摄像头,到工业检测、无人机吊舱,再到医疗内窥镜,自动对焦(Auto Focus, AF) 始终是成像系统里最基础也最关键的环节。说白了,AF 就是让镜头动起来,找到那个让画面最清晰的位置。

但怎么判断「清晰」?怎么让镜头「动得又快又准」?这就是咱们这门课要解决的核心问题。

1.1 AF系统概述:从物理到算法

一个典型的自动对焦系统,我习惯把它拆成三块:

  • 物理执行层:步进电机、音圈马达(VCM)、压电陶瓷,负责带着镜头跑。
  • 信号感知层:图像传感器(CMOS/CCD),把光信号变成数字图像。
  • 算法决策层:对焦评价函数 + 搜索策略,决定往哪跑、跑多远。

你想想看,算法层才是灵魂。物理层再快,算法判断错了位置,一切都是白搭。

核心观点:自动对焦的本质是一个一维极值搜索问题。镜头位置是自变量,清晰度评价值是因变量。我们的目标,就是在镜头行程上找到评价值的全局最大值。

我在做第一代工业相机项目时,就踩过这个坑。当时只关注了电机响应速度,结果评价函数选错了,画面在峰值附近来回震荡,始终锁不准。嗯,从那以后我养成了一个习惯:先定评价函数,再调搜索策略。

1.2 对焦评价函数:清晰度的「尺子」

评价函数,就是一把测量图像清晰度的尺子。它的基本原理是:清晰图像边缘锐利,灰度变化剧烈;模糊图像边缘平滑,灰度变化平缓。

所以,几乎所有评价函数都在做同一件事——计算图像的高频分量强度。高频越多,图像越清晰。

下面介绍三种最经典的梯度类评价函数。我个人在项目中用得最多的是 Tenengrad 和 Brenner,各有各的适用场景。

1.2.1 Tenengrad 函数

Tenengrad 基于 Sobel 算子,计算水平和垂直两个方向的梯度幅值。它的数学形式是:

F = Σ Σ [ Gx(x,y)² + Gy(x,y)² ]

其中:
Gx = Sobel_x * I(x,y)   // 水平梯度
Gy = Sobel_y * I(x,y)   // 垂直梯度

说白了,就是对每个像素做一次 Sobel 边缘检测,然后把所有边缘强度加起来。值越大,图像越清晰。

我的经验:Tenengrad 对纹理丰富的场景非常稳定。但如果你面对的是纯色平面(比如白墙),它的响应曲线会变得很平坦,容易陷入局部极值。我曾经在一个 PCB 检测项目里吃过这个亏——板子大面积是绿色阻焊层,Tenengrad 几乎失效。后来我换成了 Brenner。

1.2.2 Laplacian 函数

Laplacian 使用二阶微分算子,对噪声更敏感。它的计算方式:

F = Σ Σ | L(x,y) |

其中 L(x,y) 是 Laplacian 算子对图像的卷积结果
常用核:[[0, -1, 0], [-1, 4, -1], [0, -1, 0]]

Laplacian 的优点是响应曲线陡峭,峰值尖锐。但缺点也很明显——对噪声极度敏感。传感器有暗电流噪声?光照有波动?Laplacian 会把这些统统算进「清晰度」里。

避坑指南:我曾经在低照度场景下用 Laplacian 做对焦,结果评价曲线像心电图一样剧烈抖动。后来加了高斯预滤波才稳住。所以,用 Laplacian 之前,先确认你的图像信噪比够不够高。

1.2.3 Brenner 函数

Brenner 是最简单的梯度函数之一,只计算水平方向相隔两个像素的灰度差:

F = Σ Σ | I(x+2, y) - I(x, y) |²

为什么是相隔两个像素?我个人的理解是:相隔一个像素容易受噪声干扰,相隔两个像素能更好地捕捉边缘过渡。这个经验值在 VGA 到 5MP 的传感器上表现都不错。

Brenner 的计算量极小,非常适合嵌入式平台。我在一个基于 STM32 的低功耗相机项目里,就是用 Brenner 配合爬山法,在 30fps 下实现了实时对焦。

1.3 清晰度计算原理:从像素到曲线

理解了三种评价函数,咱们来看看实际计算流程。我把它总结为四个步骤:

  1. 图像采集:从传感器拿到一帧 RAW 或 YUV 数据。
  2. 感兴趣区域(ROI)选取:通常取画面中心区域,或者根据人脸/物体检测框动态选取。
  3. 评价函数计算:对 ROI 内的每个像素(或隔点采样)执行梯度运算。
  4. 归一化与滤波:除以像素总数得到平均清晰度,必要时做滑动平均滤波。

这里有个容易被忽略的细节:ROI 的大小和位置直接影响对焦精度。ROI 太小,容易受局部纹理干扰;ROI 太大,计算量上去了,而且背景区域会拉低评价曲线的陡峭度。

我的建议:ROI 取画面面积的 1/4 到 1/3,优先覆盖画面中心。如果场景中有明确的主体(比如人脸),就跟着主体走。我在人脸识别门禁项目里就是这么干的——对焦框跟着人脸框走,效果比固定中心 ROI 好得多。

下面这张图展示了三种评价函数在同一个镜头行程上的响应曲线对比:

三种评价函数响应曲线对比 镜头位置(步数) 清晰度评价值 Tenengrad Laplacian Brenner Laplacian 峰值最尖锐但噪声敏感,Tenengrad 最平滑稳定,Brenner 计算量最小

从图中可以清楚看到:Laplacian 的峰值最尖锐,理论上定位最准,但曲线抖动也最大;Tenengrad 最平滑,抗噪能力强;Brenner 介于两者之间,计算量最小。

1.4 三种函数的对比与选型建议

为了让你在实际项目中快速选型,我整理了一张对比表:

评价函数 计算量 抗噪性 峰值锐度 适用场景
Tenengrad 中(需 Sobel 卷积) 高 中 纹理丰富、光照稳定的场景
Laplacian 中(二阶微分) 低 高 高 SNR、需要精确定位的场景
Brenner 低(仅差分运算) 中 中 嵌入式实时系统、低功耗设备

选型口诀:

  • 资源够、场景稳 → Tenengrad
  • 要精度、噪声小 → Laplacian
  • 要速度、功耗低 → Brenner

最后说一句:没有万能的评价函数。我在实际项目中,经常会在不同场景下切换不同的函数。比如白天用 Tenengrad,晚上用 Brenner。这个思路,咱们在后面的章节里会详细展开。

好,第一章就到这里。记住这三个函数的名字和特性,它们是后续所有搜索策略的基础。