文章目录

  • 1 项目介绍
  • 2 环境配置
  • 3 数据集
    • 3.1 CCPD02020介绍
    • 3.2 解压数据集
    • 3.3 提取文本检测数据集
    • 3.4 提取文本识别数据集
  • 4 模型
    • 4.1 下载模型
    • 4.2 文本检测训练
    • 4.3 文本识别检测
    • 4.4 修改模型
  • 5 导出模型
  • 6 模型测试
  • 7 模型部署
    • 7.1 ONNX
  • 8 参考

1 项目介绍

车牌识别系统是指能够检测到受监控路面的车辆并自动提取车辆牌照信息(含汉字字符、英文字母、阿拉伯数字及号牌颜色)进行处理的技术。

本次是学习该博主https://blog.csdn.net/qq_36816848/category_12113641.html的项目智慧交通预测系统的一个总结,使用的是飞桨。
整个项目用DBNet进行文本检测(寻找文本位置),然后用RARE进行文本识别(识别图像中的文字)。
做的事情有整理数据集,然后部署模型训练模型导出模型,最终进行测试。下面也从这几个方面进行总结。

原地址:https://aistudio.baidu.com/aistudio/projectdetail/4542547

2 环境配置

因为用的是Paddle,因此需要先配置paddle环境。
首先,拉取PaddleOCR

#下载PaddleOCR
%cd ~/
!git clone -b release/2.1 https://github.com/PaddlePaddle/PaddleOCR.git

这里我执行时直接提示说已经存在,那就不用管了,可以安装使用PaddleOCR的环境

%cd PaddleOCR
!pip install -r requirments.txt
!pip install --upgrade scipy
# !pip install -r requirements.txt -i https://mirror.baidu.com/pypi/simple
%cd ..

如果没有什么问题,到这就算配置完成基本环境了。

3 数据集

3.1 CCPD02020介绍

本次使用的是CCPD02020,其训练集,验证集和测试集已经分组完成:

打开任一文件夹后发现文件名称特别长,形式如下,以-为分隔符:0139453125-91_266-231&462_435&531-429&529_231&531_236&462_435&468-0_0_3_26_24_30_32_32-116-38.jpg
其实这是该图像的标注

  1. 0139453125是区域
  2. 91_266对应两个角度, 水平91°, 竖直266°
  3. 231&462_435&531对应边界框左上(231, 462)和右下(435, 531)坐标
  4. 429&529_231&531_236&462_435&468对应四个角点坐标
  5. 0_0_3_26_24_30_32_32-116-38为映射为数字的车牌号码。第一个0为省份,根据映射关系provinces为皖。后面是数字和字母,根据对照表ads,比如第二个0为A,24是0。

映射关系

车牌省份:
provinces = [“皖”, “沪”, “津”, “渝”, “冀”, “晋”, “蒙”, “辽”, “吉”, “黑”, “苏”, “浙”, “京”, “闽”, “赣”, “鲁”, “豫”, “鄂”, “湘”, “粤”, “桂”, “琼”, “川”, “贵”, “云”, “藏”, “陕”, “甘”, “青”, “宁”, “新”, “警”, “学”, “O”]
字母和数字:
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’, ‘O’]

3.2 解压数据集


项目中,数据是以zip格式给的,需要解压:

!unzip -q data/data168819/CCPD2020.zip -d work/CCPD2020

注意,这里必须在根路径(/home/aistudio)下,可以用!pwd查看

3.3 提取文本检测数据集

我们了解到数据图像的名称是标签,其实是文本检测和文本识别结合到一起的标签。这里需要进行提取。

