1. 项目概述
这个车牌识别系统是我去年为一个智能停车场项目开发的硬件解决方案。当时客户需要一套低成本、高可靠性的车牌识别方案,要求能在各种光照条件下稳定工作。经过多次方案对比,最终选择了STM32F4系列单片机作为主控,搭配OV7670摄像头模块,实现了从图像采集到车牌识别的完整流程。
整套系统最让我自豪的是在有限硬件资源下(STM32F407仅有192KB RAM)实现了车牌定位精度达到92%以上。这得益于精心设计的图像处理算法和多次优化的神经网络模型。下面我就详细拆解这个项目的技术实现,分享一些在嵌入式视觉系统开发中的实战经验。
2. 硬件选型与系统架构
2.1 核心硬件组件
选择STM32F407ZG作为主控主要基于三点考虑:
- 带硬件浮点运算单元(FPU),这对图像处理算法至关重要
- 192KB RAM能满足图像缓存需求
- 丰富的接口资源(DCMI摄像头接口、USB、USART等)
摄像头模块选型时对比了OV7670和OV2640:
- OV7670:30万像素,性价比高,但需要外接FIFO芯片
- OV2640:200万像素,自带JPEG压缩,但价格贵3倍
最终选择OV7670+AL422B FIFO的方案,成本控制在50元以内。实测在3米距离下,30万像素完全能满足车牌识别需求。
2.2 系统架构设计
整个系统采用三层架构:
- 采集层:OV7670摄像头+AL422B FIFO
- 处理层:STM32F4完成图像预处理和车牌识别
- 通信层:ESP8266 WiFi模块上传识别结果
特别说明电源设计:
- 摄像头需要独立的3.3V LDO供电
- FIFO芯片的读写时序要严格匹配数据手册
- STM32的DCMI接口时钟配置为8MHz最佳
3. 图像采集与预处理
3.1 摄像头驱动开发
OV7670的寄存器配置是个技术难点,我的配置经验:
c复制// 关键寄存器配置
SCCB_Write(0x12, 0x80); // 复位所有寄存器
SCCB_Write(0x3A, 0x04); // 输出格式设为RGB565
SCCB_Write(0x40, 0xD0); // 开启自动曝光
SCCB_Write(0x1E, 0x30); // 镜像+翻转设置
常见问题排查:
- 图像出现条纹:检查FIFO的读写时序,特别是WE和RCLK信号
- 颜色失真:重新校准OV7670的白平衡
- 帧率不稳定:调整DCMI的时钟分频系数
3.2 图像预处理算法
在STM32上实现的预处理流程:
- RGB转灰度:采用Y=0.299R + 0.587G + 0.114B公式
- 中值滤波:3x3窗口,有效去除噪声
- Sobel边缘检测:水平垂直双方向卷积核
- 二值化:采用自适应阈值法
优化技巧:
- 使用STM32的DMA2D加速图像处理
- 将Sobel算子转换为查表法实现
- 二值化阈值通过直方图分析动态计算
4. 车牌定位与字符识别
4.1 车牌定位算法
基于边缘检测的车牌定位流程:
- 形态学闭操作连接边缘
- 查找所有轮廓并筛选矩形区域
- 根据长宽比(约3:1)筛选候选区
- 颜色验证(蓝底白字或黄底黑字)
实测发现的问题:
- 强光下车牌反光严重:解决方法是在预处理时增加Gamma校正
- 车牌倾斜超过15度:开发了基于Hough变换的倾斜校正算法
4.2 字符分割与识别
字符识别采用两级方案:
- 一级分类器:基于模板匹配快速筛选
- 二级分类器:轻量级CNN网络(TensorFlow Lite微模型)
CNN网络结构优化:
python复制Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 16, 16, 8) 80
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 8, 8, 8) 0
_________________________________________________________________
flatten (Flatten) (None, 512) 0
_________________________________________________________________
dense (Dense) (None, 36) 18468
=================================================================
这个模型只有18K参数,在STM32上运行一帧仅需12ms。训练时采用了数据增强技术:
- 随机添加高斯噪声
- 模拟不同光照条件
- 字符轻微形变处理
5. 系统优化与实测数据
5.1 性能优化技巧
- 内存管理:
- 使用STM32的CCM内存存放神经网络权重
- 图像缓冲区采用双缓冲机制
- 启用I-Cache和D-Cache
- 算法加速:
- 将浮点运算转换为Q15定点数
- 使用CMSIS-DSP库优化矩阵运算
- 关键函数用汇编重写
5.2 实测性能数据
测试环境:
- 室外停车场,早中晚各100次测试
- 车牌类型:蓝牌、黄牌、新能源绿牌
结果统计:
| 条件 | 识别率 | 平均耗时 |
|---|---|---|
| 白天正常 | 95.2% | 320ms |
| 夜间补光 | 91.7% | 350ms |
| 雨雪天气 | 86.3% | 410ms |
| 强逆光 | 82.5% | 380ms |
6. 常见问题与解决方案
- 问题:系统运行一段时间后死机
- 原因:图像缓冲区溢出
- 解决:增加看门狗,优化DMA传输机制
- 问题:字符误识别率高
- 原因:训练样本不足
- 解决:收集2000+真实车牌数据增强训练集
- 问题:夜间识别率骤降
- 原因:摄像头自动增益控制不稳定
- 解决:固定曝光参数,增加红外补光灯
- 问题:WiFi传输丢包
- 原因:ESP8266天线设计不良
- 解决:改用PCB天线方案,增加重传机制
7. 项目扩展方向
在实际部署后,我们又做了几个功能扩展:
- 多摄像头协同:通过CAN总线连接多个识别终端
- 云端校验:本地识别结果上传服务器二次验证
- 车辆特征提取:增加车型、颜色识别功能
- 低功耗模式:没车时自动进入休眠状态
这个项目给我的最大启示是:在资源受限的嵌入式系统上做视觉识别,算法优化比堆硬件更重要。通过精心设计的数据流和内存管理,STM32完全能够胜任这类应用。