车牌识别之二:车牌OCR识别(包含全部免费的数据集、源码和模型下载)

重要的事说在前面

数据集:
https://pan.baidu.com/s/1YayAeqgdqZ0u2vSovd0Z4w
提取码:8888
如果作者误删的话,参考这里下载的CCPD2019.tar.xz和CCPD2020.zip获取。

背景

上一节车牌识别之一:车牌检测(包含全部免费的数据集、源码和模型下载)利用物体检测技术将车牌已经定位出来了,包括外包框和四个角点,本文进行车牌区域的OCR识别探讨

依赖

paddlepaddle-gpu==2.6.2
shapely
scikit-image
six
pyclipper
lmdb
tqdm
numpy
rapidfuzz
opencv-python
opencv-contrib-python
cython
Pillow
pyyaml
requests
albumentations==1.4.10
# to be compatible with albumentations
albucore==0.0.13

安装paddleocr

paddleocr是目前认为针对中文识别精度最高的框架,这是本项目的不二选择

git clone https://github.com/PaddlePaddle/PaddleOCR
cd PaddleOCR
pip install -v -e .

本项目所测试的paddleocr的版本是2.9.0

将数据集下载至data/ccpd并解压

解压后的数据目录为:

data/ccpd
├── CCPD2019
├── CCPD2019.tar.xz
├── CCPD2020
└── CCPD2020.zip

生成训练测试数据集

然后解压后的数据以5:1的大小生成训练数据, 新建gen_paddleocr_format_data.py,内容为:

import os,sys
import glob
import random
import cv2
import numpy as np
from tqdm import tqdm
provincelist = ["皖", "沪", "津", "渝", "冀","晋", "蒙", "辽", "吉", "黑","苏", "浙", "京", "闽", "赣","鲁", "豫", "鄂", "湘", "粤","桂", "琼", "川", "贵", "云","西", "陕", "甘", "青", "宁","新"]wordlist = ["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"]
def gen_paddlecor_format_data(rootpath, dstpath):os.makedirs(dstpath, exist_ok=True)os.makedirs(os.path.join(dstpath, 'train'), exist_ok=True)os.makedirs(os.path.join(dstpath, 'val'), exist_ok=True)list_images = glob.glob(f'{rootpath}/**/*.jpg', recursive=True)for imgpath in tqdm(list_images):if "/ccpd_np/" in imgpath:#cpd_np是没有车牌的图片,跳过continue#print(imgpath)img = cv2.imread(imgpath)# 图像名imgname = os.path.basename(imgpath).split('.')[0]# 根据图像名分割标注_, _, box, points, label, brightness, blurriness = imgname.split('-')# --- 边界框信息box = box.split('_')box = [list(map(int, i.split('&'))) for i in box]box_w = box[1][0]-box[0][0]box_h = box[1][1]-box[0][1]filename = label# --- 读取车牌号label = label.split('_')# 省份缩写province = provincelist[int(label[0])]# 车牌信息words = [wordlist[int(i)] for i in label[1:]]# 车牌号label = province+''.join(words)#print(label)img_plate = img[box[0][1]:box[1][1], box[0][0]:box[1][0]]random_number = random.uniform(0, 1)if random_number > 0.1:#traindst_img_path = os.path.join(dstpath, 'train', f"{filename}.jpg")labelfileadd = os.path.join(dstpath, 'train.txt',)labelcontent = f"train/{filename}.jpg\t{label}\n"else:#valdst_img_path = os.path.join(dstpath, 'val', f"{filename}.jpg")labelfileadd = os.path.join(dstpath, 'val.txt',)labelcontent = f"val/{filename}.jpg\t{label}\n"cv2.imwrite(dst_img_path, img_plate)with open(labelfileadd, 'a') as f:f.write(labelcontent)
def gent_license_dict(dict_save_path):allwordlist = wordlist + provincelistallwordlist.sort()print(allwordlist)with open(dict_save_path, 'w') as f:for word in allwordlist:f.write(word+'\n')
if __name__ == '__main__':if len(sys.argv)!= 3:print("Usage: python gen_paddlecor_format_data.py <ccpd_dataset_path> <output_path>")exit(1)gen_paddlecor_format_data(sys.argv[1], sys.argv[2])gent_license_dict("data/ccpd_paddleocr/dict.txt")

