引言


HyperLRP是一个开源的、基于深度学习高性能中文车牌识别库,由北京智云视图科技有限公司开发,支持PHP、C/C++、Python语言,Windows/Mac/Linux/Android/IOS平台。与较为流行的开源的EasyPR相比,它的检测速度和鲁棒性和多场景的适应性都要好于目前开源的EasyPR,HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等。

  • TODO
    支持多种车牌以及双层
    支持大角度车牌
    轻量级识别模型
  • 特性
    速度快 720p,单核 Intel 2.2G CPU (MaBook Pro 2015)平均识别时间低于100ms
    基于端到端的车牌识别无需进行字符分割
    识别率高,卡口场景准确率在95%-97%左右
    轻量,总代码量不超1k行

目录

  • 引言
  • 一、开发环境配置
    • ⭕️Win
    • ⭕️树莓派
  • 二、代码解析
    • demo.py(单张图片检测部分)
      • 1、输入模块
      • 2、输入图片识别处理
        • HyperLPRLite.py LPR类中的int()函数
          • - cv2.CascadeClassifier()函数
          • - model_finemapping()函数:车牌精定位
          • - model_seq_rec()函数:ocr识别
      • 3、输出参数
        • HyperLPRLite.py LPR类中的SImpleRecognizePlateByE2E()函数
          • - detectPlateRough()函数:车牌粗定位
          • - filemappingVertical()函数
          • - recognizeOne函数
        • hyperlpr.pipline.py 中的drawRectBox()函数

一、开发环境配置

⭕️Win

1、在Anaconda所建环境的命令行中输入

pip3 install hyperlpr -i https://mirrors.aliyun.com/pypi/simple/

2、下载整个开源库文件
https://gitee.com/zeusees/HyperLPR/tree/master/

把hyperlpr_py3并改名为hyperlpr复制到Anaconda3安装路径\envs\环境名\lib\python3.6\site-packages,与原目录下的hyperlpr合并

3、新建开发文件
将开源库中的Font、model、HyperLprGUI.py、HyperLprLite.py、demo.py拷到此目录中,创建一个Images的目录,放置待识别车牌的车辆照片,命名为plate1.jpg、plate2.jpg、plate3.jpg。

4、测试代码demo.py(单张图片检测部分)

from hyperlpr.pipline import drawRectBox
import HyperLPRLite as pr
import cv2
import numpy as np
grr = cv2.imread("./Images/plate3.png")
model = pr.LPR("model/cascade.xml","model/model12.h5","model/ocr_plate_all_gru.h5")
for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr):if confidence>0.7:image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3)))print("plate_str:")print(pstr)print("plate_confidence")print(confidence)cv2.imshow("image",image)
cv2.waitKey(0)

⭕️树莓派

1、在命令行里输入sudo pip3 install hyperlpr
2、将上面的hyperlpr_py3并改名为hyperlpr拷贝到树莓派/home/pi/.local/lib/python3.7/site-packages

二、代码解析

demo.py(单张图片检测部分)

demo中总的流程分为:
1)利用cascade进行车牌定位
2)对粗定位的车牌进行左右边界回归,去除车牌两边多余的部分
3)将精定位的车牌送入CRNN网络进行字符识别

1、输入模块

from hyperlpr.pipline import drawRectBox
import HyperLPRLite as pr
import cv2

Github : https://github.com/icepoint666/HyperLPR

Forked from zeusees/HyperLPR 略加改动

只需要三个代码文件:

  • multi_demo.py
  • demo.py
  • HyperLPRLite.py

2、输入图片识别处理

grr = cv2.imread("./Images/plate3.png")

opencv2的imread函数导入图片, 返回的是Mat类型。

model = pr.LPR("model/cascade.xml","model/model12.h5","model/ocr_plate_all_gru.h5")

HyperLPRLiite.py中的LPR类构造函数导入model, 参数就是训练好的三个模型文件,名字分别是:

  • model/cascade.xml cascade模型
  • model/model12.h5 左右边界回归模型
  • model/ocr_plate_all_gru.h5 字符识别模型
  • HyperLPRLite.py LPR类中的int()函数

 def __init__(self,model_detection,model_finemapping,model_seq_rec):self.watch_cascade = cv2.CascadeClassifier(model_detection)self.modelFineMapping = self.model_finemapping()self.modelFineMapping.load_weights(model_finemapping)self.modelSeqRec = self.model_seq_rec(model_seq_rec)

参数 model_detection 就是文件 model/cascade.xml 用到了opencv2的CascadeClassifier()函数

- cv2.CascadeClassifier()函数

