基于PaddleOCR实现车牌识别

基于PaddleOCR的车牌识别

    • 1.方案设计
    • 2.数据处理
      • 2.1 车牌数据集介绍
      • 2.2 数据预处理
    • 3.PaddleOCR模型介绍
      • 3.1 Paddle OCR算法列表
        • 3.2 安装PaddleOCR
        • 3.3 下载预训练模型
      • 4.模型训练
        • 4.1 训练检测模型
        • 4.2 CPU?GPU?
        • 4.3 训练识别模型
          • GPU训练 支持单卡,多卡训练
        • 4.4 问题及解决方案
      • 5.模型的评估
      • 6.模型导出
      • 7.模型推理
        • 结果图

1.方案设计

车牌识别车牌识别就是使用OCR(Optical Character Recognition,光学字符识别)技术识别各类机动车车牌信息。目前,车牌识别已广泛应用在停车场、收费站、道路等交通设施中,提供高效便捷的车辆管理服务。OCR通常包含文本检测和文本识别两个子任务:
1.文字检测: 检测图片中的文字位置
2. 文字识别: 对文字区域中的文字进行识别。
使用OCR来识别车牌流程如 图1 所示,首先检测出车牌的位置(下图红色框区域)、然后对检测出来的车牌进行识别,即可得到右边的可编辑文本:

基于PaddleOCR实现车牌识别_第1张图片

图1 车牌识别
我们使用飞桨PaddleOCR实现车牌识别,接下来就一起来看看实现原理及具体实现步骤吧~

2.数据处理

2.1 车牌数据集介绍

CCPD车牌数据集来源于Git里面。链接:https://github.com/detectRecog/CCPD
是采集人员在合肥停车场采集、手工标注得来,采集时间在早7:30到晚10:00之间。且拍摄车牌照片的环境复杂多变,包括雨天、雪天、倾斜、模糊等。CCPD数据集包含将近30万张图片、图片尺寸为720x1160x3,共包含8种类型图片,每种类型、数量及类型说明如下表:

类别 说明
ccpd_base 正常车牌
ccpd_db 光线较暗或较亮
ccpd_challenge 比较有挑战性的车牌
ccpd_fn 距离摄像头较远或较近
ccpd_np 没上牌的新车
ccpd_rotate 水平倾斜20%-50%, 垂直倾斜-10%-10%
ccpd_tilt 水平倾斜15%-45%,垂直倾斜15%-45%
ccpd_weather 雨天、雪天或者雾天的车牌
注:图2来源于开源车牌数据集[CCPD介绍](https://blog.csdn.net/qianbin3200896/article/details/103009221)

CCPD数据集中每张图像的名称包含了标注信息,例如图片名称为"025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg",每个名称可以通过分隔符’-'分为几部分,每部分解释:

  • 1.025:车牌区域占整个画面的比例;
  • 2.95_113: 车牌水平和垂直角度, 水平95°, 竖直113°
  • 3.154&383_386&473:标注框左上、右下坐标,左上(154, 383), 右下(386, 473)
  • 4.386&473_177&454_154&383_363&402:标注框四个角点坐标,顺序为右下、左下、左上、右上
  • 5.0_0_22_27_27_33_16:车牌号码映射关系如下: 第一个0为省份 对应省份字典provinces中的’皖’,;第二个0是该车所在地的地市一级代码,对应地市一级代码字典alphabets的’A’;后5位为字母和文字, 查看车牌号ads字典,如22为Y,27为3,33为9,16为S,最终车牌号码为皖AY339S
provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新"]

alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z']

ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

本实验我们只使用正常车牌即ccpd_base的数据进行训练。

2.2 数据预处理

1.先在项目下创建dataset文件夹
. …命令:mkdir dataset
2.解压ccpd数据集压缩包 并放到dataset文件夹下
…命令:unzip -q data/CCPD2019.zip -d dataset/CCPD
3.项目结构树如同:
基于PaddleOCR实现车牌识别_第2张图片

  • dataset:解压后放在dataset文件数据里
  • log:训练记录
  • output训练后的输出模型
  • Paddle OCR:文字识别模型
  • CCPD_test1.py :数据预处理的代码

3.将CCPD的数据格式转换PaddleOCR检测所需格式,创建CCPD_test1.py代码如下:

import os
import os.path as osp
import cv2
#创建字典列表
ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 
              'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y', 'Z', 
              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", 
            "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", 
            "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新"]

该代码主要是创建字典列表

