python 机器视觉 车牌识别 - opencv 深度学习 机器学习 计算机竞赛
1 前言
🔥 优质竞赛项目系列,今天要分享的是
🚩 基于python 机器视觉 的车牌识别系统
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:3分
- 工作量:3分
- 创新点:3分
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
1 课题背景
车牌识别其实是个经典的机器视觉任务了,通过图像处理技术检测、定位、识别车牌上的字符,实现计算机对车牌的智能管理功能。如今在小区停车场、高速公路出入口、监控场所、自动收费站等地都有车牌识别系统的存在,车牌识别的研究也已逐步成熟。尽管该技术随处可见了,但其实在精度和识别速度上还需要进一步提升,自己动手实现一个车牌识别系统有利于学习和理解图像处理的先进技术。
本文详细介绍基于深度学习的中文车牌识别与管理系统,在介绍算法原理的同时,给出Python的实现代码以及PyQt的简单UI界面。在界面中可以选择需要识别的车牌视频、图片文件等。
2 效果演示
首先还是用动图先展示一下效果,系统主要实现的功能是对图片、视频中的车牌进行检测和识别,演示效果如下。
2.1 图片检测识别

2.2视频检测识别

3 车牌检测与识别
目前,智能交通系统中集成运用计算机视觉、物联网、人工智能等多种技术成为未来发展方向。其中,车牌识别(License Plate Recognition,
 LPR)技术作为一项重要技术,从获取的图像中提取目标车辆的车牌信息,成为完善智能交通管理运行的基础。
由于本文介绍的是中文车牌,所以可以简单了解一下国内汽车拍照的特点:字符数为七个,包括汉字、字母和数字。车牌颜色组合中,其中最常见的组合为普通小型汽车蓝底白字和新能源汽车的渐变绿底黑字。

总结来说,车牌是一个有特点的图像区域,几种特征可以综合起来确定车牌定位,所以之前就有利用车牌与周围环境的差异的算法。目前常见的车牌定位算法有以下 4
 种:基于颜色、纹理、边缘信息的车牌定位算法和基于人工神经网络的车牌定位算法。
如下图所示,常规的步骤包括图像采集、预处理、车牌定位、字符分割、字符识别、输出结果。深度学习技术成熟之后,端到端的网络模型使得这一过程变得简单起来。从思想上来说,基于深度学习的车牌识别实现思路主要包括两个部分:(1)车牌检测定位;(2)车牌字符识别。

其中,车牌的检测定位本质是一个特定的目标检测任务,即通过算法框选出属于车牌的位置坐标,以便将其与背景区分开来。可以认为检测出的车牌位置才是我们的感兴趣区域。好用的方法如Cascade
 LBP,它是一种机器学习的方法,可以利用OpenCV训练级联分类器,依赖CPU进行计算,级联分类器的方法对于常用场景效果比较好,检测速度较快,曾经一度比较流行,但准确率一般。基于深度学习的检测算法有Mobilene-
 SSD、YOLO-v5等,利用大批量的标注数据进行训练.
当ROI被检测出来,如何对这一区域中的字符进行识别,这就涉及到采取的处理方式。第一种处理方式,首先利用一系列字符分割的算法将车牌中的字符逐个分开,然后基于深度学习进行字符分类,得到识别结果;第二种,区别于第一种先分割再分类的两步走方式,利用端到端的CTC(
 Connectionist Temporal Classification)网络直接进行识别。
这里我们使用网上开源的HyperLPR中文车牌识别框架,首先导入OpenCV和hyperlpr,读取一张车牌图片调用架构中的车牌识别方法获得结果,以下代码来自官方的示例:
    #导入包from hyperlpr import *#导入OpenCV库import cv2#读入图片image = cv2.imread("demo.jpg")#识别结果print(HyperLPR_plate_recognition(image))
以上代码运行结果如下,可以看出该方法识别了车牌的车牌字符、置信度值、车牌位置坐标、图片尺寸等结果。

这样的结果还不够直观,我们写一个函数将车牌的识别结果标注在图片上,首先导入相关依赖包,其代码如下:
    # 导入包from hyperlpr import *# 导入OpenCV库import cv2 as cvfrom PIL import Image, ImageDraw, ImageFontimport numpy as np