#转换检测数据,打开注释执行三次生成训练所需txt文件,分别为train、val、test。
%cd ~ # 返回根目录的作用
import os, cv2
words_list = ["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" ]con_list = ["皖", "沪", "津", "渝", "冀","晋", "蒙", "辽", "吉", "黑","苏", "浙", "京", "闽", "赣","鲁", "豫", "鄂", "湘", "粤","桂", "琼", "川", "贵", "云","西", "陕", "甘", "青", "宁","新"]count = 0
data = open('work/train_data_det.txt', 'w', encoding='UTF-8')
# data = open('work/val_data_det.txt', 'w', encoding='UTF-8')
# data = open('work/test_data_det.txt', 'w', encoding='UTF-8')for item in os.listdir('work/CCPD2020/CCPD2020/ccpd_green/train'):
# for item in os.listdir('work/CCPD2020/CCPD2020/ccpd_green/val'):
# for item in os.listdir('work/CCPD2020/CCPD2020/ccpd_green/test'):path = 'work/CCPD2020/CCPD2020/ccpd_green/train/'+item# path = 'work/CCPD2020/CCPD2020/ccpd_green/val/'+item# path = 'work/CCPD2020/CCPD2020/ccpd_green/test/'+item_, _, bbox, points, label, _, _ = item.split('-')points = points.split('_')points = [_.split('&') for _ in points]tmp = points[-2:]+points[:2]points = []for point in tmp:points.append([int(_) for _ in point])label = label.split('_')con = con_list[int(label[0])]words = [words_list[int(_)] for _ in label[1:]]label = con+''.join(words)line = path+'\t'+'[{"transcription": "%s", "points": %s}]' % (label, str(points))line = line[:]+'\n'data.write(line)# 下面的代码没有什么作用
# total = []
# with open('work/train_data_det.txt', 'r', encoding='UTF-8') as f:
#     for line in f:
#         total.append(line)# with open('work/val_data_det.txt', 'r', encoding='UTF-8') as f:
#     for line in f:
#         total.append(line)# with open('work/test_data_det.txt', 'r', encoding='UTF-8') as f:
#     for line in f:
#         total.append(line)# with open('work/train_det.txt', 'w', encoding='UTF-8') as f:
#     for line in total[:-500]:
#         f.write(line)# with open('work/dev_det.txt', 'w', encoding='UTF-8') as f:
#     for line in total[-500:]:
#         f.write(line)


这三块,对应改变注释执行即可(总共进行三次)。下面一块被注释的代码没起到什么作用。
最终得到三个文件

  1. train_data_det
  2. val_data_det
  3. test_data_det

三个文件中,每一行的内容都和下面很类似work/CCPD2020/CCPD2020/ccpd_green/train/303154296875-91_93-224&467_530&571-530&571_224&564_224&470_527&467-0_0_3_24_32_25_33_25-78-103.jpg [{"transcription": "皖AD08191", "points": [[224, 470], [527, 467], [530, 571], [224, 564]]}]
其中空格作为分割,前面是图像的路径,后面是标签(图中文本,图中被框出的文本的四个角的坐标)

3.4 提取文本识别数据集