#转换检测数据
#获取原图片的路径+图片标注信息
train_det = open('dataset/train_det.txt', 'w', encoding='UTF-8')
dev_det = open('dataset/dev_det.txt', 'w', encoding='UTF-8')


#转换识别数据
#获取截取车牌图片的路径文件+提取车牌文字的信息
train_rec = open('dataset/train_rec.txt', 'w', encoding='UTF-8')
dev_rec = open('dataset/dev_rec.txt', 'w', encoding='UTF-8')

if not osp.exists('dataset/img'):
    os.mkdir("dataset/img")

该代码主要是创建检测数据的train和val的txt文件与识别数据的train和val的文件。

  • train_det和dev_det划分8:2 是获取原图片的路径+图片被标注信息。比如:dataset/CCPD/ccpd_db/0462-1_13-212&516_542&633-542&633_236&627_212&516_518&522-0_0_26_32_19_24_29-198-116.jpg [{“transcription”:“皖A28V05”, “points”:[[212, 516], [518, 522], [542, 633], [236, 627]]}]
  • train_rec和dev_rec划分8:2 ,是获取已经截取出车牌图片的路径+提取车牌文字的信息;比如:dataset/img/000536.jpg 皖A28V05
  • dataset/img:是用来保存截取车牌的图片。

count = 0
total_num = len(os.listdir("dataset/home/aistudio/dataset/CCPD/ccpd_db"))
#训练样本数
train_num = int(total_num * 0.8)
# print(total_num, train_num)
for item in os.listdir("dataset/home/aistudio/dataset/CCPD/ccpd_db"):
    path = "dataset/home/aistudio/dataset/CCPD/ccpd_db/" + item
    #print(path)
    #print(item.split("-"))
    a1,a2,bboxs, points, labels, a3,a4 = item.split("-")
    # print(a1, a2, bboxs, points, labels, a3,a4 )
    bboxs = bboxs.split('_')
    # print(bboxs)
    x1, y1 = bboxs[0].split('&')
    x2, y2 = bboxs[1].split('&')
    # print("x1:y1", x1,y1)
    # print("x2:y2", x2,y2)
       #提取bboxs的x坐标,y坐标
    bboxs_new = [int(coord) for coord in [x1, y1, x2, y2]]
    print(bboxs_new)

#同理points
    points = points.split("_")
    #print(points)
    points = [point.split('&') for point in points]
    points_ = points[2:]+points[:2]
    #print(points_)
    points = []
    for point in points_:
        points.append([int(_) for _ in point])
    #print(points)

#同理 label
    labels = labels.split('_')
    #print(labels)
    prov =provinces[int(labels[0])]  #获取车牌地区名称
    #print(prov)
    plate_number = [ads[int(label)] for label in labels[1:]]  #将数字转换化车牌的数字
    labels = prov + ''.join(plate_number)  #合并起来
    #print(labels)

    # 获取检测训练检测框位置
    line_det = path+'\t'+'[{"transcription":"%s", "points":%s}]' % (labels, str(points))
    line_det = line_det[:] + "\n"
    print(line_det)

    #获取识别训练图片及标签
    img = cv2.imread(path)
    #print(img)
    crop = img[bboxs_new[1]:bboxs_new[3], bboxs_new[0]:bboxs_new[2], :]
    cv2.imwrite('dataset/img/%06d.jpg' % count, crop)
    line_rec = 'dataset/img/%06d.jpg\t%s\n' % (count, labels)
    print(line_rec)

    # 写入txt文件
    if count <= train_num:
        train_det.write(line_det)
        train_rec.write(line_rec)
    else:
        dev_det.write(line_det)
        dev_rec.write(line_rec)
    count+=1
train_det.close()
dev_det.close()
train_rec.close()
dev_rec.close()


#创建字典文件

with open("dataset/dict.txt", "w") as f:
    for key in ads +provinces:
        f.write(key+"\n")

运行命令:python CCPD_test1.py后,项目结构里多了五个文件。如图下:
基于PaddleOCR实现车牌识别_第3张图片
我来给大家详细介绍一下:

  • img文件夹:是保存截取车牌得图片。如同下:
  • 基于PaddleOCR实现车牌识别_第4张图片
  • train_det,dev_det文件:保存原始图片得路径和标注格式信息。如图下:
    基于PaddleOCR实现车牌识别_第5张图片
  • train_rec,dev_rec文件:是保存img文件夹下得截取车牌图片得路径和车牌文字信息。如图下:
    基于PaddleOCR实现车牌识别_第6张图片
  • dic.txt文件:是保存字典列表信息:如图下:
    -基于PaddleOCR实现车牌识别_第7张图片

