3、图像分类基础:图像表示、像素、通道、卷积神经网络(CNN)核心概念

在进入 Person Detection 示例项目之前,必须先建立图像数据在计算机中的底层表示方式,以及卷积神经网络(CNN)如何从原始像素中提取语义特征。TFLite Micro 运行在内存以 KB 计算的 MCU 上,理解图像张量的形状、通道含义与 CNN 的运算本质,是后续裁剪模型、量化参数、调试推理结果的前提。本节将系统梳理从像素到特征图的完整链路,并指出在嵌入式环境下最容易踩中的理解误区。

图像张量 → CNN 特征提取 → 分类输出 输入图像 96×96×3 (高×宽×通道) RGB 各 8bit ≈ 27,648 字节 卷积层 1 Conv2D 3×3 8 个滤波器 输出: 48×48×8 ReLU + MaxPool 参数量: 216+8 卷积层 2 Conv2D 3×3 16 个滤波器 输出: 24×24×16 ReLU + MaxPool 参数量: 1152+16 全连接 + Softmax Flatten: 24×24×16 = 9216 维 输出: 2 类 (person / no-person) 参数量: 18432+2 分类结果 person: 0.87 原始像素 边缘/纹理 局部形状 全局语义 关键内存估算(以 int8 量化后为例) 输入: 96×96×3 = 27,648 B | 特征图1: 48×48×8 = 18,432 B | 特征图2: 24×24×16 = 9,216 B 权重: 约 2 KB | 总激活内存峰值 ≈ 55 KB(不含临时缓冲区)→ 适合 256 KB SRAM 的 MCU

3.1 图像在计算机中的张量表示

数字图像不是人类看到的"画面",而是一个多维数值数组。对于 Person Detection 使用的 RGB 图像,其本质是一个 三维张量,形状记为 (height, width, channels)。高度和宽度以像素为单位,通道数在 RGB 色彩空间中为 3,分别对应红、绿、蓝三个颜色分量的亮度值。每个像素的每个通道通常用 8 位无符号整数表示,取值范围 0~255。0 代表该通道无亮度,255 代表最大亮度。

以 TFLite Micro 的 Person Detection 模型为例,输入张量通常被设计为 96×96×3。这意味着模型期望接收一张宽 96 像素、高 96 像素、含 RGB 三通道的彩色图像。在内存中,这 27,648 个字节按特定顺序排列(通常为 HWC 或 CHW 布局,TFLite 默认使用 HWC)。当图像从摄像头传感器(如 Himax HM01B0)输出时,通常是灰度图或 Bayer 格式,需要经过预处理转换为模型期望的 RGB 张量。

关键理解: 图像分类的输入不是"图片文件",而是内存中的数值张量。TFLite Micro 的 interpreter 通过 tensor->data.uint8 指针直接访问这块内存。在嵌入式端,图像采集、格式转换、缩放、归一化这些操作必须在送入模型前完成,且每一步都消耗宝贵的 CPU 周期和内存带宽。

3.2 像素与通道的物理意义

像素是图像的最小采样单元。在灰度图中,一个像素只有一个亮度值;在 RGB 图中,一个像素由三个通道值共同决定颜色。通道的分离与组合构成了色彩模型的基础。对于 Person Detection 任务,颜色信息并非总是必要的——人体轮廓、边缘、纹理等结构特征在灰度图中同样显著。因此,许多嵌入式视觉模型会先将 RGB 图像转换为灰度图,将通道数从 3 降为 1,从而减少 2/3 的输入数据量。

但通道数减少并非没有代价。颜色信息在特定场景下具有判别力,例如区分穿红色衣服的人和背景中的红色物体。TFLite Micro 的 Person Detection 模型选择保留 RGB 三通道,是因为其预训练模型在 Visual Wake Words 数据集上使用彩色图像训练,直接使用灰度输入会导致精度下降。在工程实践中,是否降通道需要结合模型训练时的输入规格决定,不能随意更改。

图像类型张量形状单帧内存适用场景
灰度图96×96×19,216 B低功耗、边缘检测、轮廓识别
RGB 图96×96×327,648 B彩色目标识别、视觉唤醒词
RGBA 图96×96×436,864 B需要透明度信息(嵌入式少见)
YUV42096×96×1.513,824 B摄像头原生输出格式

3.3 卷积神经网络的核心运算机制

CNN 之所以适合图像分类,是因为它通过局部感受野和权值共享两大设计,大幅减少了参数量,同时保留了空间结构信息。卷积层使用一个小尺寸的滤波器(如 3×3)在输入特征图上滑动,每次计算滤波器覆盖区域内的加权和,再加上偏置项,得到输出特征图的一个像素值。

以 Person Detection 模型的第一层卷积为例:输入为 96×96×3,使用 8 个 3×3×3 的滤波器(每个滤波器深度必须与输入通道数一致),步长为 1,padding 为 SAME,则输出特征图尺寸为 96×96×8。每个滤波器负责提取一种特征,例如水平边缘、垂直边缘、颜色块等。8 个滤波器叠加,形成 8 张特征图,每张特征图对应一种特征响应。

