3. 图像分类(CIFAR-10)
任务目标
在STM32平台上部署一个针对CIFAR-10数据集的CNN图像分类模型,实现对32×32 RGB输入图像的实时推理,输出10个类别(飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车)中的预测标签。
环境与依赖
- 硬件:STM32H743ZI(或同等性能Cortex-M7,建议≥1MB RAM)
- 软件:STM32CubeIDE 1.13+,X-CUBE-AI 9.0+
- 模型:CIFAR-10量化CNN(.tflite或.onnx格式),输入1×32×32×3,输出1×10
- 图像源:通过UART接收32×32 RGB原始像素数据(或板载摄像头采集后缩放)
实现方案
使用X-CUBE-AI将预训练CNN模型转换为STM32可调用的C库。核心代码包含:模型初始化、输入张量填充(像素归一化至[0,1])、推理调用、输出后处理(argmax获取类别索引)。UART接收完整图像帧后触发推理,结果通过UART以文本形式回传。
关键完整代码
/* main.c 核心推理逻辑 */
#include "ai_platform.h"
#include "network.h"
#include "cifar10_weights.h" // X-CUBE-AI生成的权重头文件
#define IMG_SIZE (32*32*3)
#define NUM_CLASS 10
static ai_handle network = AI_HANDLE_NULL;
static ai_network_report report;
static ai_buffer ai_input[1], ai_output[1];
static ai_i8 input_data[IMG_SIZE]; // 量化输入
static ai_i8 output_data[NUM_CLASS]; // 量化输出
// CIFAR-10类别名称
static const char* class_names[NUM_CLASS] = {
"airplane", "automobile", "bird", "cat", "deer",
"dog", "frog", "horse", "ship", "truck"
};
// 初始化AI网络
int ai_init(void) {
if (ai_network_create(&network, &report) != 0) return -1;
ai_input[0] = (ai_buffer){AI_BUFFER_FORMAT_Q, 0, 0, {0}, {1,32,32,3}, {0}};
ai_output[0] = (ai_buffer){AI_BUFFER_FORMAT_Q, 0, 0, {0}, {1,10}, {0}};
// 绑定输入输出缓冲区
ai_input[0].data = input_data;
ai_output[0].data = output_data;
if (ai_network_init(network, &report) != 0) return -2;
return 0;
}
// 执行推理并返回类别索引
int ai_predict(uint8_t* rgb_pixels) {
// 像素值从uint8 [0,255] 量化为int8 [-128,127]
for (int i = 0; i < IMG_SIZE; i++) {
input_data[i] = (ai_i8)((rgb_pixels[i] - 128) & 0xFF);
}
if (ai_run(network, ai_input, ai_output) != 0) return -1;
// argmax获取最高置信度类别
int max_idx = 0;
ai_i8 max_val = output_data[0];
for (int i = 1; i < NUM_CLASS; i++) {
if (output_data[i] > max_val) {
max_val = output_data[i];
max_idx = i;
}
}
return max_idx;
}
// UART接收回调(中断中置标志,主循环处理)
volatile uint8_t frame_ready = 0;
uint8_t frame_buffer[IMG_SIZE];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart1) {
frame_ready = 1;
HAL_UART_Receive_IT(&huart1, frame_buffer, IMG_SIZE);
}
}
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_UART1_Init();
if (ai_init() != 0) {
Error_Handler();
}
HAL_UART_Receive_IT(&huart1, frame_buffer, IMG_SIZE);
while (1) {
if (frame_ready) {
frame_ready = 0;
int cls = ai_predict(frame_buffer);
if (cls >= 0) {
char msg[64];
int len = sprintf(msg, "Predicted: %s\r\n", class_names[cls]);
HAL_UART_Transmit(&huart1, (uint8_t*)msg, len, 1000);
}
}
}
}
运行与验证
- 模型转换:在CubeIDE中启用X-CUBE-AI,导入CIFAR-10量化CNN模型,生成
network.c/h及权重文件 - 编译烧录:编译工程并烧录至STM32H743
- 发送测试图像:通过UART1(115200-8-N-1)发送3072字节原始RGB数据(按行优先,R,G,B顺序)
- 观察输出:开发板应返回
Predicted: 类别名文本
通过条件:使用CIFAR-10测试集图像(如飞机、猫各1张)发送,返回的类别与图像内容一致。若使用官方测试集前10张图像,正确率应≥80%(模型量化精度损失后)。
常见问题
- 内存不足:确认模型量化至int8,且STM32H743的RAM≥1MB;若仍不足,减小批处理至1并关闭调试打印
- 输出全为0:检查输入量化是否正确——像素值需减去128再转为int8
- UART接收超时:确保发送端一次性连续发送3072字节,中间无间隔;或增大DMA缓冲