基于STM32H743与CNN的实时手写数字识别系统

基于STM32H743与CNN的
实时手写数字识别系统

—— STM32H743 + OV7725摄像头 + ST7789 LCD + 卷积神经网络 ——

主控芯片

STM32H743VIT (Cortex-M7, 480MHz, 2MB Flash)

图像采集

OV7725 摄像头 (DCMI接口, 160×120 RGB565)

显示模块

ST7789 0.96寸 LCD (SPI6, 160×80)

AI框架

X-CUBE-AI + TensorFlow/Keras 轻量CNN

识别精度

MNIST测试集准确率 99.02%

一、项目简介

本项目实现了一套基于STM32H743微控制器与卷积神经网络(CNN)的实时手写数字识别系统。系统通过OV7725摄像头实时采集图像,经图像预处理(裁剪、缩放、灰度化、二值化、归一化)后,输入轻量级CNN模型进行推理,最终在ST7789 LCD屏幕上实时显示识别结果(0~9)。

整个项目涵盖了从数据集准备、模型训练、模型转换到嵌入式部署的全流程,是一个完整的端到端嵌入式AI应用案例。模型在MNIST测试集上达到99.02%的准确率,部署到STM32H743后可实现每200ms一次的实时推理,并通过4帧滑动投票滤波抑制识别结果跳变,具有良好的实用价值。

核心技术栈

环节

技术/工具

说明

数据集

MNIST手写数字

60000张训练+10000张测试, 28×28灰度图

模型训练

Python + TensorFlow/Keras

轻量CNN, 2卷积层+2全连接层

模型转换

TFLite Converter

H5转TFLite, 保持float32精度

模型部署

STM32Cube.AI (X-CUBE-AI)

自动生成C代码, CM7运行时库

图像采集

OV7725 + DCMI + DMA

160×120 RGB565, DMA零拷贝传输

结果显示

ST7789 LCD + SPI6

0.96寸屏, 显示原图/预处理图/结果

结果优化

4帧滑动投票滤波

抑制实时识别结果跳变

二、系统总体架构

系统整体架构如下图所示,分为图像采集层、数据处理层、AI推理层和结果显示层四个部分:

【图像采集层】 OV7725摄像头 → DCMI接口 → DMA零拷贝传输 → 160×120 RGB565图像缓冲区

【数据处理层】 居中裁剪80×80 → 缩放至28×28 → RGB565转灰度 → 二值化(阈值180) → 归一化反转

【AI推理层】 ai_in[784]浮点输入 → X-CUBE-AI前向传播 → ai_out[10]概率输出 → argmax取最大值

【结果显示层】 4帧投票滤波 → ST7789 LCD显示原图+预处理图+识别结果 → 每200ms刷新一次

三、硬件设计

3.1 核心器件

器件

型号

关键参数

用途

主控MCU

STM32H743VIT

Cortex-M7, 480MHz, 2MB Flash, 1MB RAM

系统主控+AI推理

摄像头

OV7725

1/4寸CMOS, VGA, RGB565, DVP接口

手写数字图像采集

显示屏

ST7789

0.96寸, 160×80, SPI接口, 65K色

实时显示图像与结果

晶振

25MHz HSE

经PLL倍频至480MHz

系统主时钟源

3.2 引脚分配

外设

STM32引脚

功能说明

DCMI数据线

PC6/PC7/PE0/PE1/PE4/PB6/PE5/PE6

摄像头8位数据D0~D7

DCMI_HSYNC

PA4

行同步信号

DCMI_VSYNC

PB7

场同步信号

DCMI_PIXCLK

PA6

像素时钟

I2C1_SCL/SDA

PB8/PB9

摄像头SCCB寄存器配置

SPI6_SCK/MISO/MOSI

PG13/PG12/PG14

LCD显示屏SPI通信

LCD_RST/DC/PWR

PG4/PG3/PG5

LCD复位/数据命令/背光控制

USART1_TX/RX

PA9/PA10

调试串口

KEY

PC13

用户按键

RGB LED

PC0/PC1/PC2

状态指示灯

注:DCMI配合DMA1_Stream0实现图像数据零拷贝传输,摄像头采集的图像直接写入内存缓冲区,无需CPU干预,大幅提升图像采集效率。

