4、混合架构设计原则:传统模块与AI模块的接口定义、数据流设计、实时性约束下的算力分配
好,我们直接进入正题。混合架构,说白了就是把传统 ISP 的确定性算法和 AI 的“黑盒”能力捏在一起。这事儿看着简单,做起来坑特别多。我最早在项目里踩的第一个大坑,就是接口没定义清楚,结果 AI 模块吐出来的数据,传统模块根本不认。
这一章,我们就围绕三个核心问题展开:接口怎么切、数据怎么流、算力怎么分。这三个问题搞定了,架构就稳了一半。
4.1 接口定义:传统与AI的“握手协议”
传统 ISP 模块之间传的是 RAW 图、RGB 图、YUV 图,格式固定,位宽固定。但 AI 模块不一样,它可能输入是 4 通道的,输出是 1 通道的 feature map。你想想看,这两边要对接,必须定一套双方都认的“契约”。
我个人习惯把接口分成三类:
| 接口类型 | 典型数据 | 位宽/格式 | 同步方式 |
|---|---|---|---|
| 像素级接口 | RAW、RGB、YUV | 8-16bit,Bayer/BGR | 行同步/帧同步 |
| 特征级接口 | Feature Map、权重 | 8-32bit float/int | DMA 完成中断 |
| 控制级接口 | 参数、配置、状态 | 32bit 寄存器 | APB/AXI-Lite |
核心原则:AI 模块的输入输出,必须能“无损”映射回传统 ISP 的像素空间。否则下游模块会直接崩溃。
举个例子。AI 降噪模块输出了一张 feature map,但传统 3A 模块要的是 RGB 图。怎么办?我建议在 AI 模块尾部加一个 Format Converter,把 feature map 转成标准 RGB。这个转换器虽然简单,但它是整个架构的“翻译官”。
我的经验:接口定义时,一定要把 数据有效信号 和 行/帧同步信号 单独拉出来。AI 模块处理延迟不确定,传统模块需要靠这些信号来“等”数据。我曾经因为没做 valid 信号,导致传统模块读到了半帧垃圾数据,画面直接花掉。
4.2 数据流设计:从“串行”到“并行+反馈”
传统 ISP 的数据流是典型的串行管线:RAW → BLC → LSC → AWB → Demosaic → ... → YUV。每个模块处理完,数据才往下走。
但加入 AI 后,数据流就复杂了。我把它归纳为三种模式:
- 前处理模式:AI 模块放在传统管线之前,做 RAW 域的增强(如去噪、HDR 融合)。
- 后处理模式:AI 模块放在传统管线之后,做 RGB/YUV 域的优化(如超分、美颜)。
- 旁路反馈模式:AI 模块从管线中间“偷”数据,处理完再“塞”回去,或者反馈控制传统模块的参数。
我个人最常用的是第三种。为什么呢?因为前两种都会打断传统管线的流水节奏。而旁路模式,AI 模块和传统模块可以并行跑。
来看一个实际的数据流设计:
// 伪代码:AI 旁路降噪模块的数据流
while (frame_ready) {
// 传统管线正常跑
raw_frame = sensor_read();
blc_frame = blc_process(raw_frame);
lsc_frame = lsc_process(blc_frame);
// AI 模块从 LSC 之后“偷”数据
ai_input = lsc_frame;
ai_output = ai_denoise(ai_input); // 异步执行
// 传统管线继续跑,但等待 AI 结果
awb_frame = awb_process(lsc_frame); // 用原始数据先跑 AWB
// AI 结果回来后,替换掉对应区域
final_frame = merge(awb_frame, ai_output);
// 继续后续处理
demosaic_frame = demosaic_process(final_frame);
}
注意:旁路模式最大的坑是 数据对齐。AI 模块处理延迟可能比传统管线多几行甚至几帧。你必须设计一个 Line Buffer 或 Frame Buffer 来缓存传统管线的中间结果,等 AI 模块处理完再合并。否则画面会出现“撕裂”或“错位”。
4.3 实时性约束下的算力分配
这是最头疼的部分。AI 模型算得慢,传统模块算得快,怎么分配才能保证 30fps 甚至 60fps?
我一般按这个步骤来:
- 第一步:算总账。 先算出一帧图像的总处理时间预算。比如 30fps,一帧只有 33ms。传统管线固定占 15ms,留给 AI 的就只有 18ms。
- 第二步:拆模型。 把 AI 模型按层拆开,算每层的计算量(MACs)和访存量。找出瓶颈层。
- 第三步:分优先级。 实时性要求高的模块(如 3A、去噪)优先分配算力;非实时的模块(如美颜、风格迁移)可以降频或丢帧处理。
| 模块 | 计算量 (GMACs) | 延迟预算 (ms) | 分配策略 |
|---|---|---|---|
| 传统 ISP 管线 | 0.5 | 15 | 固定硬件流水线 |
| AI 降噪 (轻量) | 2.0 | 8 | NPU 专用核 |
| AI 超分 (重量) | 15.0 | 10 (可丢帧) | GPU/NPU 共享,动态调度 |
| AI 3A 辅助 | 0.8 | 5 | CPU 轻量推理 |
关键点:算力分配不是静态的。我建议设计一个 动态负载均衡器,根据当前场景的复杂度(如暗光、运动)动态调整 AI 模块的推理精度或帧率。暗光下降噪权重高,超分可以降级;白天反之。
嗯,这里要特别提一下 算力碎片化 的问题。AI 模型推理时,NPU 的利用率往往不是 100%。中间有大量的等待时间(DMA 搬运、算子切换)。我曾经在一个项目里发现,NPU 的实际利用率只有 40%,剩下的时间都在空转。后来我把传统 ISP 的一些轻量计算(如 LSC 插值)塞进了 NPU 的空闲时间片,才把整体帧率提上去。
避坑指南:我曾经为了追求极致画质,把 AI 模型做得很大,结果帧率掉到 15fps。后来学乖了,用 模型剪枝 + 量化 把计算量砍掉 60%,画质只降了 1dB,但帧率回到了 30fps。记住:在实时系统里,完成比完美重要。
4.4 架构总览:一张图说清楚
下面这张图,是我在多个项目里沉淀下来的混合架构参考。它把传统模块、AI 模块、数据流和算力分配都串在了一起。
这张图里,传统管线是“主干道”,AI 模块是“旁路”。数据从主干道分流到 AI 模块,处理完再合并回来。算力分配器在底部统一调度,确保总延迟不超过一帧的时间预算。
再次强调:不要试图让 AI 模块接管所有事情。传统 ISP 的确定性、低延迟、低功耗优势,是 AI 目前无法替代的。混合架构的精髓,是让 AI 做它擅长的事(去噪、超分、语义理解),让传统模块做它擅长的事(3A、色彩校正、伽马)。各司其职,才是王道。