参数输入.xml或者.yaml文件,表示加载模型,是一种基于Haar特征的级联分类器用于物体检测的模型

- model_finemapping()函数:车牌精定位
def model_finemapping(self):input = Input(shape=[16, 66, 3])  # change this shape to [None,None,3] to enable arbitraty shape inputx = Conv2D(10, (3, 3), strides=1, padding='valid', name='conv1')(input)x = Activation("relu", name='relu1')(x)x = MaxPool2D(pool_size=2)(x)x = Conv2D(16, (3, 3), strides=1, padding='valid', name='conv2')(x)x = Activation("relu", name='relu2')(x)x = Conv2D(32, (3, 3), strides=1, padding='valid', name='conv3')(x)x = Activation("relu", name='relu3')(x)x = Flatten()(x)output = Dense(2,name = "dense")(x)output = Activation("relu", name='relu4')(output)model = Model([input], [output])return model

利用了keras网络模型:对车牌的左右边界进行回归,通过modelFineMapping.loadweights()函数加载模型文件并由modelFineMapping.predict输出网络结果

  • 输入:16663 tensor
  • 输出:长度为2的tensor

预测出车牌的左右边框,进一步裁剪,进行精定位

- model_seq_rec()函数:ocr识别
def model_seq_rec(self,model_path):width, height, n_len, n_class = 164, 48, 7, len(chars)+ 1rnn_size = 256input_tensor = Input((164, 48, 3))x = input_tensorbase_conv = 32for i in range(3):x = Conv2D(base_conv * (2 ** (i)), (3, 3))(x)x = BatchNormalization()(x)x = Activation('relu')(x)x = MaxPooling2D(pool_size=(2, 2))(x)conv_shape = x.get_shape()x = Reshape(target_shape=(int(conv_shape[1]), int(conv_shape[2] * conv_shape[3])))(x)x = Dense(32)(x)x = BatchNormalization()(x)x = Activation('relu')(x)gru_1 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru1')(x)gru_1b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru1_b')(x)gru1_merged = add([gru_1, gru_1b])gru_2 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru2')(gru1_merged)gru_2b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru2_b')(gru1_merged)x = concatenate([gru_2, gru_2b])x = Dropout(0.25)(x)x = Dense(n_class, kernel_initializer='he_normal', activation='softmax')(x)base_model = Model(inputs=input_tensor, outputs=x)base_model.load_weights(model_path)return base_model

基于GRU的序列模型从OCR模型中修改的网络模型
model_sec_rec函数
model_path为模型weights文件路径 ocr部分的网络模型(keras模型) 输入层:164483的tensor
输出层:长度为7 的tensor,类别有len(chars)+1种

chars:chars = [u"京", u"沪", u"津", u"渝", u"冀", u"晋", u"蒙", u"辽", u"吉", u"黑", u"苏", u"浙", u"皖", u"闽", u"赣", u"鲁", u"豫", u"鄂", u"湘", u"粤", u"桂",u"琼", u"川", u"贵", u"云", u"藏", u"陕", u"甘", u"青", u"宁", u"新", u"0", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"A",u"B", u"C", u"D", u"E", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"N", u"P", u"Q", u"R", u"S", u"T", u"U", u"V", u"W", u"X",u"Y", u"Z",u"港",u"学",u"使",u"警",u"澳",u"挂",u"军",u"北",u"南",u"广",u"沈",u"兰",u"成",u"济",u"海",u"民",u"航",u"空"]

网络结构是三层卷积神经网络(CNN),以及四层内控循环单元(GRU)组成

3、输出参数

for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr):if confidence>0.7:image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3)))print("plate_str:")print(pstr)print("plate_confidence")print(confidence)

输入为一个Mat类型的图片 输出为识别的车牌字符串,以及confidence可信度,

  • HyperLPRLite.py LPR类中的SImpleRecognizePlateByE2E()函数

 def SimpleRecognizePlateByE2E(self,image):images = self.detectPlateRough(image,image.shape[0],top_bottom_padding_rate=0.1)res_set = []for j,plate in enumerate(images):plate, rect  =plateimage_rgb,rect_refine = self.finemappingVertical(plate,rect)res,confidence = self.recognizeOne(image_rgb)res_set.append([res,confidence,rect_refine])return res_set

首先用到detectPlateRough()函数

  • detectPlateRough函数是返回图像中所有车牌的边框在图片中的bbox,返回的是一个表示车牌区域坐标边框的list

对于每个车牌区域的for循环中,经过

  • filemappingVertical()函数

处理后输入

  • recognizeOne()函数