新建一个函数drawRectBox,将图像数据、识别结果、字体等参数传入,函数内部利用OpenCV和PIL库添加标注框和识别结果的字符,其代码如下:
    def drawRectBox(image, rect, addText, fontC):cv.rectangle(image, (int(round(rect[0])), int(round(rect[1]))),(int(round(rect[2]) + 8), int(round(rect[3]) + 8)),(0, 0, 255), 2)cv.rectangle(image, (int(rect[0] - 1), int(rect[1]) - 16), (int(rect[0] + 75), int(rect[1])), (0, 0, 255), -1, cv.LINE_AA)img = Image.fromarray(image)draw = ImageDraw.Draw(img)draw.text((int(rect[0] + 1), int(rect[1] - 16)), addText, (255, 255, 255), font=fontC)imagex = np.array(img)return imagex
我们首先读取图片文件,利用前面的HyperLPR_plate_recognition方法识别出车牌结果,调用以上函数获得带标注框的图片,利用OpenCV的imshow方法显示结果图片,其代码如下:
    image = cv.imread('test3.jpeg')  # 读取选择的图片res_all = HyperLPR_plate_recognition(image)fontC = ImageFont.truetype("./platech.ttf", 14, 0)res, confi, axes = res_all[0]image = drawRectBox(image, axes, res, fontC)cv.imshow('Stream', image)c = cv.waitKey(0) & 0xff
此时运行以上代码可以得到如下结果:

同理,识别视频中的车牌也可以做类似的操作,不过我们需要先对视频文件进行逐帧读取,然后采用以上的方式在图片中标识出车牌并显示。
这部分代码如下:
    
capture = cv.VideoCapture("./车牌检测.mp4")  # 读取视频文件
fontC = ImageFont.truetype("./platech.ttf", 14, 0)  # 字体,用于标注图片
    i = 1
while (True):ref, frame = capture.read()if ref:i = i + 1if i % 5 == 0:i = 0res_all = HyperLPR_plate_recognition(frame)  # 识别车牌if len(res_all) > 0:res, confi, axes = res_all[0]  # 获取结果frame = drawRectBox(frame, axes, res, fontC)cv.imshow("num", frame)  # 显示画面        if cv.waitKey(1) & 0xFF == ord('q'):
            break  # 退出
    else:
        break
以上代码每5帧识别一次视频中的车牌,将车牌的结果标注在画面中进行实时显示,运行结果的截图如下所示:
 
车牌的识别部分代码演示完毕,对此我们完成了图片和视频的识别,然而这些还是简单的脚本呈现。为了方便更换图片、视频以及管理车牌,还需要设计文件选择功能以及系统的UI界面。这部分代码如下:
    class Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(800, 600)self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.openimage = QtWidgets.QPushButton(self.centralwidget)self.openimage.setGeometry(QtCore.QRect(20, 40, 91, 51))self.openimage.setObjectName("openimage")self.showlabel = QtWidgets.QLabel(self.centralwidget)self.showlabel.setGeometry(QtCore.QRect(110, 10, 471, 441))self.showlabel.setObjectName("showlabel")self.LPRdetect = QtWidgets.QPushButton(self.centralwidget)self.LPRdetect.setGeometry(QtCore.QRect(20, 150, 81, 51))self.LPRdetect.setObjectName("LPRdetect")self.LPR_Rec = QtWidgets.QPushButton(self.centralwidget)self.LPR_Rec.setGeometry(QtCore.QRect(20, 292, 75, 31))self.LPR_Rec.setObjectName("LPR_Rec")self.lineEdit_result = QtWidgets.QLineEdit(self.centralwidget)self.lineEdit_result.setGeometry(QtCore.QRect(20, 400, 101, 41))self.lineEdit_result.setObjectName("lineEdit_result")self.openvideo = QtWidgets.QPushButton(self.centralwidget)self.openvideo.setGeometry(QtCore.QRect(20, 360, 75, 23))self.openvideo.setObjectName("openvideo")MainWindow.setCentralWidget(self.centralwidget)self.menubar = QtWidgets.QMenuBar(MainWindow)self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))self.menubar.setObjectName("menubar")MainWindow.setMenuBar(self.menubar)self.statusbar = QtWidgets.QStatusBar(MainWindow)self.statusbar.setObjectName("statusbar")MainWindow.setStatusBar(self.statusbar)self.retranslateUi(MainWindow)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))self.openimage.setText(_translate("MainWindow", "打开图片"))self.showlabel.setText(_translate("MainWindow", "TextLabel"))self.LPRdetect.setText(_translate("MainWindow", "车牌检测"))self.LPR_Rec.setText(_translate("MainWindow", "车牌识别"))self.openvideo.setText(_translate("MainWindow", "PushButton"))