#识别数据:转换成PaddleOCR使用的格式(图片名+内容),打开注释执行三次生成训练所需txt文件,分别为train、val、test。
%cd ~  # 切换到根路径
import os, cv2
words_list = ["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" ]con_list = ["皖", "沪", "津", "渝", "冀","晋", "蒙", "辽", "吉", "黑","苏", "浙", "京", "闽", "赣","鲁", "豫", "鄂", "湘", "粤","桂", "琼", "川", "贵", "云","西", "陕", "甘", "青", "宁","新"]# if not os.path.exists('work/img'):   #所有数据集都放入一个文件夹,这里其实我没有用到
#     os.mkdir('work/img')#训练、验证、测试集分开三个文件夹对应解开注释依次执行三次
# if not os.path.exists('work/train_rec_img'):
#     os.mkdir('work/train_rec_img')# if not os.path.exists('work/val_rec_img'):
#     os.mkdir('work/val_rec_img')if not os.path.exists('work/test_rec_img'):os.mkdir('work/test_rec_img')count = 0# data = open('work/train_data_rec.txt', 'w', encoding='UTF-8')
# data = open('work/val_data_rec.txt', 'w', encoding='UTF-8')
data = open('work/test_data_rec.txt', 'w', encoding='UTF-8')# for item in os.listdir('work/CCPD2020/CCPD2020/ccpd_green/train'):
# for item in os.listdir('work/CCPD2020/CCPD2020/ccpd_green/val'):
for item in os.listdir('work/CCPD2020/CCPD2020/ccpd_green/test'):# path = 'work/CCPD2020/CCPD2020/ccpd_green/train/'+item# path = 'work/CCPD2020/CCPD2020/ccpd_green/val/'+itempath = 'work/CCPD2020/CCPD2020/ccpd_green/test/'+item#原来的 path = 'work/CCPD2020/ccpd_base/'+item_, _, bbox, _, label, _, _ = item.split('-')bbox = bbox.split('_')x1, y1 = bbox[0].split('&')x2, y2 = bbox[1].split('&')label = label.split('_')con = con_list[int(label[0])]words = [words_list[int(_)] for _ in label[1:]]label = con+''.join(words)bbox = [int(_) for _ in [x1, y1, x2, y2]]img = cv2.imread(path)crop = img[bbox[1]:bbox[3], bbox[0]:bbox[2], :]# cv2.imwrite('work/train_rec_img/%06d.jpg' % count, crop)# data.write('work/train_rec_img/%06d.jpg\t%s\n' % (count, label))# cv2.imwrite('work/val_rec_img/%06d.jpg' % count, crop)# data.write('work/val_rec_img/%06d.jpg\t%s\n' % (count, label))cv2.imwrite('work/test_rec_img/%06d.jpg' % count, crop)data.write('work/test_rec_img/%06d.jpg\t%s\n' % (count, label))count += 1
data.close()with open('work/word_dict.txt', 'w', encoding='UTF-8') as f:for line in words_list+con_list:f.write(line+'\n')# 下面的代码没有什么作用
# total = []
# with open('work/train_data_rec.txt', 'r', encoding='UTF-8') as f:
#     for line in f:
#         total.append(line)# with open('work/val_data_rec.txt', 'r', encoding='UTF-8') as f:
#     for line in f:
#         total.append(line)# with open('work/test_data_rec.txt', 'r', encoding='UTF-8') as f:
#     for line in f:
#         total.append(line)

同样25-3438-4042-4446-4864-71五块,对应改变注释执行即可(总共进行三次)。下面一块被注释的代码没起到什么作用。
data.close()后面的with模块,生成的是标签映射关系,如A对应1,43对应吉。
最终,生成文件及目录

  1. word_dicrt.txt
  2. train_data_rec.txt
  3. val_data_rec.txt
  4. test_data_rec.txt
  5. train_rec_img
  6. val_rec_img
  7. test_rec_img

其中234是训练文件,每一行内容类似work/train_rec_img/000000.jpg 皖AD08191。空格隔开,前面是图像的路径,后面是理想下识别得到的文字。
567是文本识别的训练集,里面是训练,验证,测试图像。

到这里数据集就准备完毕了,其实还是有很多注释的部分,暂时没遇到需要这些的东西

4 模型

PaddleOCR提供的检测与识别模型

模型库:https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.6/doc/doc_ch/models_list.md#1.1
该博主用以MobileNetV3为backbone的DBNet和RARE进行示例。
其中DBNet原理总结:https://blog.csdn.net/weixin_51691064/article/details/130272531

4.1 下载模型

首先下载预训练模型

!wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/ch_models/ch_det_mv3_db.tar
!wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_attn.tar

注意,这里是在PaddleOCR文件夹下完成的。其中第一个是文本检测模型DBNet,第二个是文本识别模型RARE。
解压模型参数

%cd pretrain_models
!tar -xf ch_det_mv3_db.tar && rm -rf ch_det_mv3_db.tar
!tar -xf rec_mv3_tps_bilstm_attn.tar && rm -rf rec_mv3_tps_bilstm_attn.tar

