2、基础知识:嵌入式视觉系统组成、内存类型(SRAM/Flash)与容量限制、典型应用场景

在进入 TinyML 内存受限视觉的实战之前,必须先建立对嵌入式视觉系统硬件底座的清晰认知。许多初学者在模型部署阶段遭遇的“内存溢出”“推理卡死”“帧率过低”等问题,根源往往不在于模型本身,而在于对系统组成、内存层次和容量边界缺乏系统性理解。本章将围绕嵌入式视觉系统的三大核心要素——系统组成、内存类型与容量限制、典型应用场景——展开深入剖析,为后续章节中关于输入尺寸、通道数与 Arena 控制的讨论奠定坚实的工程基础。

嵌入式视觉系统组成与内存层次架构 图像采集 摄像头传感器 DVP / MIPI-CSI 分辨率/帧率控制 图像预处理 格式转换 RGB→GRAY 缩放/裁剪/ROI 归一化/量化 推理引擎 TFLite Micro / CMSIS-NN 算子调度/内核执行 Arena 内存管理 后处理与输出 Softmax/阈值判断 结果编码/串口输出 LED/显示屏/控制信号 内存层次结构 SRAM(片上) 容量:几十KB ~ 几MB 存放:模型权重、Arena、中间激活 Flash(片外/片上) 容量:256KB ~ 16MB 存放:模型权重、代码、校准数据 PSRAM / SDRAM(可选) 容量:2MB ~ 64MB 存放:大图像帧缓冲、临时数据 关键约束与瓶颈 • 模型权重存储:Flash 容量决定可部署模型大小上限 • 推理运行内存:SRAM 容量决定 Arena 可用空间,直接影响输入尺寸与通道数 • 帧缓冲占用:输入图像分辨率 × 通道数 × 字节深度 = 单帧内存消耗

上图展示了嵌入式视觉系统的完整数据流与内存层次关系。从图像采集到后处理输出,每个环节都在与内存打交道。理解这条链路中数据如何流动、存储在哪里、何时被释放,是掌握 TinyML 内存优化的第一步。下面我们将逐一拆解每个组成部分的职责与内存特征。

2.1 嵌入式视觉系统的四大核心组成

一个典型的嵌入式视觉系统由图像采集、预处理、推理引擎、后处理输出四个模块构成。每个模块对内存的需求模式截然不同,理解这些差异是进行内存规划的前提。

2.1.1 图像采集模块

图像采集模块负责从物理世界中捕获视觉信息。主流方案包括:

  • DVP(Digital Video Port)并行接口:常见于低成本的 OV7670、OV2640 等传感器,通过 8/10 位并行数据线传输,占用 GPIO 较多,但时序简单。
  • MIPI-CSI 串行接口:用于更高分辨率的传感器(如 OV5640、IMX219),差分信号传输,抗干扰能力强,但需要 MCU 内置 MIPI 控制器。

采集模块的内存消耗主要体现在帧缓冲(Frame Buffer)上。例如,一个 QVGA(320×240)的 RGB565 图像,单帧占用 320×240×2 = 153,600 字节 ≈ 150KB。如果使用双缓冲(Ping-Pong 机制),则需 300KB。对于 SRAM 仅有 256KB 的 MCU 来说,这已经占据了绝大部分可用内存。因此,输入尺寸的选择直接受限于帧缓冲的分配策略。

2.1.2 图像预处理模块

预处理模块负责将原始图像转换为模型可接受的输入格式。典型操作包括:

  1. 格式转换:RGB565 → RGB888 → GRAY(灰度),减少通道数以降低计算量。
  2. 几何变换:缩放(Resize)、裁剪(Crop)、旋转(Rotate),用于对齐模型输入尺寸。
  3. 数值归一化:将像素值从 [0, 255] 映射到 [0, 1] 或 [-1, 1],或直接进行 uint8 量化。

预处理的内存开销通常为临时缓冲区。例如,将 320×240 的 RGB565 转换为 96×96 的灰度图,中间需要至少一个 96×96×1 = 9,216 字节的临时数组。如果预处理步骤过多,每个步骤都需要独立的缓冲区,内存碎片化问题就会显现。在实际工程中,推荐采用原地操作(In-place)或单缓冲区复用策略,将多个预处理步骤合并到同一块内存区域。

