【深度学习实践】基于深度学习的车牌识别(python,车牌检测+车牌识别)

article/2025/9/20 21:59:43

车牌识别具有广泛的应用前景,基于传统方法的车牌识别效果一般比较差,随着计算机视觉技术的快速发展,深度学习的方法能够更好的完成车牌识别任务。

 本文提供了车牌识别方案的部署链接,您可以在网页上体验该模型的效果:车牌识别方案在线体验

本文介绍了使用PaddleOCR完成车牌识别任务的方法,其检测效果如下图:

原图如下:

 检测结果如下:

目录

一、概述 

二、使用

1、数据集准备

2、检测模型

3、识别模型

4、模型导出

5、联合推理

 三、总结

附录:


一、概述 

基于深度学习的车牌识别任务可以拆解为2个步骤:车牌检测-车牌识别。其中车牌检测的目的是确认图片中车牌的位置,根据检测到的车牌位置把图片中的ROI裁剪出来,车牌识别算法用于识别裁剪出的车牌图像中的具体内容。

本文使用PaddleOCR工具实现了车牌识别任务,首先使用PaddleOCR的检测算法DBNet检测出车牌位置,再将车牌位置裁剪送入文本识别算法CRNN来识别车牌的具体内容。

PaddleOCR github:https://github.com/PaddlePaddle/PaddleOCR.git

二、使用

1、数据集准备

本文选择的数据集为CCPD2020,下载链接为:CCPD2020(New energy plate) - 飞桨AI Studio

CPPD数据集的图片文件名具有特殊规则,具体规则如下:

例如: 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

每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。

  • 025:车牌面积与整个图片区域的面积比。025 (25%)

  • 95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度

  • 154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473)

  • 386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402)

  • 0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S

  • 37:牌照区域的亮度。 37 (37%)

  • 15:车牌区域的模糊度。15 (15%)

下载好了数据集,需要把数据集转换为PaddleOCR需要的标注格式,代码如下(修改图片的存储路径为自己的路径):

