2. TFLite模型加载与推理框架集成
任务目标
在STM32F407开发板上集成TensorFlow Lite for Microcontrollers(TFLM)推理库,完成模型加载与基本推理闭环。本案例使用官方提供的person_detect模型(已量化,约50KB),输入为8×8灰度图像,输出为2类概率(无人/有人)。
环境与依赖
- 硬件:STM32F407VET6(Cortex-M4F,192KB RAM)
- IDE:STM32CubeIDE 1.15+(或任意支持ARM GCC的工程)
- 依赖库:
tflite-micro(GitHub: tensorflow/tflite-micro,commit: 2024-01-15后版本) - 模型文件:
person_detect_model_data.cpp(由TFLM官方示例提供,含g_person_detect_model_data数组)
实现方案
将TFLM库源码加入工程,核心流程为:初始化MicroInterpreter → 分配张量内存 → 设置输入数据 → 调用Invoke() → 读取输出。关键点在于正确配置TensorArena大小(本模型需约10KB)以及将模型数组以extern方式引用。
关键完整代码
// main.c 核心推理逻辑(省略外设初始化)
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "person_detect_model_data.h" // 模型数组头文件
// 模型输入尺寸(由模型文件定义)
#define INPUT_CHANNELS 1
#define INPUT_WIDTH 8
#define INPUT_HEIGHT 8
// TensorArena:模型中间计算缓冲区(按模型需求调整)
static uint8_t tensor_arena[10 * 1024];
// 输入图像数据(示例:全零表示"无人")
static uint8_t input_data[INPUT_CHANNELS * INPUT_WIDTH * INPUT_HEIGHT] = {0};
void run_inference(void) {
// 1. 注册模型所需算子(仅包含当前模型使用的算子)
static tflite::MicroMutableOpResolver<5> resolver;
resolver.AddFullyConnected();
resolver.AddConv2D();
resolver.AddMaxPool2D();
resolver.AddReshape();
resolver.AddSoftmax();
// 2. 加载模型
const tflite::Model* model = tflite::GetModel(g_person_detect_model_data);
if (model->version() != TFLITE_SCHEMA_VERSION) {
// 版本不匹配处理
return;
}
// 3. 创建解释器
static tflite::MicroInterpreter interpreter(
model, resolver, tensor_arena, sizeof(tensor_arena));
// 4. 分配张量内存
TfLiteStatus allocate_status = interpreter.AllocateTensors();
if (allocate_status != kTfLiteOk) {
return;
}
// 5. 获取输入张量并填充数据
TfLiteTensor* input = interpreter.input(0);
memcpy(input->data.uint8, input_data, sizeof(input_data));
// 6. 执行推理
TfLiteStatus invoke_status = interpreter.Invoke();
if (invoke_status != kTfLiteOk) {
return;
}
// 7. 读取输出(2类概率)
TfLiteTensor* output = interpreter.output(0);
uint8_t person_score = output->data.uint8[1]; // 索引1为"有人"概率
// person_score > 128 表示检测到人(量化阈值)
}
工程集成步骤
- 将
tflite-micro仓库的tensorflow/目录复制到工程Middlewares/下 - 在CubeIDE中设置头文件路径:
Middlewares/tensorflow及Middlewares/tensorflow/lite/micro/tools/make/downloads(若使用第三方算子) - 将
person_detect_model_data.cpp加入工程源码目录 - 在链接器设置中增加:
-Wl,--gc-sections(裁剪未用段)和-u _printf_float(若需浮点打印) - 编译时需定义
TF_LITE_STATIC_MEMORY宏(在编译器预定义中添加)
验证方法
通过条件:在run_inference()末尾设置断点,观察person_score值。当输入全零时,预期输出person_score < 128(表示无人)。若需验证"有人"场景,可将input_data替换为官方示例中的人像灰度数据(可从TFLM测试用例获取),此时person_score应大于128。
附加检查:通过UART打印allocate_status和invoke_status,两者均为kTfLiteOk(0)即表示模型加载与推理链路正常。若分配失败,需增大tensor_arena数组。
常见问题
- 编译报错找不到头文件:确认所有
tflite-micro子目录已复制完整,且路径无中文 - 链接时Flash溢出:TFLM库约占用80KB Flash,需确认MCU型号及链接脚本中Flash起始地址正确
- 推理结果恒为0:检查输入张量的数据类型是否为
kTfLiteUInt8,若为kTfLiteInt8需将输入数据转为有符号类型