STM32跑YOLOV11实现饮料识别
STM32H7中跑轻量化的YOLOV11,实时检测饮料
在 STM32H7 上跑yolo,实现一个饮料识别小系统
项目简介
这次项目的目标很直接:在一块 STM32H7 MCU 上,完成一个从摄像头采集、端侧推理,到 LCD 实时显示识别结果的完整闭环。
项目最终实现的能力包括:
使用 OV5640 摄像头实时采集画面
在 STM32H7 上部署量化后的目标检测模型
在 1.69 寸 LCD 上实时显示画面、检测框和标签
结合轻量级跟踪策略,降低每一帧都做完整检测的开销
这是在MCU中部署,而非在PC或服务端进行推理,也再次展示了在低成本硬件中跑一些轻量的AI模型的可行性
项目背景
近几年边缘 AI 很热,但很多演示都停留在开发板 Demo、模型 Benchmark,或者依赖更高算力的平台。我更关心的是另一件事:
在严格受限的 MCU 平台上,能不能做出一个真正有交互感、可实时运行的视觉应用。
所以我选择了使用STM32H7,并对YOLOV11进行轻量化改进,以实现能否达到实时检测的要求(常规场景下是要求30FPS)
系统整体方案
flowchart LR
A[OV5640 摄像头] --> B[DCMI + DMA 采集]
B --> C[图像预处理]
C --> D[量化目标检测模型]
D --> E[卡尔曼跟踪]
E --> F[后处理 / NMS]
F --> G[LCD 叠加框与标签]
G --> H[240x280 屏幕显示]
flowchart LR
A[OV5640 摄像头] --> B[DCMI + DMA 采集]
B --> C[图像预处理]
C --> D[量化目标检测模型]
D --> E[卡尔曼跟踪]
E --> F[后处理 / NMS]
F --> G[LCD 叠加框与标签]
G --> H[240x280 屏幕显示]
这里加上后处理与屏幕显示,是为了便于我进行查看,但如果去掉后处理与LCD显示的话,至少能提高6~12fps
模型与部署思路

对于yolov11-n进行了轻量化改进,改进核心思想其实是:1.减少参数;2.减少并行度;3.减少计算复杂度
1. 减少参数
这最直接——权重参数量少了,Flash占用量就下降;如果是激活参数减少,RAM的占用也会同步降低。对于MCU而言,每节省1KB都弥足珍贵。
2. 减少并行度
这一点很容易被忽略。很多轻量化网络(比如ShuffleNet、MobileNetV3)采用了分组卷积或通道混洗,在GPU或NPU上能跑出漂亮的速度,但在单核MCU上,这些并行结构反而会打乱计算流水线,增加调度开销。
所以我不盲目追求“先进轻量结构”,而是优先保证计算路径是顺序、规整的
注意,是减少并行,而不是不能并行,如果增加轻微的并行计算,可以带来明显的计算复杂度降低,也是可以接收的
3. 减少计算复杂度
这是字面意思——对每个算子本身做精简,比如用深度可分离卷积替换普通卷积,减少乘加次数。
在做了上述改造后,模型体积大幅缩减。为了进一步压榨性能,我还做了 INT8量化,并用onnx-sim对计算图做了化简,去掉冗余节点
MCU端的额外工作
1. DMA搬运
摄像头通过DCMI接口采集图像,数据量不小。如果让CPU逐字节搬运,那推理就别想做了。所以必须开启DMA,让图像数据直接搬运到内存缓冲区,CPU只在中断时处理一帧完整的图像
同理,LCD的显存更新也交给DMA2D来完成
2. 卡尔曼滤波
我还额外引入了卡尔曼滤波,实现预测位置变化的功能,以达到模型推理 + 卡尔曼预测交替进行。
先跑一次完整推理得到目标框,然后接下来两帧不跑模型,只用卡尔曼滤波对框的位置做运动预测,下一帧再用模型推理结果来“修正”预测值。这样在常规场景下,实际模型推理的频次降低到原来的1/3,但视觉上依然能跟上目标运动。
这个策略大幅提升了整体帧率,而且对静态或慢速移动的目标效果很好
当前效果
我当前是摄像头采集+模型推理(卡尔曼)+后处理+屏幕展示,并且在屏幕展示的时候,还额外的将原始的192x192的图像放大到了224x224,帧率大约能达到21fps
效果展示
https://www.bilibili.com/video/BV14xJP66Eyv/?vd_source=272d2101ff9417b9c12a0450146ec0ca
如果我去掉将图像放大这一步的操作,帧率是可以达到25fps~28fps,已经接近实时检测的要求了
如果再进一步去掉后处理与屏幕展示,那么是百分百能达到30FPS以上,已经满足普通场景下的实时检测要求了
缺点
当前,缺点还是存在的
过度轻量化加上INT8量化,使得模型在mAP@0.5上还算能看,但mAP@0.95掉得很厉害。这意味着检测框不够精确,对于重叠目标或小目标容易漏检
之前在说轻量化模型时要减少参数,但实际上很难做到在保持一定精度的情况下,将权重参数与激活参数都能减少到很小。因此需要结合具体情况,在不降低精度的情况下优先减少激活参数,其次再想办法减少权重参数