运行命令:

python gen_yolo_format_data.py data/ccpd data/ccpd_paddleocr

生成识别训练集的层级目录:

ccpd_paddleocr/
├── dict.txt
├── train
├── train.txt
├── val
└── val.txt

下载预训练模型

点这里获取,然后在pretrain_models中解压

配置文件

PaddleOCR/coofigs/rec/PP-OCRv3中,新建ch_PP-OCRv3_rec_liecece.yml,其内容为

Global:debug: falseuse_gpu: trueepoch_num: 100log_smooth_window: 20print_batch_step: 10save_model_dir: ./output/rec_ppocr_licence_v3save_epoch_step: 3eval_batch_step: [0, 2000]cal_metric_during_train: truepretrained_model: pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy.pdparamscheckpoints:save_inference_dir:use_visualdl: falseinfer_img: doc/imgs_words/ch/word_1.jpgcharacter_dict_path: data/ccpd_paddleocr/dict.txt#character_dict_path: ppocr/utils/ppocr_keys_v1.txtmax_text_length: &max_text_length 12infer_mode: falseuse_space_char: falsedistributed: truesave_res_path: ./output/rec/predicts_licence_ppocrv3.txtOptimizer:name: Adambeta1: 0.9beta2: 0.999lr:name: Cosinelearning_rate: 0.001warmup_epoch: 5regularizer:name: L2factor: 3.0e-05Architecture:model_type: recalgorithm: SVTR_LCNetTransform:Backbone:name: MobileNetV1Enhancescale: 0.5last_conv_stride: [1, 2]last_pool_type: avglast_pool_kernel_size: [2, 2]Head:name: MultiHeadhead_list:- CTCHead:Neck:name: svtrdims: 64depth: 2hidden_dims: 120use_guide: TrueHead:fc_decay: 0.00001- SARHead:enc_dim: 512max_text_length: *max_text_lengthLoss:name: MultiLossloss_config_list:- CTCLoss:- SARLoss:PostProcess:  name: CTCLabelDecodeMetric:name: RecMetricmain_indicator: accignore_space: FalseTrain:dataset:name: SimpleDataSetdata_dir: data/ccpd_paddleocr/ext_op_transform_idx: 1label_file_list:- data/ccpd_paddleocr/train.txttransforms:- DecodeImage:img_mode: BGRchannel_first: false- RecConAug:prob: 0.5ext_data_num: 2image_shape: [48, 320, 3]max_text_length: *max_text_length- RecAug:- MultiLabelEncode:- RecResizeImg:image_shape: [3, 48, 320]- KeepKeys:keep_keys:- image- label_ctc- label_sar- length- valid_ratioloader:shuffle: truebatch_size_per_card: 128drop_last: truenum_workers: 4
Eval:dataset:name: SimpleDataSetdata_dir: data/ccpd_paddleocr/label_file_list:- data/ccpd_paddleocr/val.txttransforms:- DecodeImage:img_mode: BGRchannel_first: false- MultiLabelEncode:- RecResizeImg:image_shape: [3, 48, 320]- KeepKeys:keep_keys:- image- label_ctc- label_sar- length- valid_ratioloader:shuffle: falsedrop_last: falsebatch_size_per_card: 128num_workers: 4

开始训练

python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_liecece.yml -o Global.pretrained_model=./pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams

训练过程

