融合U-Net图像分割与CNN端到端识别的车牌检测系统实战

张开发
2026/4/10 16:24:08 15 分钟阅读

分享文章

融合U-Net图像分割与CNN端到端识别的车牌检测系统实战
1. 车牌检测系统整体设计思路第一次接触车牌识别系统时我被这个看似简单实则复杂的任务难住了。直到把整个流程拆解成三个关键步骤才真正理清思路。这套系统的核心在于先用U-Net分割出车牌区域再用OpenCV进行几何矫正最后通过CNN实现端到端识别。听起来简单实际操作中每个环节都有不少坑要踩。为什么选择U-Net而不是传统方法我做过对比实验在复杂背景下U-Net的定位准确率比传统边缘检测方法高出23%。特别是在夜间或雨雪天气这个优势更加明显。CNN端到端识别则省去了字符分割的麻烦实测识别速度比传统方法快3倍以上。系统的工作流程可以这样理解就像快递分拣员先找到包裹U-Net定位再把歪斜的包裹摆正OpenCV矫正最后扫描条形码CNN识别。整个过程完全自动化从输入图片到输出车牌号只需0.8秒GTX1080显卡环境下。2. 数据准备与标注技巧2.1 构建高质量数据集我花了三个月收集了超过1.2万张车辆图片涵盖各种光照条件和角度。这里有个血泪教训千万别直接从网上下载图片就用我最初用的网络图片80%都存在尺寸不一、水印等问题导致模型效果极差。正确的做法是统一调整图片尺寸为512×512像素删除模糊或遮挡严重的图片确保车牌区域至少占图片宽度的1/32.2 使用Labelme高效标注标注工具我推荐Labelme虽然学习曲线有点陡但效率确实高。安装很简单pip install labelme labelme # 启动标注界面标注时我总结了几条黄金法则沿着车牌边缘精确勾勒误差控制在3个像素内先标注50张测试标注一致性保存时选择JSON格式方便后续处理开启自动保存功能防止意外中断处理标注数据时这个Python脚本帮我省了大量时间import os import cv2 import numpy as np n 1200 # 标注图片总数 for i in range(n): os.system(flabelme_json_to_dataset labelme/json/{i}.json -o labelme/data/{i}_json) img cv2.imread(flabelme/data/{i}_json/img.png) label cv2.imread(flabelme/data/{i}_json/label.png) label label / np.max(label[:,:,2]) * 255 cv2.imwrite(ftrain_label/{i}.png, label)3. U-Net模型训练实战3.1 模型架构详解我的U-Net实现包含9个卷积块每个块都采用ConvBNLeakyReLU的组合。这种设计比原始U-Net提升了约5%的准确率。关键点在于使用8个初始滤波器逐层加倍加入Dropout层防止过拟合keep_prob0.5采用LeakyReLUalpha0.1解决梯度消失问题模型结构核心代码def Conv2d_BN(x, nb_filter, kernel_size): x layers.Conv2D(nb_filter, kernel_size, paddingsame)(x) x layers.BatchNormalization(axis3)(x) return layers.LeakyReLU(alpha0.1)(x) inpt layers.Input((512,512,3)) conv1 Conv2d_BN(inpt, 8, (3,3)) conv1 Conv2d_BN(conv1, 8, (3,3)) pool1 layers.MaxPooling2D((2,2), paddingsame)(conv1) # 后续层类似...3.2 训练技巧与参数调优训练时我踩过几个大坑初始学习率设为0.001每10个epoch衰减30%batch_size根据显存调整11G显存建议15-20使用早停策略patience15数据增强采用随机旋转-15°~15°和亮度调整0.8~1.2倍最终模型在验证集上达到95%的准确率loss降至250左右。保存模型时要注意model.fit(X_train, y_train, epochs100, batch_size15) model.save(unet.h5) # 保存完整模型4. 车牌矫正关键技术4.1 边缘检测与轮廓分析获取车牌区域后矫正效果直接决定识别准确率。我改进的算法流程如下使用cv2.findContours找到所有轮廓筛选面积大于15×15像素的区域计算最小外接矩形通过加权算法定位四边形顶点关键改进点是加入了点到直线距离的权重计算def point_to_line_distance(X,Y): if x2-x0: k_up (y2-y0)/(x2-x0) d_up abs(k_up*X-Yy2-k_up*x2)/(k_up**21)**0.5 else: d_up abs(X-x2) # 类似计算d_down... return d_up, d_down4.2 透视变换实现找到四个顶点后透视变换就是水到渠成了p0 np.float32([l0,l1,l2,l3]) # 源四边形顶点 p1 np.float32([(0,0),(0,80),(240,0),(240,80)]) # 目标矩形 M cv2.getPerspectiveTransform(p0,p1) lic cv2.warpPerspective(img_src, M, (240,80))这个过程中我发现一个关键点当车牌倾斜超过45度时需要调整权重参数我最终采用0.975的线距离权重0.025的点距离权重这样矫正准确率能提升到98%。5. CNN端到端识别实现5.1 多标签分类设计车牌识别本质上是7个分类任务的组合省份字母5位数字字母。我的解决方案是共享底层卷积特征在最后一层分叉出7个全连接层每个输出对应65个类别31省份10数字24字母模型结构核心代码Input layers.Input((80,240,3)) x layers.Conv2D(16, (3,3), paddingsame, activationrelu)(Input) x layers.MaxPool2D((2,2), paddingsame)(x) # 更多卷积层... x layers.Flatten()(x) Output [layers.Dense(65, activationsoftmax, namefc{i1})(x) for i in range(7)] model models.Model(Input, Output)5.2 数据增强与类别平衡为了应对数据不均衡问题我采用了三种策略对稀缺省份车牌如藏、青进行过采样使用弹性变形增加样本多样性调整类别权重稀缺类别权重增加1.5倍最终在3.3万张车牌数据上训练后各省份识别准确率差异控制在3%以内。训练命令如下model.compile(optimizeradam, losssparse_categorical_crossentropy, metrics[accuracy]) model.fit(X_train, y_train, epochs35)6. 系统集成与性能优化6.1 完整处理流程将三个模块串联起来后整体处理流程如下加载U-Net模型进行车牌定位使用改进算法进行车牌矫正调用CNN模型进行端到端识别输出识别结果和置信度核心集成代码unet keras.models.load_model(unet.h5) cnn keras.models.load_model(cnn.h5) def predict_plate(img_path): img_src, img_mask unet_predict(unet, img_path) lic locate_and_correct(img_src, img_mask) chars cnn.predict(lic.reshape(1,80,240,3)) return .join([char_dict_inv[np.argmax(c)] for c in chars])6.2 性能优化技巧在实际部署中我总结了几个提速技巧使用TensorRT加速模型推理速度提升2.5倍对连续视频帧采用跟踪算法减少重复计算将U-Net输入尺寸降为256×256速度提升4倍精度仅下降2%使用多线程处理批量图片在Jetson Xavier NX上测试优化后的系统能实现15FPS的实时处理速度完全满足停车场等场景的需求。

更多文章