import cv2
import os
import json
from tqdm import tqdm
import numpy as npprovinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
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', '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']def make_label(img_dir, save_gt_folder, phase):crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')os.makedirs(crop_img_save_dir, exist_ok=True)f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')i = 0for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):str_list = filename.split('-')if len(str_list) < 5:continuecoord_list = str_list[3].split('_')txt_list = str_list[4].split('_')boxes = []for coord in coord_list:boxes.append([int(x) for x in coord.split("&")])boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])# detdet_info = [{'points':boxes, 'transcription':lp_number}]f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))# recboxes = np.float32(boxes)img = cv2.imread(os.path.join(img_dir, phase, filename))# crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]crop_img = get_rotate_crop_image(img, boxes)crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)cv2.imwrite(crop_img_save_path, crop_img)f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))i+=1f_det.close()f_rec.close()def get_rotate_crop_image(img, points):'''img_height, img_width = img.shape[0:2]left = int(np.min(points[:, 0]))right = int(np.max(points[:, 0]))top = int(np.min(points[:, 1]))bottom = int(np.max(points[:, 1]))img_crop = img[top:bottom, left:right, :].copy()points[:, 0] = points[:, 0] - leftpoints[:, 1] = points[:, 1] - top'''assert len(points) == 4, "shape of points must be 4*2"img_crop_width = int(max(np.linalg.norm(points[0] - points[1]),np.linalg.norm(points[2] - points[3])))img_crop_height = int(max(np.linalg.norm(points[0] - points[3]),np.linalg.norm(points[1] - points[2])))pts_std = np.float32([[0, 0], [img_crop_width, 0],[img_crop_width, img_crop_height],[0, img_crop_height]])M = cv2.getPerspectiveTransform(points, pts_std)dst_img = cv2.warpPerspective(img,M, (img_crop_width, img_crop_height),borderMode=cv2.BORDER_REPLICATE,flags=cv2.INTER_CUBIC)dst_img_height, dst_img_width = dst_img.shape[0:2]if dst_img_height * 1.0 / dst_img_width >= 1.5:dst_img = np.rot90(dst_img)return dst_imgimg_dir = 'CCPD2020/ccpd_green'   # 改成自己的路径
save_gt_folder = 'CCPD2020/PPOCR'   # 改成自己的路径
# phase = 'train' # change to val and test to make val dataset and test dataset
for phase in ['train','val','test']:make_label(img_dir, save_gt_folder, phase)

2、检测模型

准备好了数据集,首先需要训练车牌检测模型,这里我们使用PaddleOCR提供的文本检测预训练模型进行fine-tuning,这样可以减少训练时间,首先下载预训练检测模型(先进入PaddleOCR文件夹):

mkdir models
cd models
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
tar -xf ch_PP-OCRv3_det_distill_train.tar
cd PaddleOCR

下载好了预训练模型,下面训练检测模型(其中的data_dir和label_file_list换成自己的数据集路径):

python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \Global.save_model_dir=output/CCPD/det \Global.eval_batch_step="[0, 772]" \Optimizer.lr.name=Const \Optimizer.lr.learning_rate=0.0005 \Optimizer.lr.warmup_epoch=0 \Train.dataset.data_dir=CCPD2020/ccpd_green \Train.dataset.label_file_list=[CCPD2020/PPOCR/train/det.txt] \Eval.dataset.data_dir=CCPD2020/ccpd_green \Eval.dataset.label_file_list=[CCPD2020/PPOCR/test/det.txt]

训练好了模型以后,可以使用下面的命令验证一下精度(此步可以跳过,也要更换data_dir和label_file_list路径):

python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \Eval.dataset.data_dir=CCPD2020/ccpd_green \Eval.dataset.label_file_list=[CCPD2020/PPOCR/test/det.txt]

可以使用如下命令来实现检测模型推理(路径修改为自己需要的路径):

python3 tools/infer_det.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \-o Global.infer_img="src.jpg" Global.pretrained_model="./output/CCPD/det/best_accuracy" \PostProcess.box_thresh=0.6 PostProcess.unclip_ratio=2.0

3、识别模型

训练好了检测模型,再来训练识别模型,同样先下载预训练权重再fine-tuning,下载权重命令如下:

mkdir models
cd models
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
tar -xf ch_PP-OCRv3_rec_train.tar
cd PaddleOCR

这个权重中包含不需要的内容(Teacher的权重),需要提取需要的权重:

import paddle
# 加载预训练模型
all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
# 查看权重参数的keys
print(all_params.keys())
# 学生模型的权重提取
s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
# 查看学生模型权重参数的keys
print(s_params.keys())
# 保存
paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams")

开启训练(注意路径):

python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \Global.save_model_dir=output/CCPD/rec/ \Global.eval_batch_step="[0, 90]" \Optimizer.lr.name=Const \Optimizer.lr.learning_rate=0.0005 \Optimizer.lr.warmup_epoch=0 \Train.dataset.data_dir=CCPD2020/PPOCR \Train.dataset.label_file_list=[PPOCR/train/rec.txt] \Eval.dataset.data_dir=CCPD2020/PPOCR \Eval.dataset.label_file_list=[PPOCR/test/rec.txt]

验证精度:

python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \Eval.dataset.data_dir=CCPD2020/PPOCR \Eval.dataset.label_file_list=[PPOCR/test/rec.txt]

使用如下命令测试识别模型的效果(需要注意的是,识别模型的输入是车牌号图片,不是完整的图片,可以使用数据集处理时的PPOCR文件夹内生成的裁剪后的车牌图片):

python3 tools/infer/predict_det.py --det_algorithm="DB" --det_model_dir="output/CCPD/det/infer" --image_dir="/home/aistudio/src.jpg" --use_gpu=True

4、模型导出

上面训练好的模型都是动态图模型,将他们导出为静态图模型来部署,可以加快速度,首先导出检测模型:

python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \Global.save_inference_dir=output/CCPD/det/infer

测试一下导出的检测模型推理效果(注意图片路径):

python3 tools/infer/predict_det.py --det_algorithm="DB" --det_model_dir="output/CCPD/det/infer" --image_dir="src.jpg" --use_gpu=True

下面导出识别模型:

python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \Global.save_inference_dir=output/CCPD/rec/infer

测试一下导出的识别模型推理效果(注意图片路径):

python3 tools/infer/predict_rec.py --image_dir="PPOCR/test/crop_imgs" \--rec_model_dir="output/CCPD/rec/infer" --rec_image_shape="3, 48, 320" --rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt"

5、联合推理

训练好了检测和识别模型,下面就是联合推理,测试效果,命令如下(det_model_dir和rec_model_dir是上面导出的模型文件夹):

python tools/infer/predict_system.py \--det_model_dir=output/CCPD/det/infer/ \--rec_model_dir=output/CCPD/rec/infer/ \--image_dir="src.jpg" \--rec_image_shape=3,48,320

这是识别的结果:

 三、总结

本文总结了PaddleOCR提供的车牌识别方案,并进行了简化,根据识别的结果来看可以很好地检测车牌图像。

附录:

PaddleOCR轻量级车牌识别方案

本文提供了车牌识别方案的部署链接,您可以再网页上体验该模型的效果:

车牌识别方案在线体验


http://chatgpt.dhexx.cn/article/cde0DjjF.shtml

相关文章

C++中文车牌识别检测系统源码

下载地址&#xff1a;C中文车牌识别检测系统源码 其目标是成为一个简单、高效、准确的非限制场景(unconstrained situation)下的车牌识别库。 相比于其他的车牌识别系统&#xff0c;EasyPR有如下特点&#xff1a; 它基于openCV这个开源库。这意味着你可以获取全部源代码&…

车辆检测+车牌识别

车辆检测算法使用YOLOv5实现 自建数据集训练的车辆检测模型&#xff0c;效果还是很棒的 车牌识别使用mtcnn实现车牌检测 lprnet实现车牌号码识别 两者都是pytorch框架 整合在一个工程中实现车辆检测和车牌识别 同时使用pyqt开发可视化界面

智能驾驶 车牌检测和识别(一)《CCPD车牌数据集》

智能驾驶 车牌检测和识别&#xff08;一&#xff09;《CCPD车牌数据集》 目录 智能驾驶 车牌检测和识别&#xff08;一&#xff09;《CCPD车牌数据集》 1. 前言 2.车牌号码说明 3.车牌数据集CCPD &#xff08;1&#xff09;车牌数据集CCPD说明 &#xff08;2&#xff09…

智能驾驶 车牌检测和识别(二)《YOLOv5实现车牌检测(含车牌检测数据集和训练代码)》

智能驾驶 车牌检测和识别&#xff08;二&#xff09;《YOLOv5实现车牌检测&#xff08;含车牌检测数据集和训练代码&#xff09;》 目录 智能驾驶 车牌检测和识别&#xff08;二&#xff09;《YOLOv5实现车牌检测&#xff08;含车牌检测数据集和训练代码&#xff09;》 1. 前…

在线合成车牌照片【模拟车牌,用于车牌识别项目测试】

1、服务发布地址&#xff1a; http://new.hdsxsc.com:10086/server.php?cphm冀DSX888&cpys0 2、传参说明&#xff1a; cphm&#xff1a;车牌号码【仅限合规的车牌号码规则】 cpys&#xff1a;车牌颜色&#xff1a; 0蓝色&#xff0c;1黄色&#xff0c;2白色&#xff0c…

车牌号码识别程序分享

本文参考博客使用opencv进行车牌提取及识别进行。程序部分为网上获取程序修改而来&#xff0c;并在其中加入了自己的注释和理解 采用pythonopencv进行程序编写。 课程设计内容分享 程序下载请前往https://download.csdn.net/download/chenkz123/10841956 一个典型的车辆牌照…

车牌图像识别

1.车牌预处理 车牌预处理过程的好坏直接影响到车牌图像进行后期处理过程&#xff0c;比如车牌字符分割等。车牌预处理也是尽可能的消除噪声&#xff0c;减少后期处理带来的不必要的麻烦。 输入的车牌是24Bit的BMP真彩色图像&#xff0c;车牌照有黄底黑字&#xff0c;蓝底白字…

基于python+OpenCV的车牌号码识别

基于pythonOpenCV的车牌号码识别 车牌识别行业已具备一定的市场规模&#xff0c;在电子警察、公路卡口、停车场、商业管理、汽修服务等领域已取得了部分应用。一个典型的车辆牌照识别系统一般包括以下4个部分&#xff1a;车辆图像获取、车牌定位、车牌字符分割和车牌字符识别 …

TensorFlow进阶:车牌号识别项目

终于算是闲下来点时间了&#xff0c;也不能算闲&#xff0c;该交的报告什么的算完事了。其他要交的东西现在还不急&#xff0c;然后考研的东西现在也不想看&#xff0c;再加上中午没睡好&#xff0c;下午也不想学习新的东西了&#xff0c;就抽出点时间把前段时间做的一个小项目…

数字图像处理--车牌识别

数字图像处理–车牌识别 主要内容 实现车牌识别 算法流程 本文中&#xff0c;车牌识别具体流程设计以及算法使用主要分为以下几步。 1、读取源车牌图像。 2、对原始车牌图像进行预处理&#xff1a;灰度化&#xff0c;运用基于几何运算的滤波器(开运算)消除毛刺噪声。 3、二…

数字图像处理——基于matlab的车牌号识别

希望大家有问题多多评论留言鸭 码字不易&#xff0c;老阿姨头发都没啦&#xff0c;小可爱们记得给三连鸭&#xff0c;么么哒。 &#xff08;只收藏&#xff0c;不点赞&#xff0c;好运连连会中断&#xff01;&#xff01;&#xff01;&#xff09; <--!&#xff08;源码资源…

【OpenCV实战】简洁易懂的车牌号识别Python+OpenCV实现“超详解”(含代码)

前面4篇博客介绍了OpenCV图像处理的基础知识&#xff0c;本篇博客利用前4篇的知识完成一个小项目——车牌号码识别。该篇博客的代码可以满足小区门禁车牌号的识别。本篇博客是前4篇博客知识的一个综合运用。感觉学会了这个可以实现一系列的图像识别任务。。。毕竟好多技巧都是共…

网络安全检测技术

一&#xff0c;网络安全漏洞 安全威胁是指所有能够对计算机网络信息系统的网络服务和网络信息的机密性&#xff0c;可用性和完整性产生阻碍&#xff0c;破坏或中断的各种因素。安全威胁可分为人为安全威胁和非人为安全威胁两大类。 1&#xff0c;网络安全漏洞威胁 漏洞分析的…

深度学习网络安全

Introduction 我们在社区中看到的大多数深度学习应用程序通常面向营销&#xff0c;销售&#xff0c;财务等领域。我们几乎从未阅读过文章或找到有关深度学习的资源用于保护这些产品和业务&#xff0c; 恶意软件和黑客攻击。 虽然像谷歌&#xff0c;Facebook&#xff0c;微软和…

网络安全法学习整理笔记

网络安全法 一、背景 概念 网络&#xff1a;是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息进行收集、存储、传输、交换、处理的系统。网络安全&#xff1a;是指通过采取必要措施&#xff0c;防范对网络的攻击、侵入、干扰、破坏和非法使用以及意…

网络安全免费学习网址(英文)

转载 作者&#xff1a;W-Pwn 链接&#xff1a;https://www.zhihu.com/question/49222590/answer/339206050 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 知识就是力量 但是知识太贵了&#xff0c;现在随便拎…

【论文阅读】基于强化学习的网络安全防护策略

【论文阅读】基于强化学习的网络安全防护策略 本篇文章将介绍一篇针对网络安全问题&#xff0c;运用强化学习方法寻找最优的网络防御策略。 Finding Effective Security Strategies through Reinforcement Learning and Self-Play 前言 通过强化学习和 自对弈(self-play) 寻…

还在为不知道怎么学习网络安全而烦恼吗?这篇文带你从入门级开始学习网络安全—认识网络安全

随着网络安全被列为国家安全战略的一部分&#xff0c;这个曾经细分的领域发展提速了不少&#xff0c;除了一些传统安全厂商以外&#xff0c;一些互联网大厂也都纷纷加码了在这一块的投入&#xff0c;随之而来的吸引了越来越多的新鲜血液不断涌入。 不同于Java、C/C等后端开发岗…

[网络安全自学篇] 一.入门笔记之看雪Web安全学习及异或解密示例

最近开始学习网络安全相关知识&#xff0c;接触了好多新术语&#xff0c;感觉自己要学习的东西太多&#xff0c;真是学无止境&#xff0c;也发现了好几个默默无闻写着博客、做着开源的大神。准备好好学习下新知识&#xff0c;并分享些博客与博友们一起进步&#xff0c;加油。非…

码农翻身,卧虎藏龙

写公众号是很不容易的&#xff0c;在现在信息爆炸的情况下&#xff0c;好文章也很容易被标题党埋没&#xff0c;在我的知识星球“码农翻身”中&#xff0c;我发起了一个活动&#xff1a;免费给写公众号的球友们做个推广。 这个不是互推&#xff0c;就是我单方面的推广&#xf…