4 HyperLPR库
4.1 简介
HyperLPR是一个使用深度学习针对对中文车牌识别的实现,与较为流行的开源的EasyPR相比,它的检测速度和鲁棒性和多场景的适应性都要好于目前开源的EasyPR,HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等。
4.2 特点
- 基于端到端sequence模型,无需进行字符分割,识别速度更快。
- 速度快 720p ,单核 Intel 2.2G CPU (macbook Pro 2015)平均识别时间<=90ms
- 识别率高,仅仅针对车牌ROI在EasyPR数据集上,0-error达到 95.2%, 1-error识别率达到 97.4% (指在定位成功后的车牌识别率)
- 轻量总代码量不超1k行。
- 带有Android实现,其Android Demo可解决一些在一些普通业务场景(如执法记录仪)下的车牌识别任务。
- 支持多种车牌的识别,详情见如下
4.3 HyperLPR的检测流程
- 使用opencv的HAAR Cascade检测车牌大致位置
- Extend检测到的大致位置的矩形区域
- 使用类似于MSER的方式的多级二值化和RANSAC拟合车牌的上下边界
- 使用CNN Regression回归车牌左右边界
- 使用基于纹理场的算法进行车牌校正倾斜
- 使用CNN滑动窗切割字符
- 使用CNN识别字符
4.4 安装
  pip install hyperlpr
4.5 Python 依赖
-  Keras (>2.0.0) 
-  Theano(>0.9) or Tensorflow(>1.1.x) 
-  Numpy (>1.10) 
-  Scipy (0.19.1) 
-  OpenCV(>3.0) 
-  Scikit-image (0.13.0) 
-  PIL 
-  使用CNN识别字符 
5 最后
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
相关文章:
 
python 机器视觉 车牌识别 - opencv 深度学习 机器学习 计算机竞赛
1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于python 机器视觉 的车牌识别系统 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:3分创新点:3分 🧿 更多资…...
 
Hadoop3教程(十二):MapReduce中Shuffle机制的概述
文章目录 (95) Shuffle机制什么是shuffle?Map阶段Reduce阶段 参考文献 (95) Shuffle机制 面试的重点 什么是shuffle? Map方法之后,Reduce方法之前的这段数据处理过程,就叫做shuff…...
 