%cd pretrain_models 是进入PaddleOCR的pretrain_models文件夹,即预训练模型下载的位置。解压后两个压缩包被删除,pretrain_models目录下多了两个文件夹,即det_mv3_dbrec_mv3_tps_bilstm_attn,分别是文本检测模型和文本识别模型。
进去后,emmm…看不懂

4.2 文本检测训练

为了训练模型,我们需要修改配置文件下数据集的路径。首先找到PaddleOCR目录下的configs/det/det_mv3_db.yml,可以看到里面的内容如下:

其中包含了epoch总数等各种信息。
接下来,打开里面的数据集文件路径./configs/det/det_db_icdar15_reader.yml修改数据集路径。该文件内容如下:

这里图像数据路径写根路径/home/aistudio/即可,猜测是执行train.py,自动数据集将后面的路径进行拼接了。这就要求我们解压数据集时不要修改解压路径,否则可能出错。

修改完数据路径后,进行训练:

%cd ~/PaddleOCR
# 设置PYTHONPATH路径
%env PYTHONPATH=$PYTHONPATH:.
# GPU单卡训练
%env CUDA_VISIBLE_DEVICES=0
!python3 tools/train.py -c configs/det/det_mv3_db.yml

%cd ~/PaddleOCR作用是返回PaddleOCR目录,如果手动返回了,不要这行也可以。
我用的环境是V100 16G,挺慢的。因此仅仅训练了10个epoch,可以选择更大的。
保存的模型参数等文件如下图:

4.3 文本识别检测

和文本检测很像,也是先修改数据集路径,然后训练。
这次,先找到PaddleOCR目录下的configs/rec/rec_mv3_tps_bilstm_attn.yml,内容如下:

其中的东西也与文本检测类似,重点关注配置数据集路径文件./configs/rec/rec_chinese_reader.yml
打开后如下:

同样,图像数据设置为根路径即可,后面路径训练脚本自动拼接,要求提取文本识别数据集中的路径代码不能随意更改
然后执行训练脚本

# %cd ~/PaddleOCR
# GPU单卡训练
%env CUDA_VISIBLE_DEVICES=0
!python3 tools/train.py -c configs/rec/rec_mv3_tps_bilstm_attn.yml

上面文本检测和文本识别脚本都是单卡训练,如果要多卡训练,比如四张,%env CUDA_VISIBLE_DEVICES=0改为%env CUDA_VISIBLE_DEVICES=0,1,2,3

到这里模型训练部分就完成了

4.4 修改模型

假如我们不想使用DBNet或者RARE,可以对模型进行修改。
首先选择模型,有两个入口:

  1. 拉取的PaddleOCR的README文件
  2. 官方模型库https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.6/doc/doc_ch/models_list.md

其次,下载模型后,参照4.1节中解压模型压缩文件,路径最好不变。
最后修改配置文件,比如文本检测:

%cd ~/PaddleOCR
# 设置PYTHONPATH路径
%env PYTHONPATH=$PYTHONPATH:.
# GPU单卡训练
%env CUDA_VISIBLE_DEVICES=0
!python3 tools/train.py -c configs/det/det_mv3_db.yml

从上面可以看到DBNet配置文件configs/det/det_mv3_db.yml,那么就到里面去修改pretrain_weights的值为解压的模型文件路径。
如果下载的模型对配置文件有要求,将上述训练命令中-c的参数修改为指定配置文件。
比如

我要使用第一个,要求的配置文件是ch_PP-OCRv3_det_cml.yml,那就将-c设置为上述配置文件。修改的模型路径也是上述配置文件的pretrain_weights值。

5 导出模型

%cd ~/PaddleOCR
# 导出检测模型
!python3 tools/export_model.py \-c configs/det/det_mv3_db.yml \-o Global.checkpoints=./myoutput/det_db/best_accuracy \Global.save_inference_dir=./inference/mydet_db# 导出识别模型
!python3 tools/export_model.py \-c configs/rec/rec_mv3_tps_bilstm_attn.yml \-o Global.checkpoints=./myoutput/rec_RARE_atten_new/best_accuracy \Global.save_inference_dir=./inference/myrec_rare