2.1.3 推理引擎模块

推理引擎是 TinyML 系统的核心计算单元。以 TensorFlow Lite for Microcontrollers(TFLite Micro)为例,其内存模型包含三个关键区域:

  • 模型权重区:存储在 Flash 中,只读,不占用 SRAM。例如 MobileNetV1 的 96×96×3 输入版本,权重约 1.8MB,需要 2MB 以上的 Flash。
  • Tensor Arena:这是 SRAM 中最重要的动态内存区域,用于存放中间激活值、临时张量和推理过程中的所有动态数据。Arena 的大小直接决定了模型能否成功部署。
  • 算子工作区:某些算子(如卷积、深度可分离卷积)需要额外的临时缓冲区,这些也在 Arena 中分配。

推理引擎的内存消耗与输入尺寸、通道数呈非线性关系。例如,一个 3×3 卷积层,输入特征图 32×32×16,输出 32×32×32,其激活值内存为 32×32×32 = 32,768 字节。如果输入尺寸翻倍到 64×64,激活值变为 64×64×32 = 131,072 字节,增长了 4 倍。这就是为什么输入尺寸是内存优化的第一杠杆。

2.1.4 后处理与输出模块

后处理模块将推理结果转换为可执行的决策。常见操作包括:

  • Softmax 归一化:将 logits 转换为概率分布,需要临时存储所有类别的概率值。
  • 阈值判断:例如检测到目标时输出 1,否则输出 0。
  • 结果编码:将分类结果编码为 UART 串口数据、LED 控制信号或显示屏刷新数据。

后处理的内存需求通常较小(几 KB 以内),但需要注意输出缓冲区的生命周期管理。如果后处理需要保留多帧结果(例如滑动窗口平均),则需额外分配历史结果缓冲区。

2.2 内存类型与容量限制深度解析

嵌入式系统的内存类型直接决定了数据存储的持久性和访问速度。下表对比了三种主要内存类型的特性:

内存类型 典型容量 访问速度 掉电保持 主要用途 成本特征
SRAM(片上) 16KB ~ 1MB 极快(单周期) 否 运行时数据、Arena、栈、堆 高(每 KB 成本最高)
Flash(片上/片外) 256KB ~ 16MB 慢(读 50-100ns) 是 代码、模型权重、只读数据 中
PSRAM/SDRAM(片外) 2MB ~ 64MB 中等(需刷新) 否 大帧缓冲、扩展内存池 低(每 MB 成本低)

在 TinyML 视觉任务中,SRAM 是最稀缺的资源。以 STM32F746 系列为例,其 SRAM 容量为 320KB,Flash 为 1MB。这意味着:

  • 模型权重必须存放在 Flash 中,且不能超过 1MB(实际可用约 800KB,需留出代码空间)。
  • Arena 大小不能超过 320KB,且需要与帧缓冲、预处理缓冲区共享这 320KB。
  • 如果输入图像为 96×96×3(RGB),单帧原始数据为 27,648 字节,加上预处理临时缓冲区,留给 Arena 的空间可能只剩 200KB 左右。
关键风险提示:许多开发者在选择 MCU 时只关注 Flash 容量,而忽略了 SRAM 的限制。一个 2MB 的模型权重可以轻松放入 4MB Flash 的芯片,但如果 SRAM 只有 256KB,Arena 可能无法容纳推理所需的中间激活值,导致部署失败。务必在选型阶段同时评估 Flash 和 SRAM 的容量。

2.3 典型应用场景与内存需求特征

不同的应用场景对内存的需求模式差异显著。下表总结了三种典型场景的内存特征:

应用场景 输入尺寸 模型大小 SRAM 需求 帧率要求 典型 MCU 选型
关键词唤醒(KWS) 10×10×1(MFCC) 50-200KB 30-80KB 实时(<100ms) Cortex-M4 @ 100MHz
图像分类(简单物体) 32×32×3 ~ 96×96×3 200KB-1MB 100-250KB 1-10 FPS Cortex-M7 @ 400MHz
物体检测(人脸/行人) 128×128×3 ~ 192×192×3 1-3MB 300KB-1MB 0.5-5 FPS Cortex-M7 + PSRAM

2.3.1 场景一:低功耗智能门铃