MySQL为什么用b+树
索引是一种数据结构,用于帮助我们在大量数据中快速定位到我们想要查找的数据。 索引最形象的比喻就是图书的目录了。注意这里的大量,数据量大了索引才显得有意义,如果我想要在[1,2,3,4]中找到4这个数据,直接对全数据检索也很快&am…...
浅谈机器学习中的概率模型
浅谈机器学习中的概率模型 其实,当牵扯到概率的时候,一切问题都会变的及其复杂,比如我们监督学习任务中,对于一个分类任务,我们经常是在解决这样一个问题,比如对于一个n维的样本 X [ x 1 , x 2 , . . . .…...
 
MySQL 函数 索引 事务 管理
目录 一. 字符串相关的函数 二.数学相关函数 编辑 三.时间日期相关函数 date.sql 四.流程控制函数 centrol.sql 分页查询 使用分组函数和分组字句 group by 数据分组的总结 多表查询 自连接 子查询 subquery.sql 五.表的复制 六.合并查询 七.表的外连接 …...
Flink如何基于事件时间消费分区数比算子并行度大的kafka主题
背景 使用flink消费kafka的主题的情况我们经常遇到,通常我们都是不需要感知数据源算子的并行度和kafka主题的并行度之间的关系的,但是其实在kafka的主题分区数大于数据源算子的并行度时,是有一些注意事项的,本文就来讲解下这些注…...
 
总结:JavaEE的Servlet中HttpServletRequest请求对象调用各种API方法结果示例
总结:JavaEE的Servlet中HttpServletRequest请求对象调用各种API方法结果示例 一方法调用顺序是按照英文字母顺序从A-Z二该示例可以用作servlet中request的API参考,从而知道该如何获取哪些路径参数等等三Servlet的API版本5.0.0、JSP的API版本:…...
 
ChatGPT AIGC 完成Excel跨多表查找操作vlookup+indirect
VLOOKUP和INDIRECT的组合在Excel中用于跨表查询,其中VLOOKUP函数用于在另一张表中查找数据,INDIRECT函数则用于根据文本字符串引用不同的工作表。具体操作如下: 1.假设在工作表1中,A列有你要查找的值,B列是你希望查询的工作表名称。 2.在工作表1的C列输入以下公式:=VLO…...
Linux系统conda虚拟环境离线迁移移植
本人创建的conda虚拟环境名为yys(每个人的虚拟环境名不一样,替换下就行) 以下为迁移步骤: 1.安装打包工具将虚拟环境打包: conda install conda-pack conda pack -n yys -o yys.tar.gz 2.将yys.tar.gz上传到服务器&…...
Vue16 绑定css样式 style样式
绑定样式: 1. class样式写法:class"xxx" xxx可以是字符串、对象、数组。字符串写法适用于:类名不确定,要动态获取。对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。数组写法适用于&…...
 
[Spring] SpringMVC 简介(三)
目录 九、SpringMVC 中的 AJAX 请求 1、简单示例 2、RequestBody(重点关注“赋值形式”) 3、ResponseBody(经常用) 4、为什么不用手动接收 JSON 字符串、转换 JSON 字符串 5、RestController 十、文件上传与下载 1、Respo…...
 
kettle应用-从数据库抽取数据到excel
本文介绍使用kettle从postgresql数据库中抽取数据到excel中。 首先,启动kettle 如果kettle部署在windows系统,双击运行spoon.bat或者在命令行运行spoon.bat 如果kettle部署在linux系统,需要执行如下命令启动 chmod x spoon.sh nohup ./sp…...
 
Git Commit Message规范
概述 Git commit message规范是一种良好的实践,可以帮助开发团队更好地理解和维护代码库的历史记录。它可以提高代码质量、可读性和可维护性。下面是一种常见的Git commit message规范,通常被称为"Conventional Commits"规范: 一…...
 
Linux网络编程系列之UDP广播
Linux网络编程系列 (够吃,管饱) 1、Linux网络编程系列之网络编程基础 2、Linux网络编程系列之TCP协议编程 3、Linux网络编程系列之UDP协议编程 4、Linux网络编程系列之UDP广播 5、Linux网络编程系列之UDP组播 6、Linux网络编程系列之服务器编…...
spring中事务相关面试题(自用)
1 什么是spring事务 Spring事务管理的实现原理是基于AOP(面向切面编程)和代理模式。Spring提供了两种主要的方式来管理事务:编程式事务管理和声明式事务管理。 声明式事务管理: Spring的声明式事务管理是通过使用注解或XML配置来…...
 
09 | JpaSpecificationExecutor 解决了哪些问题
QueryByExampleExecutor用法 QueryByExampleExecutor(QBE)是一种用户友好的查询技术,具有简单的接口,它允许动态查询创建,并且不需要编写包含字段名称的查询。 下面是一个 UML 图,你可以看到 QueryByExam…...
Linux命令(93)之su
linux命令之su 1.su介绍 linux命令su用于变更为其它使用者的身份,如root用户外,需要输入使用者的密码 2.su用法 su [参数] user su参数 参数说明-c <command>执行指定的命令,然后切换回原用户-切换到目标用户的环境变量 3.实例 3…...
1.HTML-HTML解决中文乱码问题
题记 下面是html文件解决中文乱码的方法 方法一 在 HTML 文件的 <head> 标签中添加 <meta charset"UTF-8">,确保文件以 UTF-8 编码保存 <head> <meta charset"UTF-8"> <!-- 其他标签和内容 --> </head> --…...
 
Vue3 + Nodejs 实战 ,文件上传项目--实现拖拽上传
目录 1.拖拽上传的剖析 input的file默认拖动 让其他的盒子成为拖拽对象 2.处理文件的上传 处理数据 上传文件的函数 兼顾点击事件 渲染已处理过的文件 测试效果 3.总结 博客主页:専心_前端,javascript,mysql-CSDN博客 系列专栏:vue3nodejs 实战-…...
 
Windows:VS Code IDE安装ESP-IDF【保姆级】
物联网开发学习笔记——目录索引 参考: VS Code官网:Visual Studio Code - Code Editing. Redefined 乐鑫官网:ESP-IDF 编程指南 - ESP32 VSCode ESP-ID Extension Install 一、前提条件 Visual Studio Code IDE安装ESP-IDF扩展…...
 
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
 
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
 
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
 
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
 
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
 
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