3.PaddleOCR模型介绍

3.1 Paddle OCR算法列表

PaddleOCR中提供了如下文本检测算法和文本识别算法列表,以及每个算法在英文公开数据集上的模型和指标,主要用于算法简介和算法性能对比。

文本检测算法:
基于PaddleOCR实现车牌识别_第8张图片
文本识别算法:
基于PaddleOCR实现车牌识别_第9张图片
考虑车牌识别中字符数量较少,而且长度也固定,且为标准的印刷字体,所以无需使用过于复杂的模型。我们选择DBNet检测算法和CRNN识别模型作,PaddleOCR的检测模型目前支持两种backbone,分别是MobileNetV3、ResNet_vd系列,本实验两个模型均使用MobileNetV3作为其主干网络(Backbone)。

3.2 安装PaddleOCR

  • 1.安装命令:git clone clone https://github.com/PaddlePaddle/PaddleOCR
    如果因为忘了问题无法pull成功,可以选用码云上的托管即可:
    git clone !git clone https://gitee.com/paddlepaddle/PaddleOCR
  • 2.安装依赖
    pip install -r PaddleOCR/requirements.txt 下载并安装

3.3 下载预训练模型

  • 1.下载mobileNetv3的检测预训练模型
    wget -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV3_large_x0_5_pretrained.pdparams
  • 2.下载MobileNetV3.识别预训练模型
    !wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_mv3_none_bilstm_ctc_v2.0_train.tar
  • 3.解压识别预训练模型压缩文件
    tar -xvf pretrain_models/rec_mv3_none_bilstm_ctc_v2.0_train.tar
  • 4.删掉压缩文件(以免占空间)
    rm -rf pretrain_models/rec_mv3_none_bilstm_ctc_v2.0_train.tar

4.模型训练

4.1 训练检测模型

1.首先我们在configs/det/det_mv3_db.yml 文件中Train和Eval数据集得图片路径“data_dir"和标签路径”label_file_list".我自己修下是:
基于PaddleOCR实现车牌识别_第10张图片

4.2 CPU?GPU?

如果你安装的是paddle-cpu版本,或者没有gpu显卡的话,需要将det_mv3_db.yml配置文件中的use_gpu字段修改为false.

  • 如果你只有一个gpu显卡的话,单机单卡训练可以输入命令: python tools/train.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained

  • 如果你是土豪又很多gpu的话,单机多卡训练,需要通过–gpus 参数设置使用的gpu ID。输入命令: python -m paddle.distributed.launch --gpus ‘0,1,2,3’ tools/train.py -c configs/det/det_mv3_db.yml
    -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained

      上述指令中,通过-c 选择训练使用configs/det/det_db_mv3.yml配置文件。 有关配置文件的详细解释,请参考链接。
    
      您也可以通过-o参数在不需要修改yml文件的情况下,改变训练的参数,比如,调整训练的学习率为0.0001
    
      python tools/train.py -c configs/det/det_mv3_db.yml -o Optimizer.base_lr=0.0001
    

4.3 训练识别模型

如果您是在自己的数据集上训练的模型,并且调整了中文字符的字典文件,请注意修改配置文件configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml中的character_dict_path是否是所需要的字典文件。同时修改Train和Eval的图片路径data_dir和标签路径label_file_list。

同检测模型,如果您安装的是cpu版本,请将配置文件中的 use_gpu 字段修改为false

GPU训练 支持单卡,多卡训练

#单卡训练(训练周期长,不建议)
python tools/train.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml

#多卡训练,通过–gpus参数指定卡号
python -m paddle.distributed.launch --gpus ‘0,1,2,3’ tools/train.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml

PaddleOCR支持训练和评估交替进行, 可以在rec_chinese_lite_train_v2.0.yml中修改 eval_batch_step 设置评估频率,
默认每500个iter评估一次。评估过程中默认将最佳acc模型,保存为 output/rec_CRNN/best_accuracy。如果验证集很
大,测试将会比较耗时,建议减少评估次数,或训练完再进行评估。

4.4 问题及解决方案

**1.**遇到问题:Config use_gpu cannot be set as true while you are using paddlepaddle cpu version !
基于PaddleOCR实现车牌识别_第11张图片
解决方案:修改rec_chinese_lite_train_v2.0.yml 的use_gpu 字段为false

