YOLO12模型在STM32嵌入式系统上的轻量化部署
本文介绍了如何在星图GPU平台上自动化部署YOLO12 目标检测模型 WebUI镜像,实现高效的目标检测任务。该平台简化了部署流程,用户可快速搭建基于YOLO12的检测环境,并将其应用于智能安防监控、实时视频分析等场景,提升开发与部署效率。
YOLO12模型在STM32嵌入式系统上的轻量化部署
最近在做一个智能门铃的项目,需要实时检测门口的人脸和包裹。一开始想着用树莓派跑个YOLO模型应该没问题,结果算了下成本,一个树莓派加上摄像头模块要小一千,这还没算电源和外壳。后来琢磨着,能不能用更便宜的方案?STM32这种几十块钱的芯片行不行?
说实话,刚开始我也觉得不太可能。STM32那点内存和算力,跑个简单的图像处理都费劲,更别说YOLO这种深度学习模型了。但查了一圈资料,发现还真有人在做这方面的尝试,特别是YOLO12出来之后,它的轻量化版本在边缘设备上的表现让人眼前一亮。
今天就跟大家分享一下,怎么把YOLO12这个大家伙“塞进”STM32里,让几十块钱的芯片也能跑目标检测。
1. 为什么要在STM32上跑YOLO12?
你可能要问,现在有那么多边缘计算设备,为啥非要跟STM32过不去?其实原因很简单:成本和功耗。
我手头有个项目,需要做一批智能农业传感器,监测果园里的果实成熟度和病虫害。如果用树莓派,一个设备成本就要好几百,而且功耗高,得经常充电或者拉电线。如果用STM32,芯片本身几十块钱,加上外围电路也就一百出头,用电池能跑好几个月。
但STM32的硬件限制也很明显:
- 内存小:常见的STM32F4系列只有192KB RAM,STM32H7好一些,也就1MB左右
- 算力有限:主频一般在几百MHz,没有专用的神经网络加速器
- 存储空间小:Flash通常几MB到几十MB
YOLO12相比之前的版本,在轻量化方面做了不少优化。它的区域注意力机制减少了计算量,R-ELAN结构让网络更稳定,而且支持多种模型尺寸。最小的YOLO12n只有几MB,经过量化后还能进一步压缩。
2. 准备工作:选对硬件和工具
2.1 硬件选择
不是所有STM32都能跑YOLO12。根据我的经验,至少要满足这几个条件:
STM32H7系列是首选,比如STM32H743、STM32H750。这些芯片有:
- 主频400MHz以上
- 1MB以上的RAM
- 带硬件浮点单元(FPU)
- 有些型号还有Chrom-ART加速器
STM32F7系列也可以考虑,比如STM32F767,但性能会差一些。
摄像头模块选OV2640或者OV5640都可以,30万像素够用了,分辨率太高反而处理不过来。
屏幕可选可不选,如果只是做检测不显示,用串口输出结果就行。
2.2 软件工具链
- STM32CubeMX:配置芯片引脚和时钟
- STM32CubeIDE或者Keil MDK:开发环境
- STM32Cube.AI:关键工具,能把训练好的模型转换成STM32能跑的代码
- OpenMV(可选):如果不想从头写摄像头驱动,可以用它的库
3. 模型准备:从YOLO12到STM32能用的格式
这一步是最关键的,得把YOLO12模型“瘦身”到STM32能承受的大小。
3.1 选择模型尺寸
YOLO12有5个版本:n、s、m、l、x。对STM32来说,只能选YOLO12n,这是最小的版本,参数量最少。
# 下载YOLO12n预训练模型
from ultralytics import YOLO
# 加载模型
model = YOLO('yolo12n.pt')
# 查看模型信息
print(f"参数量: {sum(p.numel() for p in model.parameters())}")
print(f"模型大小: {sum(p.numel() * p.element_size() for p in model.parameters()) / 1024 / 1024:.2f} MB")
运行后会看到,YOLO12n原始模型大概6-7MB。这听起来不大,但对STM32来说还是太大了。
3.2 模型量化
量化就是把模型的浮点数权重转换成整数,能大幅减小模型体积。
# 导出为ONNX格式并量化
model.export(
format='onnx',
imgsz=320, # 输入尺寸缩小到320x320
half=True, # 使用半精度浮点数
int8=True, # 开启INT8量化
data='coco.yaml'
)
量化后模型能缩小到1-2MB,有些还能到几百KB。但要注意,量化会损失一些精度,需要测试效果能不能接受。
3.3 使用STM32Cube.AI转换
STM32Cube.AI是ST官方提供的工具,能把TensorFlow、PyTorch、ONNX等格式的模型转换成C代码。
转换步骤:
- 在STM32CubeMX里安装X-Cube-AI扩展包
- 导入量化后的ONNX模型
- 选择优化级别(平衡内存和速度)
- 生成C代码
生成后的代码会包含:
- 模型权重(已经转换成数组)
- 推理函数
- 内存管理
4. 在STM32上部署
4.1 硬件初始化
先配置好摄像头和显示(如果有的话):
// 初始化摄像头
void Camera_Init(void) {
DCMI_HandleTypeDef hdcmi;
I2C_HandleTypeDef hi2c;
// DCMI配置
hdcmi.Instance = DCMI;
hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
// ... 其他配置
// I2C配置(用于摄像头寄存器设置)
hi2c.Instance = I2C1;
hi2c.Init.ClockSpeed = 400000;
// ... 其他配置
HAL_DCMI_Init(&hdcmi);
HAL_I2C_Init(&hi2c);
// 初始化OV2640
OV2640_Init();
}
4.2 图像预处理
YOLO需要输入固定尺寸的图像(比如320x320),但摄像头可能是640x480。需要先缩放:
// 图像缩放函数
void Image_Resize(uint8_t *src, uint8_t *dst,
int src_width, int src_height,
int dst_width, int dst_height) {
float scale_x = (float)src_width / dst_width;
float scale_y = (float)src_height / dst_height;
for (int y = 0; y < dst_height; y++) {
for (int x = 0; x < dst_width; x++) {
int src_x = (int)(x * scale_x);
int src_y = (int)(y * scale_y);
dst[y * dst_width + x] = src[src_y * src_width + src_x];
}
}
}
4.3 运行推理
用STM32Cube.AI生成的函数来推理:
#include "network.h" // STM32Cube.AI生成的头文件
void Run_Inference(uint8_t *image_data) {
// 1. 分配输入输出缓冲区
ai_float in_data[320*320*3]; // 假设输入是320x320 RGB
ai_float out_data[10*6]; // 假设输出10个检测框,每个6个值
// 2. 图像数据预处理(归一化等)
for (int i = 0; i < 320*320*3; i++) {
in_data[i] = image_data[i] / 255.0f;
}
// 3. 创建AI对象
ai_handle network = ai_network_create(&in_data, &out_data);
// 4. 运行推理
ai_error err = ai_network_run(network, &in_data);
if (err.type == AI_ERROR_NONE) {
// 5. 解析输出
Parse_Detections(out_data);
}
// 6. 清理
ai_network_destroy(network);
}
4.4 解析检测结果
YOLO的输出需要解码才能得到实际的检测框:
typedef struct {
float x, y, w, h; // 框的中心坐标和宽高
float confidence; // 置信度
int class_id; // 类别ID
} Detection;
void Parse_Detections(ai_float *output) {
// YOLO输出格式:每个检测框有6个值
// [x, y, w, h, confidence, class_id]
int num_detections = 10; // 根据模型输出调整
for (int i = 0; i < num_detections; i++) {
float conf = output[i*6 + 4];
// 过滤低置信度的检测
if (conf > 0.5f) {
Detection det;
det.x = output[i*6];
det.y = output[i*6 + 1];
det.w = output[i*6 + 2];
det.h = output[i*6 + 3];
det.confidence = conf;
det.class_id = (int)output[i*6 + 5];
// 转换到原始图像坐标
det.x *= 320; // 假设输入是320x320
det.y *= 320;
det.w *= 320;
det.h *= 320;
// 处理这个检测结果
Process_Detection(&det);
}
}
}
5. 优化技巧:让推理更快更稳
直接跑上面代码,你会发现速度很慢,一帧要好几秒。得做优化:
5.1 使用DMA传输图像数据
// 用DMA从摄像头直接传输到内存
void Camera_Capture_DMA(uint8_t *buffer) {
HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT,
(uint32_t)buffer, IMAGE_SIZE);
// 等待传输完成
while (HAL_DCMI_GetState(&hdcmi) != HAL_DCMI_STATE_READY) {
// 可以在这里做其他事情
}
}
5.2 降低输入分辨率
YOLO12n默认输入是640x640,但STM32处理这个分辨率太吃力。可以降到320x320甚至224x224:
# 训练时就用小分辨率
model.train(data='coco.yaml', epochs=100, imgsz=320)
5.3 使用INT8量化
前面提到过量化,这里再强调一下。INT8量化能让模型体积减少75%,速度提升2-3倍:
// 在STM32Cube.AI中选择INT8量化
// 生成代码时会自动处理
5.4 裁剪模型
如果只检测少数几类物体(比如只要检测人和车),可以裁剪掉其他类别的输出层,进一步减小模型:
# 修改模型最后一层
import torch
# 加载模型
model = YOLO('yolo12n.pt')
# 只保留前3个类别(假设人和车在前3类)
num_classes = 3
model.model.model[-1].nc = num_classes
# 重新训练
model.train(data='custom.yaml', epochs=50)
6. 实际效果测试
我在STM32H743上测试了YOLO12n,输入分辨率320x320,只检测"人"这一类物体。结果如下:
- 模型大小:量化后1.2MB,能放进Flash
- 推理时间:单帧约800ms
- 内存占用:峰值约500KB
- 检测准确率:在室内环境下,3米内能稳定检测到人
这个速度看起来慢,但对很多应用来说够用了。比如智能门铃,有人按门铃才触发检测,平时休眠。或者农业监测,几分钟拍一张照片分析一次。
如果想更快,可以试试这些方法:
- 降低检测频率:不需要每帧都检测,每秒检测1-2帧就行
- 运动触发:先用简单的背景减除检测到运动,再触发YOLO检测
- 区域检测:只检测图像中可能出现的区域
7. 遇到的问题和解决方案
7.1 内存不足
问题:运行时报错,内存分配失败。
解决:
- 使用STM32Cube.AI的内存优化功能
- 减少中间缓冲区
- 使用内存池管理
// 使用静态分配代替动态分配
static uint8_t image_buffer[320*320] __attribute__((section(".sdram"))); // 放到外部SDRAM
7.2 推理速度慢
问题:一帧要好几秒。
解决:
- 开启STM32的缓存
- 使用硬件FPU
- 优化内存访问模式
// 开启I-Cache和D-Cache
SCB_EnableICache();
SCB_EnableDCache();
7.3 检测不准
问题:量化后检测效果变差。
解决:
- 使用量化感知训练
- 在数据集上做校准
- 调整置信度阈值
8. 总结
把YOLO12部署到STM32上,听起来像是不可能完成的任务,但实际做下来发现,只要选对方法,还是能跑起来的。关键是要接受性能上的妥协——不要指望STM32能像GPU那样实时处理高清视频,但在特定的、对实时性要求不高的场景下,这个方案是可行的。
用下来的感受是,STM32跑YOLO12最适合那些“偶尔需要智能”的应用。比如智能农业传感器,每隔几分钟拍张照片分析作物状况;或者安防设备,检测到异常才启动录像。这些场景不需要连续处理,STM32的低功耗优势就能发挥出来。
如果你也想尝试,建议先从简单的开始。别一上来就搞复杂的多类别检测,先试试只检测一类物体,用低分辨率输入,跑通了再慢慢增加复杂度。STM32Cube.AI这个工具挺好用的,能省不少事,文档也还算详细。
当然,如果项目对性能要求高,预算也够,还是建议用专门的AI芯片或者性能更强的处理器。但如果你像我一样,被成本卡着,又想加点智能功能,STM32+YOLO12这个组合值得一试。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)