3、光学系统设计:镜头选型与成像质量

做嵌入式视觉这几年,我踩过最大的坑,往往不是算法选错了,而是镜头没选对。你想想看,传感器再好,镜头不给力,拍出来的图就是一团糊。今天咱们就聊聊光学系统设计里最核心的几个问题。

3.1 镜头选型三要素:焦距、光圈、视场角

选镜头,说白了就是算三个数。我习惯先定视场角,再算焦距,最后看光圈够不够用。

焦距(Focal Length)

焦距决定了你能看多远、看多宽。公式很简单:

焦距 f = (传感器尺寸 × 工作距离) / 目标宽度

举个例子。我做过一个车牌识别项目,要求3米外拍清车牌。车牌宽约0.44米,用的1/2.3英寸传感器(宽约6.2mm)。算下来:

f = (6.2 × 3000) / 440 ≈ 42mm

嗯,实际选了35mm镜头,稍微广一点,留点余量。

我的习惯:焦距宁短勿长。短了可以裁图,长了拍不全就麻烦了。

光圈(Aperture)

光圈用F数表示,F1.4比F2.8进光量大。但别盲目追求大光圈。

  • 大光圈(F1.2~F2.0):进光多,适合暗光。但景深浅,容易虚焦。
  • 中等光圈(F2.8~F4.0):画质最锐,畸变也小。我大部分项目用这个范围。
  • 小光圈(F8.0以上):景深大,但衍射效应开始影响清晰度。
注意:嵌入式设备常用自动光圈镜头,但要注意光圈控制器的响应速度。我曾经遇到光圈调节滞后,导致画面忽明忽暗,排查了两天才发现是驱动时序问题。

视场角(Field of View, FOV)

视场角分水平、垂直、对角线三种。我一般只看水平视场角,因为传感器宽高比固定,算一个就全知道了。

传感器尺寸 6mm镜头 12mm镜头 25mm镜头
1/3英寸 约52° 约28° 约14°
1/2英寸 约67° 约37° 约19°
2/3英寸 约83° 约48° 约25°

记住一个规律:焦距翻倍,视场角大约减半。这不是精确的线性关系,但做快速估算够用了。

3.2 光照条件对成像的影响

光照是嵌入式视觉里最头疼的问题,没有之一。我见过太多项目在实验室跑得飞起,一到现场就翻车,十有八九是光照变了。

光照强度

太暗了噪点多,太亮了过曝。嵌入式相机动态范围有限,一般只有60~70dB,而真实场景动不动就100dB以上。

  • 低照度(<10 lux):需要红外补光或大光圈镜头。我建议用全局快门传感器,配合LED频闪同步。
  • 正常照度(100~1000 lux):大部分镜头都能应付。注意避免阳光直射。
  • 高照度(>10000 lux):必须加ND滤镜或缩短曝光时间。否则传感器会饱和。
关键点:光照变化时,自动曝光算法要稳。我习惯用「目标亮度+曝光时间优先」策略,先固定增益,再调曝光时间,最后才动增益。这样噪点可控。

色温与白平衡

不同光源色温差异很大。白炽灯约2800K,日光约5500K,荧光灯约4000K。嵌入式相机自动白平衡经常翻车,尤其是混合光源场景。

我的做法:固定色温值,用LED补光统一光源。如果必须适应环境,就手动标定几个常用色温的校正矩阵。

频闪问题

50Hz/60Hz的交流电会让LED灯和荧光灯产生频闪。你想想看,如果曝光时间刚好是10ms,拍出来的画面可能一明一暗。

解决方案:

// 避开频闪的曝光时间设置
// 50Hz地区:曝光时间设为10ms的整数倍
// 60Hz地区:曝光时间设为8.33ms的整数倍
if (region == 50Hz) {
    exposure_time = 20;  // 20ms
} else {
    exposure_time = 16.66;  // 16.66ms
}

3.3 镜头畸变与校正

畸变是镜头的物理缺陷,广角镜头尤其明显。说白了就是画面边缘的直线变弯了。

畸变类型

  • 桶形畸变:画面像吹气球一样向外鼓。广角镜头常见。
  • 枕形畸变:画面向内凹。长焦镜头常见。
  • 复合畸变:两者都有,边缘像波浪一样。变焦镜头常见。

畸变校正方法

校正分两步:标定和重映射。

第一步:标定

用棋盘格拍几张不同角度的照片,提取角点,算出畸变系数。OpenCV里用 cv::calibrateCamera() 就行。

// 畸变系数示例(5参数模型)
// k1, k2: 径向畸变
// p1, p2: 切向畸变
// k3: 高阶径向畸变
double distCoeffs[] = {-0.2854, 0.0897, 0.0004, -0.0008, -0.0215};

第二步:重映射

cv::initUndistortRectifyMap() 生成映射表,再用 cv::remap() 校正。注意,嵌入式设备上要提前算好映射表,运行时只做查表操作。

性能优化:畸变校正很耗CPU。我一般把映射表存成二进制文件,启动时加载。如果帧率要求高(比如30fps以上),考虑用NEON指令集加速重映射。

什么时候必须校正?

不是所有场景都需要校正。我的经验:

  • 必须校正:测量类应用(尺寸检测、定位)、需要拼接多张图的场景。
  • 可以不校:纯分类任务(比如判断有没有人)、目标检测(只要目标没变形到认不出)。
避坑指南:我曾经在一个项目里,为了省性能没做畸变校正,结果目标检测框在画面边缘偏移了十几个像素。后来加校正后,检测精度从82%提升到94%。所以,别偷懒。

3.4 实战选型流程

最后,我总结一下自己的选型步骤:

  1. 定工作距离和视场:现场量一下,留20%余量。
  2. 算焦距:用公式算,然后选最接近的标品。
  3. 定光圈:先按F2.8算,如果暗光不够再开大。
  4. 检查畸变:广角镜头必须标定,长焦可以放宽。
  5. 做光照测试:拿样机去现场拍一段视频,看自动曝光稳不稳。

嗯,这套流程我用过不下二十次,基本没出过大问题。你试试看。