我第一次执行时有两个包没有安装,pip安装即可。
其次,导出模型前,PaddleOCR/interface/mydet_dbPaddleOCR/interface/myrec_rare路径下已经存在model和params两个文件。导出后仍是这两个名称的文件,在没有报错的情况下,是正常的(覆盖了)。

6 模型测试

首先安装深度学习数据增强库imgaug:

!pip install imgaug

然后执行训练脚本

%cd ~/PaddleOCR
!python3 tools/infer/predict_system.py \--image_dir="../imgtest" \--det_model_dir="./inference/mydet_db" \--rec_model_dir="./inference/myrec_rare" \--rec_image_shape="3, 32, 320" \--rec_char_type="ch" \--rec_algorithm="RARE" \--use_space_char False \--max_text_length 8 \--rec_char_dict_path="../word_dict.txt" \--use_gpu False

结果类似即正确:

原文中结果的置信度基本接近1,可能我这是文本检测训练的不足,置信度略低。

7 模型部署

7.1 ONNX

首先安装环境:

!pip install onnx==1.10.1 onnxruntime-gpu==1.10 paddle2onnx
!paddle2onnx --model_dir ./stac --model_filename model.pdmodel --params_filename model.pdiparams --opset_version 11 --save_file result.onnx

导出检测模型

%cd ~/PaddleOCR
!paddle2onnx \--model_dir ./inference/mydet_db \--model_filename __model__ \--params_filename __params__ \--save_file ./out_onnx/det/det.onnx \--opset_version 12 \--enable_onnx_checker True

其中--model_dir是模型的保存路径,--save_file是onnx文件的保存路径,修改这两个即可。
导出识别模型

%cd ~/PaddleOCR
!paddle2onnx \--model_dir ./inference/rec_RARE_attn_new \--model_filename __model__ \--params_filename __params__ \--save_file ./out_onnx/rec/rec.onnx \--opset_version 12 \--enable_onnx_checker True

8 参考

https://aistudio.baidu.com/aistudio/projectdetail/4542547
https://blog.csdn.net/qq_36816848/category_12113641.html
https://aistudio.baidu.com/aistudio/projectdetail/4359114?channelType=0&channel=0