...[2024/12/17 18:25:33] ppocr INFO: epoch: [85/100], global_step: 215960, lr: 0.000101, acc: 0.992187, norm_edit_dis: 0.998884, CTCLoss: 0.029224, SARLoss: 0.201802, loss: 0.234332, avg_reader_cost: 0.23257 s, avg_batch_cost: 0.42802 s, avg_samples: 128.0, ips: 299.05106 samples/s, eta: 4:16:11, max_mem_reserved: 9719 MB, max_mem_allocated: 9308 MB
[2024/12/17 18:25:37] ppocr INFO: epoch: [85/100], global_step: 215970, lr: 0.000101, acc: 0.984375, norm_edit_dis: 0.997768, CTCLoss: 0.037204, SARLoss: 0.198890, loss: 0.242042, avg_reader_cost: 0.15294 s, avg_batch_cost: 0.35018 s, avg_samples: 128.0, ips: 365.52281 samples/s, eta: 4:16:07, max_mem_reserved: 9719 MB, max_mem_allocated: 9308 MB
[2024/12/17 18:25:41] ppocr INFO: epoch: [85/100], global_step: 215980, lr: 0.000101, acc: 0.984375, norm_edit_dis: 0.997210, CTCLoss: 0.071525, SARLoss: 0.196448, loss: 0.259408, avg_reader_cost: 0.20332 s, avg_batch_cost: 0.39946 s, avg_samples: 128.0, ips: 320.43009 samples/s, eta: 4:16:03, max_mem_reserved: 9719 MB, max_mem_allocated: 9308 MB
[2024/12/17 18:25:44] ppocr INFO: epoch: [85/100], global_step: 215990, lr: 0.000101, acc: 0.984375, norm_edit_dis: 0.997280, CTCLoss: 0.063012, SARLoss: 0.195158, loss: 0.248105, avg_reader_cost: 0.10683 s, avg_batch_cost: 0.30685 s, avg_samples: 128.0, ips: 417.13550 samples/s, eta: 4:15:59, max_mem_reserved: 9719 MB, max_mem_allocated: 9308 MB
[2024/12/17 18:25:48] ppocr INFO: epoch: [85/100], global_step: 216000, lr: 0.000101, acc: 0.988281, norm_edit_dis: 0.997280, CTCLoss: 0.038435, SARLoss: 0.206021, loss: 0.248680, avg_reader_cost: 0.22180 s, avg_batch_cost: 0.41802 s, avg_samples: 128.0, ips: 306.20233 samples/s, eta: 4:15:56, max_mem_reserved: 9719 MB, max_mem_allocated: 9308 MB
eval model:: 100%|██████████████████████████████████████████████████████████| 284/284 [00:16<00:00, 16.73it/s]
[2024/12/17 18:26:05] ppocr INFO: cur metric, acc: 0.9785529428504617, norm_edit_dis: 0.9959577823762181, fps: 3396.2841101808885
[2024/12/17 18:26:06] ppocr INFO: save best model is to ./output/rec_ppocr_licence_v3/best_accuracy
[2024/12/17 18:26:06] ppocr INFO: best metric, acc: 0.9785529428504617, is_float16: False, norm_edit_dis: 0.9959577823762181, fps: 3396.2841101808885, best_epoch: 85
...

我们看到测试精度97.86%,说明识别模型还是很不错的。

训练结果保存

output/rec_ppocr_licence_v3/
├── best_accuracy.pdopt
├── best_accuracy.pdparams
├── best_accuracy.states
├── best_model
│   ├── model.pdopt
│   └── model.pdparams
├── config.yml
├── latest.pdopt
├── latest.pdparams
├── latest.states
└── train.log

分数最高的模型保存在output/rec_ppocr_licence_v3/best_model中。

接下来随便找几张先手动切出来看一下识别结果

以下是推理命令

python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_liecece.yml -o Global.pretrained_model=./output/rec_ppocr_licence_v3/best_model/model Global.infer_img=../license_plate/test_plate.jpg

在这里插入图片描述 在这里插入图片描述

结果显示

infer_img: ../license_plate/test_plate.jpgresult: 皖AD49590	0.9894002079963684
infer_img: ../license_plate/22_16_5_0_25_24_25.jpgresult: 川SFA101	

一点点遗憾

这个模型用于普通场景下的车牌识别,是足够用的了。但是在训练的字典中,没有发现特殊车牌,比较双行文字,大使馆,军车等,这也是因为数据集有缺失导致,只能在以后收集更加完整的数据集后,再次使用相同的方法进行训练了。

