目标检测
概述
在上一节关于计算机视觉(CV)与 XIAO ESP32S3 的 图像分类 实验中,我们学习了如何用这款出色的开发板进行图像分类。本节将继续 CV 之旅,探索微控制器上的目标检测。
目标检测 vs 图像分类
图像分类模型的主要任务是识别图片中最可能出现的物体类别,例如区分猫和狗,即判断图片中占主导地位的“对象”:

但如果图片中没有明显的主导类别会怎样?

如上图,图像分类模型会错误地将其识别为“ashcan”(垃圾桶),可能是因为颜色相近。
上述模型为 MobileNet,基于大规模数据集 ImageNet 训练,在树莓派上运行。
为解决此问题,我们需要另一类模型,不仅能识别多个类别(标签),还要知道这些物体在图片中的具体位置。
显然,这类模型更复杂、更庞大。例如,MobileNetV2 SSD FPN-Lite 320x320(COCO 数据集训练),可在一张图片中定位最多 10 个物体,并输出每个物体的边界框。下图为该模型在树莓派上的推理结果:

用于目标检测的模型(如 MobileNet SSD、YOLO)通常体积较大(数 MB),适合树莓派等设备,但不适合如 XIAO ESP32S3 这类 RAM 仅几 MB 的嵌入式设备。
目标检测创新方案:FOMO
Edge Impulse 于 2022 年推出了 FOMO(Faster Objects, More Objects) ,为嵌入式设备(如 Nicla Vision、Portenta、Cortex M4F、ESP32 系列等)带来了高效目标检测能力。
本节将通过实践项目,体验基于 FOMO 的目标检测。
想深入了解 FOMO,可阅读 Edge Impulse 官方 FOMO 公告 ,Louis Moreau 和 Mat Kelcey 详细介绍了其原理。
项目目标
所有机器学习项目都需明确目标。假设我们在工业或农业场景,需要对**橙子(水果)和特定青蛙(虫子)**进行分拣与计数。

即需实现多标签分类,每张图片包含三类:
- 背景(无物体)
- 水果
- 虫子
以下为部分未标注样本图,用于检测水果和虫子:

我们关注图片中有哪些物体、它们的位置(质心)以及数量。FOMO 不检测物体尺寸(不像 MobileNet SSD 或 YOLO 输出边界框),只输出质心坐标。
本项目将用 XIAO ESP32S3 采集图像并进行模型推理,ML 流程在 Edge Impulse Studio 完成。在 Studio 开始目标检测项目前,需先采集包含目标物体的原始数据集(未标注)。
数据采集
可用 XIAO、手机或其他设备采集图片。此处以 XIAO + Arduino IDE ESP32 库为例。
用 XIAO ESP32S3 采集数据集
打开 Arduino IDE,选择 XIAO_ESP32S3 板卡与端口。依次进入 File > Examples > ESP32 > Camera,选择 CameraWebServer。
在板卡管理器确认已安装最新“稳定版”包。
⚠️ 注意
Alpha 版(如 3.x-alpha)与 XIAO、Edge Impulse 兼容性差,建议用最新稳定版(如 2.0.11)。
仅保留 XIAO 型号摄像头定义:
#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM
在 Tools 启用 PSRAM,填写 WiFi 信息并上传代码:

代码运行后,串口监视器会显示设备地址:

浏览器访问该地址,选择分辨率(如 QVGA),点击 [START STREAM],即可实时预览。点击 [Save] 可保存图片到电脑。

Edge Impulse 建议:为获得更好效果,物体应大小相近且不重叠。工业场景下摄像头固定,距离一致即可。也可尝试不同大小和位置,观察效果。
不必为每类物体单独建文件夹,每张图片可含多个标签。
建议采集约 50 张图片,混合不同物体,变化角度、背景和光照。
存储图片为 QVGA($320\times 240$),RGB565 格式。
采集完毕后,点击 [Stop Stream],将图片整理到文件夹。
Edge Impulse Studio
项目初始化
访问 Edge Impulse Studio ,登录或注册账号,新建项目。

可克隆本节项目: XIAO-ESP32S3-Sense-Object_Detection
在 Project Dashboard 下方 Project info 选择 Bounding boxes (object detection),目标设备选 Espressif ESP-EYE(与本板最接近)。

上传未标注数据
在 Studio 的 Data acquisition 标签页,UPLOAD DATA 区域上传采集的图片文件夹。

可让 Studio 自动划分训练/测试集,也可手动。此处全部作为训练集上传。

所有未标注图片(47 张)上传后,需标注后才能用作数据集。Studio 提供标注工具,点击 Labeling queue(47)。
Edge Impulse Studio(免费版)支持两种 AI 辅助标注方式:
- yolov5 预训练模型
- 帧间目标跟踪
Edge Impulse 企业版支持 自动标注功能 。
常见物体可用 YOLOv5(COCO 数据集)自动标注。但本例物体不在 COCO 数据集,应选目标跟踪:在一帧手动框选并标注后,后续帧自动跟踪(部分自动标注,需人工校正)。
若已有带边界框的数据集,可用 EI uploader 导入。
标注数据集
从未标注数据的首张图片开始,用鼠标框选目标并添加标签,点击 Save labels 进入下一张。

重复操作直至队列清空。最终所有图片应如样例所示完成标注:

在 Data acquisition 标签页复查标注样本。如有错误,可用三点菜单编辑:

进入编辑界面修正标签:

数据集平衡与划分训练/测试集
标注后发现 fruit 类样本远多于 bug 类。补充采集 11 张 bug 图片(共 58 张),标注后将部分图片划为测试集(如 6 张,占总数 13%),用三点菜单操作。

Impulse 设计
本阶段需定义:
- 预处理:将图片从 $320\times 240$ 缩放至 $96\times 96$,保持比例(不裁剪),再转为灰度图。
- 模型设计:选择“Object Detection”。

数据集预处理
选择 Color depth 为 Grayscale(灰度),适合 FOMO 模型,保存参数。

Studio 自动进入 Generate features,所有样本预处理后生成 $96\times 96\times 1$ 图像(9216 特征)。

特征可视化显示样本分布良好。
个别样本分布异常,点击可确认标签无误。
模型设计、训练与测试
本项目采用 FOMO,基于 MobileNetV2(alpha 0.35),将图片粗分为背景与目标对象(如 box、wheel)。
FOMO 是创新型目标检测模型,能耗与内存消耗比传统 SSD/YOLO 低 30 倍,可在 <200 KB RAM 的微控制器上运行。其原理是仅输出目标质心坐标,不输出边界框。
FOMO 工作原理
FOMO 将灰度图按 8 像素分块,$96\times 96$ 输入对应 $12\times 12$ 网格。每个像素块用分类器判断是否含目标(box/wheel),概率最高的区域输出为目标质心。无目标则判为背景。

训练时选用 FOMO MobileNetV2 0.35 预训练模型,约 250 KB RAM、80 KB ROM,适合本板。

训练超参数:
- Epochs: 60
- Batch size: 32
- Learning Rate: 0.001
训练集 80%(含数据增强:翻转、缩放、亮度、裁剪),验证集 20%。最终模型 F1 分数 85%,测试集 83%。
FOMO 自动为 box、wheel 增加第三类 background。

目标检测常用 F1 分数而非准确率,因其需同时分类与定位。FOMO 仅输出质心,无边界框,准确率不全面,F1 更合理。
Live Classification 测试
模型训练完成后,可用 Live Classification 工具测试。点击开发板图标,手机扫码连接。

手机采集图片,实时测试模型推理效果。

注意模型可能有误报、漏报。可通过调整置信度阈值(建议 0.8 以上)优化。
模型部署(Arduino IDE)
选择 Arduino Library、Quantized (int8) 模型,Deploy Tab 启用 EON Compiler,点击 [Build]。

在 Arduino IDE Sketch > Include Library > Add .ZIP Library 导入下载的库。

在 Examples 下找到项目名下的 esp32 > esp32_camera 示例。

将 32~75 行摄像头型号与引脚定义替换为:
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 10
#define SIOD_GPIO_NUM 40
#define SIOC_GPIO_NUM 39
#define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 11
#define Y7_GPIO_NUM 12
#define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 16
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 17
#define Y2_GPIO_NUM 15
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 47
#define PCLK_GPIO_NUM 13
效果如下:

上传至 XIAO ESP32S3 Sense,即可开始检测水果与虫子。串口监视器可查看推理结果。
背景

水果

虫子

模型延迟 143 ms,帧率约 7 fps(与图像分类项目相近)。FOMO 基于 CNN,非传统 SSD MobileNet 目标检测模型。例如,树莓派 4 跑 MobileNetV2 SSD FPN-Lite $320\times 320$ 延迟约 1.5 fps,慢 5 倍。
模型部署(SenseCraft-Web-Toolkit)
如图像分类章节所述,Arduino IDE 下难以直观查看摄像头画面。推荐用 SenseCraft-Web Toolkit。
操作步骤:
连接 XIAO 至电脑:
- 选择设备:

图 33: 选择设备界面 - 选择端口,点击
[Connect]:

图 34: 端口选择界面 可体验 Seeed Studio 预置的多种视觉模型,欢迎尝试。
本例需点击页面底部蓝色按钮
[Upload Custom AI Model]。先从 Edge Impulse Studio 下载 量化 .tflite 模型。
进入 Edge Impulse Studio 项目,或克隆:
在
Dashboard下载模型(block output):Object Detection model - TensorFlow Lite (int8 quantized)
图 35: 模型下载界面 在 SenseCraft-Web-Toolkit,点击蓝色按钮
[Upload Custom AI Model],弹窗中上传模型文件,填写模型名与标签(ID: Object):
图 36: 上传自定义模型界面
标签顺序需与 EI Studio 训练一致,按字母顺序填写(如 background, bug, fruit)。
上传后,摄像头实时画面与检测结果显示于 Preview 区域:

检测到的物体会标记质心。可调整推理置信度 Confidence 和 IoU(评估预测框与真实框重叠度)。
点击顶部 Device Log 可打开串口监视器,查看推理日志。

Device Log 信息示例:
- 预处理时间(图像采集与裁剪):3 ms
- 推理时间(模型延迟):115 ms
- 后处理时间(显示与标记):1 ms
- 输出张量(boxes),如 [[30,150, 20, 20,97, 2]],含坐标、置信度、类别
如上例,5 个框中有 3 个质心为水果。可通过后处理聚合相近质心。
更多截图:

总结
FOMO 是图像处理领域的重要突破,正如 Louis Moreau 和 Mat Kelcey 在 2022 年发布时所说:
FOMO 是首个将实时目标检测、跟踪与计数带到微控制器的开创性算法。
在嵌入式设备上探索目标检测(尤其是计数)有无限可能。