一个典型的智能门铃需要实现“人形检测”功能,要求在 1 秒内完成一次推理,且平均功耗低于 10mW。系统约束如下:

  • MCU:STM32L4 系列,SRAM 128KB,Flash 512KB。
  • 摄像头:QVGA(320×240)灰度传感器,输出 8-bit 灰度图。
  • 模型:MobileNetV1 96×96×1 输入,权重 400KB(Flash),Arena 需求 80KB。

内存分配方案:

SRAM 分配(总计 128KB):
- 帧缓冲(单缓冲):320×240×1 = 76,800 字节 ≈ 75KB
- 预处理临时区:96×96×1 = 9,216 字节 ≈ 9KB
- Tensor Arena:80KB
- 栈 + 堆 + 系统保留:约 20KB
- 总计:75 + 9 + 80 + 20 = 184KB > 128KB ❌

上述方案超出 SRAM 容量,必须优化。优化策略:

  1. 降低采集分辨率:将摄像头配置为 160×120(QQVGA),帧缓冲降至 160×120×1 = 19,200 字节 ≈ 19KB。
  2. 直接缩放采集:部分传感器支持硬件缩放,直接输出 96×96 灰度图,帧缓冲进一步降至 9,216 字节。
  3. 调整 Arena 分配:通过模型量化(int8)将 Arena 需求从 80KB 降至 50KB。

优化后:9,216 + 9,216 + 50,000 + 20,000 ≈ 88KB,满足 128KB 限制,且留有 40KB 余量。

2.3.2 场景二:工业视觉缺陷检测

在工业质检场景中,需要在传送带上检测产品表面的划痕。系统要求:

  • 分辨率:128×128 RGB 输入,以捕捉细微缺陷。
  • 检测精度:F1 分数 ≥ 0.95。
  • 节拍:每件产品检测时间 ≤ 200ms。

该场景的内存挑战在于:128×128×3 的输入意味着单帧数据为 49,152 字节(RGB888),如果使用 RGB565 则为 32,768 字节。模型选择 MobileNetV2 128×128×3,权重约 1.2MB(Flash),Arena 需求约 180KB。此时需要选择带有 PSRAM 的 MCU(如 STM32H747 或 i.MX RT1062),将帧缓冲放在 PSRAM 中,SRAM 仅用于 Arena 和关键路径数据。

工程经验:当 SRAM 不足时,优先考虑将帧缓冲迁移到 PSRAM。因为帧缓冲的访问模式是顺序读写,PSRAM 的随机访问延迟虽然高于 SRAM,但顺序访问性能接近。而 Arena 中的激活值访问模式是随机的,必须保留在 SRAM 中以保证推理速度。

2.4 常见误区与设计复盘

在嵌入式视觉系统的内存规划中,以下误区最为常见:

误区一:只关注模型大小,忽略激活值内存

许多开发者认为“模型权重 300KB,Flash 有 1MB,肯定够用”。但实际部署时发现 Arena 需要 150KB,而 SRAM 只有 128KB,导致无法运行。激活值内存与输入尺寸、通道数直接相关,必须提前估算。

误区二:帧缓冲使用双缓冲,导致内存翻倍

双缓冲(Ping-Pong)可以提高采集与处理的并行度,但代价是内存翻倍。在 TinyML 场景中,如果推理时间小于帧间隔,单缓冲 + 等待机制通常足够。只有在需要持续采集且推理时间接近帧间隔时,才考虑双缓冲。

误区三:忽略预处理临时缓冲区

预处理步骤(如缩放、格式转换)需要临时存储中间结果。如果每个步骤都分配独立缓冲区,内存碎片化会非常严重。推荐使用内存池复用技术,将多个预处理步骤的临时缓冲区合并为一块。

复盘总结

本章的核心结论可以归纳为以下三点:

  1. 系统组成决定内存分布:采集、预处理、推理、后处理四个模块各自的内存需求模式不同,需要统一规划。
  2. SRAM 是硬约束:Flash 容量决定模型大小上限,但 SRAM 决定能否运行。选型时必须同时评估两者。
  3. 输入尺寸是第一优化杠杆:将输入从 128×128 降至 96×96,激活值内存可减少约 44%,这是最直接有效的内存优化手段。