附模型

点这里下载

车牌识别之一:车牌检测(包含全部免费的数据集、源码和模型下载)
车牌识别之三:检测+识别的onnx部署(免费下载高精度onnx模型)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/64384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单北斗+鸿蒙系统+国产芯片,遨游防爆手机自主可控“三保险”

在当今全球科技竞争日益激烈的背景下&#xff0c;技术自主可控的重要性愈发凸显。它不仅关乎国家安全&#xff0c;更是推动产业升级和经济发展的关键。特别是在一些特殊领域&#xff0c;如防爆通信&#xff0c;自主可控的技术更是不可或缺。遨游通讯推出了一款融合了单北斗、鸿…

【zlm】 webrtc源码讲解三(总结)

目录 setsdp onwrite ​编辑 play 参考 setsdp onwrite play 参考 【zlm】 webrtc源码讲解_zlm webrtc-CSDN博客 【zlm】 webrtc源码讲解&#xff08;二&#xff09;_webrtc 源码-CSDN博客

打造专业的电子商务维护页面:如何确保用户信任与业务连续性

在电子商务网站的运营过程中&#xff0c;维护是不可避免的一部分。然而&#xff0c;网站的短暂下线如果处理不当&#xff0c;可能会导致用户流失和销售额的下降。为了在维护期间依然保持客户的信任与业务的连续性&#xff0c;创建一个专业的维护页面至关重要。本文将为您详细介…

【python因果库实战5】使用银行营销数据集研究营销决策的效果5

目录 接触次数的效应 重新定义治疗变量和潜在混杂因素 更深入地审视干预情景 逆概率加权 标准化 总结及与非因果分析的比较 接触次数的效应 我们现在转而研究当前营销活动中接触次数的数量&#xff08;campaign&#xff09;对积极结果发生率的影响。具体来说&#xff0c;…

单步调试Android Framework——App冷启动

纸上得来终觉浅&#xff0c;绝知此事要躬行。 —— [宋]陆游 基于aosp_cf_x86_64_phone-trunk_staging-eng &#xff0c; 下面是具体断点位置。 第一部分&#xff0c;桌面launcher进程 com.android.launcher3.touch.ItemClickHandler onClickonClickAppShortcutstartAppShor…

【5G】5G的主要架构选项

最初&#xff0c;在3GPP讨论中考虑了所有可能的聚合和核心网络组合&#xff0c;共有八个架构选项。以下重点介绍option2、3、4和7。 1. 独立组网 (Standalone, SA) 架构选项 2 &#xff1a;Standalone architecture with 5G-core 特点&#xff1a; 5G核心网&#xff08;5GC, …

MySQL数据库备份,恢复

备份策略不同&#xff0c;恢复方式也不同。 在进行数据备份的时候&#xff0c;能使用冷备份就使用冷备份&#xff0c;安全可靠&#xff0c; 但是冷备份自己的缺点是【每一个数据库都对应着一个前端的业务】此时前端业务停止可能带来经济损失。 一.备份类型 根据服务是否在线…

OpenCV 学习记录:首篇

最近在学习机器视觉&#xff0c;希望能通过记录博客的形式来鞭策自己坚持学完&#xff0c;同时也把重要的知识点记录下来供参考学习。 1. OpenCV 介绍与模块组成 什么是 OpenCV&#xff1f; OpenCV (Open Source Computer Vision Library) 是一个开源的计算机视觉和机器学习软…