进行ocr识别

下面是SImpleRecognizePlateByE2E()函数中所用到的函数解析

- detectPlateRough()函数:车牌粗定位
def detectPlateRough(self,image_gray,resize_h = 720,en_scale =1.08 ,top_bottom_padding_rate = 0.05):if top_bottom_padding_rate>0.2:print("error:top_bottom_padding_rate > 0.2:",top_bottom_padding_rate)exit(1)height = image_gray.shape[0]padding = int(height*top_bottom_padding_rate)scale = image_gray.shape[1]/float(image_gray.shape[0])image = cv2.resize(image_gray, (int(scale*resize_h), resize_h))image_color_cropped = image[padding:resize_h-padding,0:image_gray.shape[1]]image_gray = cv2.cvtColor(image_color_cropped,cv2.COLOR_RGB2GRAY)watches = self.watch_cascade.detectMultiScale(image_gray, en_scale, 2, minSize=(36, 9),maxSize=(36*40, 9*40))cropped_images = []for (x, y, w, h) in watches:x -= w * 0.14w += w * 0.28y -= h * 0.15h += h * 0.3cropped = self.cropImage(image_color_cropped, (int(x), int(y), int(w), int(h)))cropped_images.append([cropped,[x, y+padding, w, h]])return cropped_images

利用多尺度检测detectMultiScale,得到可能的车牌,及其在原图中的rect位置

输入参数:

  • image_gray: 一个rgb图像,Mat类型
  • resize_h: 重新设定的图像大小
  • top_bottom_padding_rate: 表示要裁剪掉图片的上下部占比

这个函数实现的处理:

  • resize图像大小,cv2.resize函数,按照原来图像比例裁剪图片,根据输入的top_bottom_padding_rate如果是0.1,那么上面裁剪掉0.1height,下面也裁剪掉0.1height
  • 将图像从rgb转化为灰度 cv2.cvtColor函数,cv2.COLOR_RGB2GRAY
  • 根据前面的cv2.CascadeClassifier()物体检测模型,输入image_gray灰度图像,边框可识别的最小size,最大size,输出得到车牌在图像中的offset,也就是边框左上角坐标(x, y )以及边框高度( h )和宽度( w )
  • 对得到的车牌边框的bbox进行扩大,也就是宽度左右各扩大0.14倍,高度上下各扩大0.15倍。
  • 返回图片中所有识别出来的车牌边框bbox,这个list作为返回结果。
- filemappingVertical()函数
def finemappingVertical(self,image,rect):resized = cv2.resize(image,(66,16))resized = resized.astype(np.float)/255res_raw= (np.array([resized]))[0]res  =res_raw*image.shape[1]res = res.astype(np.int)H,T = resH-=3if H<0:H=0T+=2;if T>= image.shape[1]-1:T= image.shape[1]-1rect[2] -=  rect[2]*(1-res_raw[1] + res_raw[0])rect[0]+=res[0]image = image[:,H:T+2]image = cv2.resize(image, (int(136), int(36)))return image,rect

输入参数: 裁剪的车牌区域图像(Mat类型),rect也是裁剪的车牌部分的图像(Mat类型)

实现处理:
1.将原来车牌图像resize大小:66163
2.将原来灰度图颜色通道[0, 255]转化为float类型[0,1]
3.将输入66*16(float),输入进模型进行测试self.modelFineMapping.predict

- recognizeOne函数
   def recognizeOne(self,src):x_tempx = srcx_temp = cv2.resize(x_tempx,( 164,48))x_temp = x_temp.transpose(1, 0, 2)y_pred = self.modelSeqRec.predict(np.array([x_temp]))y_pred = y_pred[:,2:,:]return self.fastdecode(y_pred)

1.将前面的(136, 36)图像resize成(164, 48)
2.将图像转置,输入

hyperlpr.pipline.py 中的drawRectBox()函数

#打上boundingbox和标签
def drawRectBox(image,rect,addText):cv2.rectangle(image, (int(rect[0]), int(rect[1])), (int(rect[0] + rect[2]), int(rect[1] + rect[3])), (0,0, 255), 2,cv2.LINE_AA)cv2.rectangle(image, (int(rect[0]-1), int(rect[1])-16), (int(rect[0] + 115), int(rect[1])), (0, 0, 255), -1,cv2.LINE_AA)img = Image.fromarray(image)draw = ImageDraw.Draw(img)draw.text((int(rect[0]+1), int(rect[1]-16)), addText.decode("utf-8"), (255, 255, 255), font=fontC)imagex = np.array(img)return imagex

