相机流水线基础:从光子到像素的旅程

做端侧推理引擎适配相机,第一件事不是写代码,而是搞懂相机是怎么把光变成数字信号的。我刚开始接触这个领域时,以为相机就是个传感器加个驱动,后来被 ISP 流水线狠狠教育了一顿。今天咱们就把这条流水线拆开看看。

相机成像原理:光子的奇幻漂流

说白了,相机成像就是光子从镜头进入,最终变成数字像素的过程。整个过程可以分成三步:

  • 镜头组聚焦:光线通过多片透镜,被折射到传感器表面。这里有个坑——镜头畸变,广角镜头尤其明显,后面 ISP 会做校正。
  • 传感器光电转换:CMOS 传感器上的每个像素点(photosite)吸收光子,产生电子。电子数量与光强成正比。嗯,这里要注意,传感器只能感知光的强度,不能感知颜色。
  • Bayer 阵列采样:为了获取颜色信息,传感器表面覆盖了一层彩色滤光片阵列(CFA),最常见的是 Bayer 模式——RGGB。每个像素只记录一种颜色,另外两种颜色要靠插值算出来。

关键理解:传感器输出的原始数据叫 RAW 数据,每个像素只有 10bit 或 12bit 的灰度值,没有颜色、没有白平衡、没有伽马校正。这就是 ISP 流水线的起点。

ISP 流水线:三大域的处理逻辑

ISP(Image Signal Processor)把 RAW 数据变成人眼看起来舒服的图像。我习惯把 ISP 流水线分成三个处理域:RAW 域、RGB 域、YUV 域。每个域干的事完全不同。

RAW 域:原始数据的预处理

这个阶段处理的是传感器直接输出的 RAW 数据。我在项目中遇到过一个问题:暗光下图像全是噪点,后来发现是 RAW 域的降噪参数没调好。

  • 黑电平校正:传感器在无光时也有微弱输出,需要减去这个基准值。
  • 镜头阴影校正:镜头边缘进光量比中心少,需要补偿。
  • 坏点校正:传感器上总有那么几个像素是坏的,需要用邻居像素插值替换。
  • 去马赛克:把 Bayer 阵列插值成完整的 RGB 图像。这一步很关键,算法好坏直接影响画质。

个人经验:RAW 域处理是 ISP 性能瓶颈之一。如果你要在相机流水线里插入 AI 推理,最好在 RAW 域或 YUV 域做,别在 RGB 域折腾——RGB 域数据量大,带宽吃不消。

RGB 域:色彩的重塑

去马赛克之后,图像变成了 RGB 格式。这个阶段主要做色彩相关的处理:

处理模块 作用 我踩过的坑
白平衡 校正色温,让白色物体在不同光源下都呈现白色 荧光灯下白平衡经常偏绿,需要手动干预
颜色校正矩阵 把传感器色彩空间映射到标准色彩空间 不同传感器矩阵参数完全不同,不能复用
伽马校正 调整亮度曲线,适配显示设备 伽马值设错了,图像要么发白要么发暗

YUV 域:压缩与传输的妥协

RGB 转 YUV 是为了压缩和传输。Y 是亮度分量,UV 是色度分量。人眼对亮度敏感、对色度不敏感,所以 UV 可以降采样,数据量直接减半。

为什么会这样?说白了,视频编码和显示接口都基于 YUV 设计。你在手机上看到的每一帧画面,最终都是以 YUV 格式在流水线里跑的。

注意:YUV 有多种格式,NV12、NV21、YV12 等等。Android 相机默认输出 NV21,iOS 默认输出 NV12。做推理引擎适配时,输入格式不匹配是常见问题。我曾经因为格式搞错,浪费了两天调试时间。

Android Camera2 API 与 iOS AVFoundation 框架

这两个是移动端相机开发的入口。我简单对比一下:

维度 Android Camera2 iOS AVFoundation
架构 基于管道(Pipeline)模型,异步回调 基于会话(Session)模型,代理回调
数据流控制 通过 CaptureRequest 和 CaptureResult 控制 通过 AVCaptureOutput 子类控制
YUV 获取 ImageReader 获取 YUV_420_888 格式 AVCaptureVideoDataOutput 获取 CMSampleBuffer
性能 碎片化严重,不同厂商实现差异大 统一性好,但定制化能力弱

我个人习惯在 Android 上用 Camera2 的 ImageReader 获取 YUV 数据,然后传给推理引擎。iOS 上则用 AVCaptureVideoDataOutput 的代理方法,在 captureOutput:didOutputSampleBuffer:fromConnection: 里拿到数据。

相机数据流:Preview、Video、Photo

相机有三种数据流,它们的处理逻辑完全不同:

  • Preview 流:实时性要求最高,延迟要控制在 30ms 以内。分辨率通常较低(1080p 或更低),帧率 30fps。推理引擎做实时检测时,一般挂在这个流上。
  • Video 流:需要编码存储,对画质要求高。分辨率可达 4K,帧率 60fps。推理引擎可以在这里做视频分析,但要注意功耗。
  • Photo 流:单帧最高质量,分辨率最大。适合做高精度推理,但延迟不是问题。

实战建议:做端侧推理时,优先挂载 Preview 流。原因很简单——Preview 流分辨率低、帧率稳定、延迟可控。Video 流和 Photo 流数据量大,推理耗时高,容易导致手机发热降频。

本章知识结构图

下面这张图展示了相机流水线的完整链路,以及推理引擎可以插入的位置:

相机流水线 & 推理引擎插入点 镜头组 CMOS 传感器 RAW 域处理 RGB 域处理 YUV 域 Preview 流 Video 流 Photo 流 推理引擎 (YUV 输入) 关键说明: 1. RAW 域:黑电平校正、镜头阴影校正、坏点校正、去马赛克 2. RGB 域:白平衡、颜色校正矩阵、伽马校正 3. YUV 域:色彩空间转换、色度降采样 4. 推理引擎推荐插入点:YUV 域(数据量适中,格式统一)