四、神经网络模型设计与训练

4.1 MNIST数据集

本项目使用经典的MNIST手写数字数据集进行模型训练。MNIST包含60000张训练图像和10000张测试图像,每张图像为28×28像素的灰度手写数字(0~9),是深度学习入门的标准数据集。

图4-1 MNIST手写数字数据集样本展示

4.2 CNN模型结构

为适配STM32嵌入式平台的算力和存储限制,本项目设计了一个轻量级卷积神经网络,包含2个卷积层、2个最大池化层和2个全连接层。模型结构如下表:

层名

类型

输出形状

参数量

说明

Input

输入层

1×28×28×1

-

28×28灰度图

conv2d_0

Conv2D(16@3×3)+ReLU

1×26×26×16

160

第一卷积层

pool_1

MaxPool2D(2×2)

1×13×13×16

-

下采样

conv2d_2

Conv2D(32@3×3)+ReLU

1×11×11×32

4,736

第二卷积层

pool_3

MaxPool2D(2×2)

1×5×5×32

-

下采样

reshape_4

Flatten

1×800

-

展平

gemm_5

Dense(64)+ReLU

1×64

51,264

全连接层

gemm_6

Dense(10)

1×10

650

输出层

nl_7

Softmax

1×10

-

概率输出

4.3 模型训练

模型使用Python + TensorFlow/Keras框架进行训练,优化器为Adam,损失函数为稀疏交叉熵。训练代码如下图所示:

图4-2 MNIST模型训练代码(Python/TensorFlow)

训练过程截图如下,可以看到模型在训练过程中损失持续下降,准确率稳步提升:

图4-3 PyCharm中模型训练代码运行

图4-4 训练过程(Epoch 4~7损失与准确率)

训练最终结果如下图所示,模型在测试集上达到了99.02%的准确率:

图4-5 训练完成,测试集准确率99.02%

4.4 模型转换与部署

训练好的Keras H5模型需要转换为TFLite格式,再通过STM32Cube.AI工具链导入生成C代码,最终编译部署到STM32H743上。转换流程如下:

Step 1: H5模型转TFLite(不使用INT8量化,保持float32精度以确保CubeAI兼容性):

图4-6 H5转TFLite模型转换代码

Step 2: STM32Cube.AI导入TFLite模型,自动生成C代码:

在STM32CubeMX中配置X-CUBE-AI中间件,导入TFLite模型后,工具自动生成network_data.c(权重数据)、network_data_params.c(参数配置)和app_x-cube-ai.c(推理接口)等文件。

Step 3: 模型资源占用报告(X-CUBE-AI生成):

资源

占用

说明

Flash(权重)

221.54 KiB

模型权重存储在Flash中

RAM(激活值)

16.21 KiB

推理时的中间激活值

总Flash

236.91 KiB

权重+代码+常量

总RAM

18.86 KiB

激活值+IO缓冲区

MACC运算量

735,792

单次推理乘加运算次数

输入

f32(1×28×28×1)

784个浮点数

输出

f32(1×10)

10个概率值(softmax)

注:STM32H743拥有2MB Flash和1MB RAM,模型占用不到12%的Flash和2%的RAM,资源充裕。

五、软件设计

5.1 主程序流程

系统上电后依次完成CPU缓存使能、HAL初始化、480MHz时钟配置、各外设初始化(GPIO/DMA/SPI6/DCMI/USART1/I2C1)、LCD初始化、摄像头初始化和AI模型初始化,随后启动DCMI DMA连续采集并进入主循环。主循环中并行处理图像显示和AI推理两个任务。主函数代码如下:

图5-1 主函数初始化与主循环代码

5.2 图像预处理

图像预处理是连接摄像头采集与AI模型推理的关键环节。由于OV7725采集的是160×120的RGB565彩色图像,而MNIST模型需要28×28的灰度归一化输入,因此需要经过以下处理步骤:

  • 【裁剪】从160×120图像中居中裁剪80×80区域,聚焦数字主体
  • 【缩放】使用最近邻采样将80×80缩放至28×28,匹配模型输入尺寸
  • 【灰度化】RGB565转灰度:0.299R + 0.587G + 0.114B标准公式
  • 【二值化】阈值180二值化:大于180设为255(白),否则0(黑)
  • 【归一化】1.0 - gray/255.0 反转归一化,适配MNIST白底黑字格式