参考教程
HyperLPR车牌识别代码解读
hyperlpr学习笔记——demo学习

【车牌识别和动态称重系统】(二)基于树莓派+HyperLPR的中文车牌识别相关推荐

  1. 【车牌识别和动态称重系统】(四)基于stc51HX711的动态称重系统

    目录 元件清单 元件清单 树莓派3B+ stc51最小系统 HX711 木板 红外激光器 光电二极管 小车 车牌

  2. 【车牌识别和动态称重系统】(三)基于PyQt的UI设计

    目录 一.UI界面Mainwindow.py 二.业务逻辑主程序 main.py 三.演示效果 一.UI界面Mainwindow.py # -*- coding: utf-8 -*-# Form im ...

  3. 新超重车辆高速动态称重系统设计方案

    2021年最新超重车辆高速动态称重系统设计方案(专业完整版).pdf-Actionscript文档类资源-CSDN下载

  4. 超重车辆高速动态称重系统设计方案

    2021年最新超重车辆高速动态称重系统设计方案(专业完整版).pdf-Actionscript文档类资源-CSDN下载

  5. 最新超重车辆高速动态称重系统设计方案

    2021年最新超重车辆高速动态称重系统设计方案(专业完整版).pdf-Actionscript文档类资源-CSDN下载

  6. 动态称重c语言程序,动态称重系统 Dynamic Weighing System

    摘要: The main function of a dynamic weighing system is to measure the stress of the tyres of a dynami ...

  7. 智能称重系统应用车牌识别的优势

    无人值守磅房业务概述 一直以来,电子衡器在大宗物资行业得到了广泛的应用.但这些电子计量设备,却一直停留在辅助手工计量.人工读数.专人再汇总的层面上,严重滞后于企业整体的信息化管理进程. 在手工记录计量 ...

  8. 智能称重系统应用车牌识别的工作原理和优势-业内必看

    称重:测量与质量有关的数据,一般指重量.做名词时为:测量质量的过程.例如:我需要知道这件物品的重量,你们帮我称重.或者作为一个行业的名称:称重行业或者衡器行业.生活中的方方面面我们都需要得到重量这个数 ...

  9. 智能称重系统应用车牌识别解决方案

    传统称重管理系统需要在测量车辆载重的同时记录车牌号码,并建立对应关系,采用人工录入车牌方式,需要较长的等待时间,且容易产生失误甚至作弊等问题.车牌识别地磅称重系统是车牌识系统和称重两种系统相结合,实现 ...

最新文章

  1. 以金山界面库(openkui)为例思考和分析界面库的设计和实现——问题
  2. MyBatis Review——输入输出映射
  3. IntelliJ IDEA中跳转到上一个视图位置(向后/向前导航)的键盘快捷键
  4. python安装第三方库的三种方法
  5. 汇编伪指令EVEN(数据对齐的伪指令,使得下一个变量的起始地址是偶数字节的)
  6. 汉诺塔算法python_经典算法:汉诺塔
  7. 字符串常量池StringTable 你真的了解么
  8. Android允许应用程序使用Http明文网络传输
  9. js foreach 跳出循环_VUE.js
  10. php文件名函数,详解php 获取文件名basename()函数的用法
  11. cisco 交换机 获取 转发表_看完这份1113页的TCP/IP协议+路由与交换机,成功上岸字节跳动...
  12. DP(Nietzsche)的hu测 T1(状压dp)
  13. 解放生产力,VSCode使用小技巧
  14. win10系统多桌面切换方法及切换快捷键详细介绍
  15. 黑马C++学习总结之对象的初始化和清理
  16. MYSQL下载安装:
  17. [332]sql快速创建一张相同表结构的表
  18. IntelliJ IDEA 之 jdk Language level
  19. 5G/NR 学习笔记: RAR随机接入过程
  20. 深度分析|一文读懂银行数据架构体系

热门文章

  1. java做一个远程桌面程序
  2. C#中Guid.ToString (String)五种格式,以及将32位的GUID转为16位及其他格式
  3. Oracle ERP/EBS顾问就业前景 Oracle ERP/EBS顾问 培训
  4. 码农不识贝叶斯,虽知数据也枉然
  5. excel列值实现向下填充
  6. CAD2017打印图纸时无法找到公司自定义的打印样式
  7. 2020.7 Hexo手把手教程(还带视频教程)
  8. Zookeeper异常:FAILED TO WRITE PID与Permission denied
  9. java判断手机application/xhtml+xml_判断浏览器是否支持wml
  10. 一个即将毕业的软件工程硕士研究生的感慨