**2.**遇到问题:.No Images in train dataset, please ensure
基于PaddleOCR实现车牌识别_第12张图片
解决方案:1.标注工具识别结果没有内容, 2.修改batch_size_per_card字段

3.遇到问题:ABORT!!! Out of all 4 trainers, the trainer process with rank=[0, 1, 2, 3] was aborted. Please check its log.
在这里插入图片描述
**解决方案:**1.选用单卡训练。2.在代码里加一行:paddle.set_device(“gpu”)

5.模型的评估

当文字检测模型和文字识别模型训练完成后需要查看评估结果。可以执行下面的代码进行评估:
1.输入命令并执行(这是文字检测模型的评估代码):

python PaddleOCR/tools/eval.py -c PaddleOCR/configs/det/det_mv3_db.yml -o Global.checkpoints=output/db_mv3/best_accuracy.pdparams PostProcess.box_thresh=0.5 PostProcess.unclip_ratio=1.5

2.文字检测模型的评估结果如下:
在这里插入图片描述

  • 同理,文字识别模型的评估代码可以自己执行

3.从上面的结果可以看出,精准度:92%,召回率96%,hmean:94%,fps:24
hmean是一个综合指标,从先的表达式可以看出其值介与精度和召回率自己,其表达式为:
![在这里插入图片描述](https://img-blog.csdnimg.cn/7496f601fb2746308affc0101e2f2107.png

6.模型导出

将训练好 的模型转换成inference模型需要运行如下命令:

# 导出检测模型
python PaddleOCR/tools/export_model.py -c PaddleOCR/configs/det/det_mv3_db.yml -o Global.pretrained_model=output/db_mv3/best_accuracy Global.save_inference_dir=inference/db_mv3/
# 导出识别模型
python PaddleOCR/tools/export_model.py -c PaddleOCR/configs/det/det_mv3_db.yml -o Global.pretrained_model=output/db_mv3/best_accuracy Global.save_inference_dir=inference/db_mv3/

生成inference文件,如图下:基于PaddleOCR实现车牌识别_第13张图片

  其中:
  
  -c后面设置训练算法的yml配置文件
  -o配置可选参数
  Global.pretrained_model 参数设置待转换的训练模型地址,不用天津文件后缀。pdmodel,.pdopt或者。pdparams即可
  Global.save_inference_dir参数设置转换模型保存的地址

转inference模型时,使用的配置文件和训练时使用的配置文件相同。另外,还需要设置配置文件中的Global.pretrained_model参数,其指向训练中保存的模型参数文件。 转换成功后,在模型保存目录下有三个文件:
/inference/*/
├── inference.pdiparams # inference模型的参数文件
├── inference.pdiparams.info # inference模型的参数信息,可忽略
└── inference.pdmodel # inference模型的program文件

7.模型推理

在执行预测时,需要通过参数image_dir指定单张图像或者图像集合的路径、参数det_model_dir,cls_model_dirrec_model_dir分别指定检测方向分类识别的inference模型路径。参数use_angle_cls用于控制是否启用方向分类模型。如果训练时修改了文本的字典,在使用inference模型预测时,需要通过**–rec_char_dict_path**指定使用的字典路径,并且设置 rec_char_type=ch。可视化识别结果默认保存到 ./inference_results 文件夹里面。

python3 tools/infer/predict_system.py \
    --image_dir="./doc/imgs/00018069.jpg" \   #要预测图片的路径
    --det_model_dir="./inference/db_mv3/" \    #加入检测模型参数的路径
    --rec_model_dir="./inference/rec_chinese_lite_v2.0/" \    #加入识别模型参数的路径
    --rec_char_dict_path="../dict.txt" \                         #加入字典列表的路径
    --rec_char_type=ch \         #设置中文或者en
    --use_angle_cls=false \
    --output=../output/table \
    --vis_font_path=./doc/fonts/simfang.ttf    #加入字体

结果图

基于PaddleOCR实现车牌识别_第14张图片

创作不易,求关注和点赞!!
我是一名听力障碍人士,热爱学习热爱健身,想学习怎么健身的欢迎关注哈。有图有真相!!!

基于PaddleOCR实现车牌识别_第15张图片
基于PaddleOCR实现车牌识别_第16张图片

你可能感兴趣的:(深度学习,人工智能,计算机视觉,深度学习)