车牌识别工作时间轴

最近放弃了带遮挡的人脸识别,投身车牌识别的大业,这里的车牌识别是基于国内的、多种类的、恶劣条件下的,可以成为Real or Wild的plate recognition,将时间线和所做工作总结如下,主要同步自实验室的私有gitlab。


说下gitlab

恰巧guyhub被微软收购了,未来可能会退出CN版的guyhub,当然如果是这样,外网guyhub应该是访问不了了,而国内的服务一定是遵守社会主义核心价值观,像host这样的开源库可能就要被灭绝了。

我们实验室内部代码交流和项目协作主要使用gitlab,一方面代码不便于在github公开仓库上共享,另一方面放着服务器不搭个写代码的平台也说不过去。gitlab的功能一定是比github更强大更丰富的,目前使用的功能还是比较少,对于git比较熟,所以也算得心应手。


开源库HyperLPR

HyperLPR是基于深度学习的高性能中文车牌识别开源库,这里做一些研究,目前发现的问题有:

  • EasyPR的数据集准确率并不高,大概60%?远达不到宣称的90%
  • 框架使用深度学习,训练网络时数据集应该不够多,效果差强人意

目前发现的优点有:

  • 端到端的神经网络训练模型进行车牌字符识别
  • 代码比较轻量

工作流程分析

对HyperLPR一个完整的车牌识别工作流程进行分析:

  1. batch.py 批量处理工具 批量读取文件调用pipline
  2. pipline调用SimpleRecognizePlate函数(SimpleRecognizePlateByE2E ?)
  3. detectPlateRough 传入灰度图 参数如下
    • resize_h
    • en_scale
    • top_bottom_padding_rate
  4. 调用模型’./model/cascade.xml’ 使用opencv中CascadeClassifier的detectMultiScale多尺度检测
  5. 车牌粗定位完成 进行SimplePredict 使用”./model/plate_type.h5”模型确定车牌类别(神经网络)
  6. 如果车型判断成功 对车牌进行bitwise_not二值化反色处理
  7. 调用finemapping中的精定位算法findContoursAndDrawBoundingBox
  8. 调用finemapping中的”./model/model12.h5”左右边界回归 进行垂直精定位算法finemappingVertical
  9. 调用e2e 使用模型”./model/ocr_plate_all_w_rnn_2.h5” 端到端字符识别 只输出不使用?
  10. 校正完成 使用segmentation中的slidingWindowsEval 进行文字分割和识别
  11. 置信度判断和输出

注意事项:

  • ocr_plate_all_gru.h5 作为序列模型效果更好,但是更慢 以上过程中未使用

思路整理和细节分析

车牌粗定位

  1. 读取图像,进行resize,高度720,cvtColor转化为灰度图
  2. cascade多尺度检测
    cascade模型如何训练的?
    Opencv的Haar级联分类目标检测器,使用train-detector,需要正样本和负样本,正样本使用现有车牌识别软件crop,误检区域也加入负样本。
    cascade是通过多个adaboost强分类串联得到一个新的分类器,只有所有的adaboost分类器都认为是positive,最终结果才是positive,否则都是negative,以此大幅降低FP rate,而TP rate基本不变。
  3. 剪切crop

车牌精定位

  1. 上下边界
  2. 左右边界

车牌颜色识别

  1. reshape成3行矩阵,用KMeans聚类
  2. 画直方图,找出数目最多的聚类中心
  3. 对该点进行颜色识别

数据生成和增强

  1. 使用label和template
  2. 增加脏污效果,生成脏污块,使用cv2.addweighted图片融合
  3. 轻微畸变,cv2.warpPerspective
  4. 分三个通道增加noise
  5. 5w张车牌

模型训练

  1. 使用端到端的级联CNN模型,模型结构:级联的Conv2D卷积,kernel size分别为32 64 128 256 1024,前几层使用relu激活,最后一层使用softmax,数量为num_char+1

车牌识别

测试程序

完整修改了测试程序,并进行了正确率测试,大部分特殊车牌不支持,少数几种车牌识别率低于20%。

def plate_recogniton(real_path):
plate_real = real_path[:-4].split('\\')[-1][:8]
plate_real_list.append(plate_real)
print('plate_real:' + str(plate_real))

if real_path.endswith(".jpg") or real_path.endswith(".png") or real_path.endswith(".JPG"):
image = cv_imread(real_path)
# print(type(image))
# image,res = model.SimpleRecognizePlateByE2E(image)
res = model.SimpleRecognizePlateByE2E(image)
max_res = ['null',0,[862.01999999999998, 924.0, 178.03504678726196, 52.0]]
res.sort(key=lambda x: x[1],reverse=True)
if len(res) == 0:
pass
elif len(res) >= 1:
max_res = res[0]
print(res)
plate_predict = max_res[0]
print('plate_predict:' + plate_predict)
plate_predict_list.append(plate_predict)

车牌生成

使用hyperlpr-train_e2e

具体代码和训练模板稍后放出。

模型的训练程序

使用Hyperlpr端到端车牌识别训练脚本

一个encoding问题:

def init(self):
self.labels = []
with open(self._label_file,encoding='utf-8') as f: # 强制utf-8
for line in f:
filename, label = parseLine(line)
self.filenames.append(filename)
self.labels.append(label)
self._num_examples += 1
self.labels = np.float32(self.labels)

代码跑出来loss到30%,在titan上大约30秒一个epoch

需要改进的:

  • 输出acc
  • 输出网络模型

框架的改进思路

尝试使用GRU模型,但图片的输入格式有问题,训练loss不降反升?

keras仍然不够熟悉,需要继续学习。


Author: Ykk
Link: https://ykksmile.top/posts/19204/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.