图5-2 图像预处理代码(裁剪/缩放/灰度化/二值化/归一化)

5.3 AI推理引擎

AI推理由X-CUBE-AI运行时库驱动。每次推理时,先将预处理后的784个浮点数拷贝到AI输入缓冲区,调用ai_network_run()执行前向传播,再将输出的10个概率值取回。推理接口代码如下:

图5-3 X-CUBE-AI推理引擎代码(输入填充/前向传播/输出取回)

5.4 识别结果滤波

由于实时识别中摄像头画面可能存在抖动或光照变化,单次识别结果可能出现跳变。系统采用4帧滑动窗口投票滤波:缓存最近4次识别结果,取出现次数最多的数字作为最终输出,有效抑制了结果跳变,提升了识别稳定性。滤波代码如下:

图5-4 识别结果滑动投票滤波代码

5.5 LCD显示

ST7789 LCD通过SPI6与STM32通信,屏幕分辨率为160×80(旋转90度后)。主循环中LCD实时显示三类内容:

  • 【原图显示】160×80原始摄像头画面(左侧)
  • 【预处理图】28×28预处理灰度图放大2倍显示(右侧)
  • 【识别结果】"RES:X"格式的识别结果文字叠加在画面上

DCMI帧中断回调函数中刷新D-Cache并置位帧就绪标志,主循环检测到标志后执行显示更新。

六、项目文件结构

工程采用STM32CubeMX生成的HAL库架构,代码分层清晰。主要目录结构如下:

目录/文件

说明

python/

Python模型训练脚本(main.py训练, h5转tflite.py转换)+ H5/TFLite模型

MNIST/raw/

MNIST数据集原始文件(训练/测试图像与标签)

Digit_Rec_keil/Core/Src/

STM32主程序(main.c)及外设初始化(dcmi/spi/i2c/dma/usart/gpio)

Digit_Rec_keil/BSP/Camera/

摄像头驱动(OV7725/OV2640/OV5640/OV7670, 含寄存器配置表)

Digit_Rec_keil/BSP/LCD_ST7789/

ST7789 LCD驱动(核心驱动/端口层/字体数据)

Digit_Rec_keil/X-CUBE-AI/App/

AI推理引擎(app_x-cube-ai.c)+ 模型权重(network_data.c)

Digit_Rec_keil/X-CUBE-AI/AI/Lib/

X-CUBE-AI运行时静态库(CM7专用)

Digit_Rec_keil/MDK-ARM/

Keil MDK工程文件(.uvprojx)

Digit_Rec_keil/*.ioc

STM32CubeMX工程配置文件

七、演示视频

系统演示视频展示了实时手写数字识别的完整效果。演示内容包括:

  • 上电启动,LCD显示摄像头实时画面
  • 手写数字置于摄像头前,LCD右侧显示28×28预处理图像
  • 系统每200ms执行一次AI推理,LCD左上角显示"RES:X"识别结果
  • 4帧投票滤波后识别结果稳定,数字切换时无明显跳变
  • 0~9各数字均可准确识别

图7-1 演示视频 

八、总结

本项目成功实现了一套基于STM32H743与CNN的实时手写数字识别系统。通过OV7725摄像头采集图像,经裁剪、缩放、灰度化、二值化等预处理后,输入轻量CNN模型进行推理,在ST7789 LCD上实时显示识别结果。模型在MNIST测试集上达到99.02%的准确率,嵌入式部署后通过4帧投票滤波实现了稳定可靠的实时识别。

本项目是一个完整的端到端嵌入式AI应用案例,涵盖了数据集准备、模型训练(Python/TensorFlow)、模型转换(H5→TFLite)、嵌入式部署(STM32Cube.AI)和实时推理(X-CUBE-AI)的全流程,对学习嵌入式人工智能具有很好的参考价值。后续可扩展方向包括:支持更多字符识别、引入INT8量化加速推理、增加WiFi模块实现云端识别结果上传等。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

— END —

posted @ 2026-07-21 00:24  Yan_2  阅读(5)  评论(0)    收藏  举报