// 卷积运算伪代码(单输出像素)
for (int c_out = 0; c_out < num_filters; c_out++) {
  float sum = bias[c_out];
  for (int c_in = 0; c_in < input_channels; c_in++) {
    for (int kh = 0; kh < kernel_h; kh++) {
      for (int kw = 0; kw < kernel_w; kw++) {
        int ih = h + kh - pad_h;
        int iw = w + kw - pad_w;
        if (ih >= 0 && ih < input_h && iw >= 0 && iw < input_w) {
          sum += input[ih][iw][c_in] * weight[c_out][kh][kw][c_in];
        }
      }
    }
  }
  output[h][w][c_out] = activation(sum);
}

卷积层之后通常紧跟激活函数(ReLU)和池化层(MaxPool)。ReLU 将负值置零,引入非线性;MaxPool 在 2×2 窗口内取最大值,将特征图尺寸减半,同时保留最显著的特征响应。经过两次"卷积+池化"后,特征图从 96×96×3 变为 24×24×16,空间分辨率降低,但通道数增加,表示的是更高层次的语义特征。

3.4 从特征图到分类输出:全连接层与 Softmax

经过多层卷积和池化后,特征图需要被"展平"为一维向量,送入全连接层进行最终分类。在 Person Detection 模型中,最后一层特征图尺寸为 24×24×16,展平后得到 9,216 个值。全连接层将这 9,216 个值映射到 2 个输出节点,分别对应"person"和"no-person"两个类别。

Softmax 函数将全连接层的原始输出(logits)转换为概率分布,使得两个类别的输出值之和为 1。例如,模型可能输出 person: 0.87、no-person: 0.13,表示模型认为图像中有人的概率为 87%。在 TFLite Micro 中,由于使用 int8 量化,Softmax 通常通过查表或近似计算实现,以避免浮点运算。

嵌入式优化提示: 在 MCU 上,Softmax 的指数运算非常耗时。TFLite Micro 的 int8 Softmax 使用预先计算的查找表(LUT),将输入范围映射到 256 个离散值,牺牲少量精度换取数十倍的性能提升。理解这一点有助于调试量化模型的输出概率。

3.5 案例拆解:96×96 输入在 TFLite Micro 中的内存足迹

以 Arduino Nano 33 BLE Sense(配备 256 KB SRAM)运行 Person Detection 模型为例,我们来估算内存占用。该模型包含 2 个卷积层、2 个池化层和 1 个全连接层,总参数量约 2,000 个(int8 量化后约 2 KB)。但激活内存(即中间特征图)才是主要消耗者。

  1. 输入张量: 96×96×3 = 27,648 B,由摄像头 DMA 直接写入。
  2. 第一层输出: 48×48×8 = 18,432 B(经过 2×2 MaxPool 后尺寸减半)。
  3. 第二层输出: 24×24×16 = 9,216 B(再次池化)。
  4. 全连接输入: 展平后 9,216 个 int8 值,与第二层输出共用内存。
  5. 临时缓冲区: 卷积运算需要额外的行缓冲区,约 2~4 KB。

峰值内存出现在第一层卷积计算时,需要同时保存输入、输出和临时缓冲区,总计约 50 KB。加上权重、偏置、解释器开销和堆栈,总占用约 80~100 KB,在 256 KB SRAM 的 MCU 上可以安全运行。如果改用 160×160 输入,内存需求将增长约 2.8 倍,可能超出 MCU 容量,这就是为什么嵌入式模型必须限制输入分辨率。

常见误区: 初学者常认为"模型参数量小 = 内存占用小"。实际上,激活内存往往远大于权重内存。在 TFLite Micro 中,arena_size 的配置主要取决于激活张量的大小,而非模型文件大小。如果遇到 arena allocation failed 错误,优先检查输入分辨率和通道数,而不是模型参数量。

3.6 常见误区与总结复盘

在图像分类基础的学习中,以下误区最为常见:

  • 混淆图像分辨率与模型输入尺寸: 摄像头输出 320×240,但模型输入是 96×96,必须进行缩放。缩放算法(双线性插值 vs 最近邻)会影响边缘质量,进而影响分类精度。
  • 忽略通道顺序: TFLite 默认使用 RGB 顺序,但部分摄像头驱动输出 BGR。通道顺序颠倒会导致模型输出完全错误的结果,且难以排查。
  • 认为池化层是必须的: 现代 CNN 有时用步长大于 1 的卷积替代池化。TFLite Micro 的 Person Detection 模型使用池化是为了降低计算量,但并非所有模型都如此。
  • 忽视量化对特征值的影响: int8 量化后,特征图的数值范围被压缩到 -128~127,ReLU 的截断行为与浮点版本略有差异。调试时不能直接对比浮点模型和量化模型的中间特征值。

总结而言,图像分类的底层逻辑是:像素张量 → 卷积提取局部特征 → 池化降维 → 全连接聚合全局信息 → Softmax 输出概率。在 TFLite Micro 环境中,每一步都受到内存和算力的双重约束。理解这些基础概念,是后续进行模型裁剪、量化调优和硬件部署的基石。建议读者在开发板上实际打印输入张量和第一层卷积输出的数值,建立对特征图的直观感知,这将极大加速对 CNN 工作原理的理解。