基于飞桨实现项目1 车牌识别相关推荐

  1. 基于飞桨实现手写数字识别2

    参考课程笔记:https://aistudio.baidu.com/aistudio/projectdetail/728143 上篇https://mp.csdn.net/console/editor ...

  2. 搭建基于飞桨的OCR工具库,总模型仅8.6M的超轻量级中文OCR,单模型支持中英文数字组合识别、竖排文本识别、长文本识别的PaddleOCR

    介绍 基于飞桨的OCR工具库,包含总模型仅8.6M的超轻量级中文OCR,单模型支持中英文数字组合识别.竖排文本识别.长文本识别.同时支持多种文本检测.文本识别的训练算法. 相关链接 PaddleOCR ...

  3. 基于飞桨 DeepLabV3+实现人体肾组织图像中肾小球识别

    基于飞桨 DeepLabV3+实现人体肾组织图像中肾小球识别 一.项目背景 估计显示,地球上有超过70亿人,银河系中有3000亿颗恒星.相比之下,成年人体内含有37万亿个细胞.确定这些细胞之间的功能和 ...

  4. Coding-Party 基于飞桨的农作物智能识别系统病虫害识别

    目录 Coding-Party 基于飞桨的农作物智能识别系统 病虫害识别 Coding-Party 基于飞桨的农作物智能识别系统 联合国粮食及农业组织最近的一份报告表明,每年农业生产的自然损失中有三分 ...

  5. 智能交通组合拳--飞桨实现车辆类别/车牌/车速检测、跨境头跟踪、车流密度检测、逆行检测

    智能交通组合拳–飞桨实现车辆类别/车牌/车速检测.跨境头跟踪.车流密度检测.逆行检测 总体简介 这个项目的代码和文件全部都已经上传到百度aistudio上,有需要的伙伴的可以搜索下面的链接找到,那里已 ...

  6. 基于“飞桨”的深度学习智能车

    本文作者:吴东昱,北京钢铁侠科技深度学习算法工程师 前言   我在观察历届智能车竞赛以及教学实验中发现,采用传统视觉算法的视觉智能车只能在特定赛道中行驶,一旦赛道环境改变,必须修改大量的代码才能运行. ...

  7. 基于飞桨实现高精度岩相自动分析,助力油气田勘探开发设计

    1. 概述 1.1 行业背景与痛点 岩相分析是以岩石薄片的微观描述和分类为基础的研究工作,也是沉积和成岩研究的一项重要技术,对于油气勘探开发的工程实践具有基础性指导地位.通过薄片分析矿物的比例.分布. ...

  8. 基于飞桨图像分类套件PaddleClas的柠檬分类竞赛实战

    前情提要   通过之前教程中的学习,相信大家对于如何搭建一个分类网络已经清晰了.那么我们不禁会想,有没有更快速的尝试模型及技巧的方法呢?因为我们在上一次课程中使用的代码都需要自己进行开发,自己写需要很 ...

  9. 基于飞桨的智能课堂行为分析与考试作弊检测系统

    智慧课堂:基于飞桨的智能化课堂 本项目主要实现了课堂专注度分析与考试作弊检测两个功能,通过对学生的姿态检测,可以有效的辅助老师有效监督学生的学习上课情况,对学生的上课行为进行分析及评分,避免出现课堂不 ...

最新文章

  1. C语言中整型浮点型在计算机中的存储
  2. 内存可见性和原子性:Synchronized和Volatile的比较
  3. fiddler对手机进行抓包
  4. CF453C-Little Pony and Summer Sun Celebration【构造】
  5. 一篇文章看清楚JDK13的特性!
  6. sql2000执行sql2005导出的数据脚本时出现“提示含有超过64K限度的行”(转)
  7. 计算机网络原理学习笔记
  8. 基于Simulink的转速、电流双闭环直流调速系统的建模与仿真
  9. Linux EXT4文件系统简介
  10. adb快速截图小脚本
  11. 基于PT100的温度测量系统设计
  12. power bi报表html,数据可视化系列:Power BI基于Web数据的报表制作(经典级示例)
  13. What's the AOP?
  14. 安卓修炼之路必要要知道的要求和建议
  15. c语言标识首字母不能是,c语言的标识符由哪字符组成
  16. vue项目在vscode中编译eslint报错没显示红色波浪线提示
  17. 华为鸿蒙系统研发砸了多少钱,5000研发人员,打造生态系统砸10亿美元,为鸿蒙华为几乎不惜代价!...
  18. 但使龙城飞将在,不教胡马度阴山
  19. 已知正方形面积求边长c语言,正方形知道面积怎么求边长.
  20. 2016下半年计算机水平模拟考试系统,2016下半年计算机等级考试试题及答案

热门文章

  1. 最远对踵点 旋转卡壳
  2. 在html项目中使用webpack编译es6语法
  3. html抢答器代码,基于FPGA的四路抢答器的Verilog HDL代码.doc
  4. 软件需求管理用例方法 pdf_一卡通考勤门禁管理软件需求描述
  5. Topaz Video AI for mac(视频增强和修复工具)
  6. 一款程序员值得拥有的机械键盘:Keychron K3
  7. 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现Eureka(Finchley版本)
  8. Mac平台epub阅读器推荐
  9. Java实验一—创建用于计算身体质量指数的BMI类
  10. 2017word计算机操作题,2017职称计算机考试Word操作试题及答案