1. 项目背景与核心价值
车牌识别作为计算机视觉领域的经典应用场景,在智慧交通、停车场管理、违章抓拍等场景中发挥着关键作用。传统基于图像处理的车牌识别方案在复杂环境下的准确率往往难以突破90%大关,而基于深度学习的方案在实测中可以达到98%以上的识别准确率。
我在本科毕业设计期间实现的这套车牌识别系统,采用YOLOv5+CRNN的经典组合方案,在自建数据集上取得了97.6%的端到端识别准确率。整个项目从数据采集到模型部署历时4个月,期间踩过不少坑也积累了大量实战经验,现将完整实现思路和优化技巧分享给大家。
这套方案特别适合需要快速实现高精度车牌识别的场景,比如:
- 校园/小区门禁系统改造
- 毕业设计或课程大作业
- 中小型停车场管理系统
- 交通流量统计等轻量级应用
2. 技术方案选型与对比
2.1 主流技术路线分析
当前车牌识别主要有三种技术路线:
-
传统图像处理方案
- 基于OpenCV的颜色分割+形态学处理
- 优点:无需训练数据,开发速度快
- 缺点:光照敏感,旋转适应性差(实测准确率约85%)
-
两阶段检测识别方案
- 检测(YOLO/SSD)+ 识别(CRNN/LPRNet)
- 优点:模块化设计,便于单独优化
- 缺点:流程较长,耗时增加约30%
-
端到端统一模型
- 如PP-OCRv3等一体化方案
- 优点:推理速度快
- 缺点:数据需求量大,小样本表现不佳
经过实际测试对比,最终选择了两阶段方案中的YOLOv5s+CRNN组合,在准确率和推理速度上取得了最佳平衡。
2.2 关键组件选型理由
检测模块选择YOLOv5s的原因:
- 相比v3/v4,v5的FPN结构更适合小目标检测
- 模型体积仅14MB(FP32),适合边缘设备部署
- 官方提供的预训练模型在COCO上表现优异
识别模块选择CRNN的原因:
- 序列建模能力优于传统CNN
- 支持不定长字符识别
- 开源实现成熟(PaddleOCR等)
实测对比:在相同测试集上,CRNN比LPRNet的字符识别准确率高3.2个百分点
3. 数据集构建与增强策略
3.1 数据采集方案
由于公开车牌数据集(如CCPD)主要包含中国车牌,为增强模型泛化能力,我们采用以下多源数据方案:
-
自采数据(占比40%)
- 使用普通手机在不同时段(早/中/晚)拍摄
- 包含多种角度(正拍/斜拍/俯拍)
- 覆盖不同光照条件(顺光/逆光/阴影)
-
公开数据集(占比30%)
- CCPD(中国车牌)
- UFPR-ALPR(巴西车牌)
- EuroPlate(欧洲车牌)
-
合成数据(占比30%)
- 使用Blender生成带随机背景的虚拟车牌
- 添加运动模糊、雨雪等天气效果
- 示例代码:
python复制import albumentations as A transform = A.Compose([ A.MotionBlur(blur_limit=7, p=0.3), A.RandomShadow(shadow_roi=(0,0,1,0.5), p=0.2), A.RandomBrightnessContrast(p=0.5) ])
3.2 数据标注规范
采用专业标注工具LabelImg+自定义脚本处理:
-
检测标注
- 车牌区域标注为"plate"
- 保留5%的负样本(不含车牌图像)
-
识别标注
- 统一转换为"京A·12345"格式
- 特殊字符用拼音首字母表示(如"使→S")
-
数据划分比例
类型 训练集 验证集 测试集 数量(张) 6800 1500 1700 车牌类型 混合 混合 纯真实
4. 模型训练与优化技巧
4.1 检测模型训练细节
关键参数配置:
yaml复制# yolov5s_plate.yaml
nc: 1 # 仅检测车牌一类
depth_multiple: 0.33
width_multiple: 0.50
anchors:
- [10,13, 16,30, 33,23] # 调整anchor适配车牌长宽比
训练命令示例:
bash复制python train.py --img 640 --batch 32 --epochs 100 \
--data plate.yaml --cfg yolov5s_plate.yaml \
--weights yolov5s.pt --name plate_det
效果提升技巧:
- 使用余弦退火学习率(--cos-lr)
- 添加CutMix数据增强(--rect关闭)
- 最后10个epoch冻结骨干网络
实测显示:添加马赛克增强后,小目标召回率提升12%
4.2 识别模型调优方案
CRNN模型结构优化点:
- 将LSTM层数从2增加到3
- 在CNN部分添加SE注意力模块
- 使用CTC loss + CrossEntropy联合训练
字符准确率对比:
| 模型变体 | Top-1 Acc | 推理时间(ms) |
|---|---|---|
| 原始CRNN | 94.2% | 28 |
| +SE模块 | 95.1% | 31 |
| +3层LSTM | 96.3% | 35 |
| 联合损失函数 | 97.6% | 38 |
5. 系统集成与部署实战
5.1 端到端推理流程
python复制class LPRSystem:
def __init__(self):
self.det_model = torch.hub.load('ultralytics/yolov5', 'custom', 'plate_det.pt')
self.rec_model = load_crnn('crnn_se.pth')
def recognize(self, img):
# 检测阶段
det_results = self.det_model(img)
plates = extract_plates(det_results) # 提取车牌区域
# 识别阶段
results = []
for plate in plates:
plate = preprocess(plate) # 尺寸归一化+二值化
text = self.rec_model(plate)
results.append(text)
return results
5.2 性能优化技巧
多线程处理方案:
python复制from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=4) as executor:
plate_futures = [executor.submit(preprocess, p) for p in plates]
texts = [self.rec_model(f.result()) for f in plate_futures]
TensorRT加速实践:
- 将PyTorch模型转为ONNX格式
- 使用trtexec生成引擎:
bash复制
trtexec --onnx=crnn.onnx --fp16 --saveEngine=crnn_fp16.engine - 实测加速比:
设备 原始推理时间 TensorRT加速后 Jetson Nano 380ms 120ms RTX 3060 38ms 12ms
6. 常见问题与解决方案
6.1 检测阶段典型问题
问题1:车牌漏检(特别是倾斜车牌)
- 解决方案:
- 训练数据中添加更多斜拍样本
- 测试时使用多尺度推理(--img 640,1280)
问题2:误检(将类似车牌的区域识别为车牌)
- 解决方案:
- 提高置信度阈值(从0.25调整到0.5)
- 添加负样本重新训练
6.2 识别阶段常见错误
字符混淆统计表:
| 易混淆字符对 | 出现频率 | 改进措施 |
|---|---|---|
| 0与D | 23% | 调整字体生成策略 |
| 8与B | 17% | 添加笔画特征损失 |
| 5与S | 12% | 增加相似字符样本 |
识别结果后处理技巧:
python复制def postprocess(text):
# 基于车牌规则的纠错
if len(text) == 7 and text[2] == '·':
return text # 标准格式
elif text.startswith('京'):
return text[:2] + '·' + text[2:] # 补充分隔符
else:
return spell_check(text) # 基于词典的纠错
7. 完整项目结构说明
核心代码目录结构:
code复制lpr-system/
├── configs/ # 模型配置文件
├── data/ # 数据集与增强脚本
├── models/ # 模型定义
│ ├── detection.py # YOLOv5改造代码
│ └── recognition.py # CRNN实现
├── utils/ # 工具函数
│ ├── augmentation.py # 自定义数据增强
│ └── visualization.py# 结果可视化
├── train_det.py # 检测模型训练
├── train_rec.py # 识别模型训练
└── demo.py # 端到端演示
关键依赖版本:
- PyTorch 1.10+
- OpenCV 4.5+
- PyYAML 6.0+
- 支持CUDA 11.3的GPU环境
在Jetson Nano上的部署注意事项:
- 使用TensorRT加速时必须安装jetpack 4.6+
- 建议将识别模型量化为INT8
- 视频流处理时限制分辨率为720p
这个项目最让我有成就感的是通过数据增强和模型微调,将夜间车牌的识别准确率从最初的68%提升到了93%。其中最关键的是添加了模拟车灯眩光的增强策略,这在实际应用中非常实用。如果大家想要进一步提升性能,可以尝试用最新的YOLOv8替换v5,我在测试中发现其对小目标的检测效果有显著提升。