基于vue框架的的校园二手市场交易平台8k655(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;学生,大学,商品分类,商品信息,在线咨询 开题报告内容 基于Vue框架的校园二手市场交易平台开题报告 一、课题意义 &#xff08;一&#xff09;理论意义 本课题旨在研究基于Vue框架的校园二手市场交易平台的设计与实现。当前&#xff…

3D计算机视觉概述

3D计算机视觉 3D计算机视觉概述 像机标定 文章目录 3D计算机视觉前言一、人类视觉二、计算机视觉2.1 计算机视觉的研究目的2.2 计算机视觉的研究任务2.3 计算机视觉的研究方法2.4 视觉计算理论2.5 马尔框架中计算机视觉表达的四个层次2.5.1 图像&#xff08;像素表达&#xff…

操作系统(13)虚拟存储器

前言 操作系统中的虚拟存储器是一项关键技术&#xff0c;它为用户提供了一个远大于实际物理内存容量的逻辑内存空间。 一、定义与原理 虚拟存储器是具有请求调入功能和置换功能&#xff0c;能从逻辑上对内存容量加以扩充的存储器系统。其逻辑容量由内存容量与外存容量之和决定&…

【实用技能】如何运用Visual Paradigm快速创建团队的项目模板

从 Visual Paradigm 17.2 &#xff08;&#xff09;版开始&#xff0c;您可以创建自己的项目模板并与团队共享。这样团队成员就可以轻松创建符合团队标准的新项目。本文将指导您完成为团队创建项目模板的过程。 Visual Paradigm v17.2试用版下载 先决条件 您的团队必须使用 …

不良人系列-复兴数据结构(栈和队列)

个人主页&#xff1a;爱编程的小新☆ 不良人经典语录&#xff1a;“相呴相济 玉汝于成 勿念 心安” 目录 一. 栈(stack) 1. 栈的概念 2. 栈的常见方法 3.栈的模拟实现 ​编辑 二. 队列 1. 队列的概念 2. 队列的使用 2.1 队列的常见方法 2.2 队列的模拟实现 2.3 队列…

【Linux网络】网络基础:IP协议

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ IP协议 IP协议基本概念协议头格式分片与组装网段划分子网掩码特殊的IP地址 IP地址的数量限制…

Linux正则化与三剑客速成(一)

目录 1.正则化 1.1正则表达式&#xff08;RE&#xff09; 1.2 正则表达式的注意事项 1.3正则表达式的分类 1.4 基本正则表达式 ^:表示匹配文本中以某个字符串开头的行。 $:表示匹配以某个字符串结尾的文件内的行 ^$:表示空行&#xff0c;但是在Linux中的实际的操作中一…

HarmonyOS 非线性容器LightWeightMap 常用的几个方法

LightWeightMap可用于存储具有关联关系的key-value键值对集合&#xff0c;存储元素中key值唯一&#xff0c;每个key对应一个value。 LightWeightMap依据泛型定义&#xff0c;采用轻量级结构&#xff0c;初始默认容量大小为8&#xff0c;每次扩容大小为原始容量的两倍。 集合中k…

Docker的容器

目录 1. 什么是容器&#xff1f;2. 容器的生命周期2.1 容器处理OOM事件2.2 容器异常退出2.3 容器暂停 3. 容器命令详解3.1 容器命令清单3.2 docker create命令3.3 docker run命令3.4 docker ps命令3.5 docker logs命令3.6 docker attach命令3.7 docker exec命令3.8 docker stat…

LearnOpenGL学习(高级OpenGL -> 高级GLSL,几何着色器)

完整代码见&#xff1a;zaizai77/Cherno-OpenGL: OpenGL 小白学习之路 高级GLSL 内建变量 顶点着色器 gl_PointSoze : float 输出变量&#xff0c;用于控制渲染 GL_POINTS 型图元时&#xff0c;点的大小。可用于粒子系统。将其设置为 gl_Position.z 时&#xff0c;可以使点…

Excel/VBA 正则表达式归纳汇总

1.with结构。以下语句用来提取A列中的“成品”两个字前面的部分的中文&#xff0c;不含成品两个字&#xff0c;结果存放在第2列。使用了On Error Resume Next&#xff0c;表示错误时继续下一条。 Sub 提取口味() Set regx CreateObject("vbscript.regexp") On Err…

CodeMirror 如何动态更新definemode

CodeMirror 如何动态更新definemode 问题描述&#xff1a;解决方法&#xff1a; 问题描述&#xff1a; 项目中有一部分用到了CodeMirror组件&#xff0c;其高亮显示的内容需要根据最新的json动态的更新&#xff0c;需要使用definemode自定义高亮内容。 想要的效果如下&#xf…