python 机器视觉 车牌识别 - opencv 深度学习 机器学习 计算机竞赛

news2024/11/24 0:41:59

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 cv
    from PIL import Image, ImageDraw, ImageFont
    import 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 + 1
        if i % 5 == 0:
            i = 0
            res_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.translate
        MainWindow.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

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

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

相关文章

JDBC封装查询单个和查询多个

Mybatis在转化时候可以将数据库任意类型全转字符串是没有问题的 下面封装存在一个问题就是需要数据库字段类型与实体类字段类型一致 实体类 //String columnName metaData.getColumnName(i 1); 这个方法返回实际列名 String columnLabel metaData.getColumnLabel(i 1);//该…

查看系统的核心信息

查看系统的版本 cat /etc/redhat-release查看系统的主机名 hostname uname -n 查看内核 uname -r查看网卡信息 ip a ifconfig 查看网关 ip route route -n netstat -rn 查看分区black大小 df -h 查看磁盘block大小 df -i 查看磁盘和分区大小 fdisk -l查看内存大小…

竞赛选题 深度学习YOLOv5车辆颜色识别检测 - python opencv

文章目录 1 前言2 实现效果3 CNN卷积神经网络4 Yolov56 数据集处理及模型训练5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习YOLOv5车辆颜色识别检测 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0…

Delay-Based 拥塞控制算法

上班七天了&#xff0c;有点崩溃&#xff0c;看一篇论文提神&#xff1a;A Delay-Based Approach for Congestion Avoidance in Interconnected Heterogeneous Computer networks&#xff0c;来自 Raj Jain&#xff0c;1989 年。这篇论文基于下图展开&#xff1a; 是不是很熟…

基于DBC Signal Group生成Autosar SR接口(2)

文章目录 前言m脚本生成BUS数据类型建立Input模块及关联对应的BUS数据类型实现效果总结 前言 上一篇文章中&#xff0c;介绍了DBC中SignalGroup的提取&#xff0c;对于已经提取好的Group信息&#xff0c;就可以批量操作生成Simulink BUS及Simulink接口模型了。本文介绍这部分的…

Element el-table 表格内容 样式错乱的问题

表格切换样式错乱展示 因为切换行的高度变化可能未异步渲染 解决方法&#xff1a; 在需要使用v-if渲染的el-table-column元素上加上一个不重复的key值即可解决问题 :key“Math.random()” <el-table-columnprop""label"问题"width"630.5px":…

你不一定知道的四种遍历进程的方法(c语言)

一、前言 有时候写代码的时候&#xff0c;我们需要遍历出系统的一些进程&#xff0c;一般我们是直接在任务管理器中查看&#xff0c;不过我们也可以自己写一个&#xff0c;下面小编将会从三个方面着手&#xff0c;给大家讲讲如何遍历进程。 二、系统快照 一般会用到了3个关键…

智慧公厕管理系统

在当今快速发展的科技时代&#xff0c;智慧城市管理成为了城市发展的重要趋势。而智慧公厕管理系统作为其中的一个重要组成部分&#xff0c;为公共卫生设施的管理提供了全新的解决方案&#xff0c;引领着智慧城市管理科技的新篇章。 一、智慧公厕管理系统的概念 什么是智慧公…

【基于windows desktop上的docker配置nacos,并采用宿主机访问】

1、拉取镜像&#xff08;以下命令全部基于powershell&#xff09; docker pull nacos/nacos-server2、启动容器 docker run -d -e PREFER_HOST_MODEhostname -e MODEstandalone -e JVM_XMS256m -e JVM_XMX256m -e JVM_XMN128m -p 8848:8848 --name nacos --restartalways nac…

VL53L5CX驱动开发(3)----检测阈值

VL53L5CX驱动开发----3.检测阈值 概述实现demo视频教学样品申请源码下载生成STM32CUBEMX选择MCU串口配置IIC配置 INT设置配置使能与复位X-CUBE-TOF1串口重定向代码配置TOF代码配置Kcps/SPAD定义状态说明演示结果 概述 本章展示如何使用VL53L5CX近接传感器的"检测阈值&quo…

vscode用密钥文件连接ssh:如果一直要输密码怎么办

commandshiftP&#xff1a;打开ssh配置文件 加上这么一段&#xff0c;host就是你给主机起的名字 对IdentityFile进行更改&#xff0c;改成相应的密钥文件 然后commandshiftP链接到主机就可以了 但是有时候它会让输入密码 这是由于你给这个IdentityFile的权限太多了&#xf…

【VTK】基础知识分析

很高兴在雪易的CSDN遇见你 &#xff0c;给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文分享VTK基础操作技术&#xff0c;记录vtk编程中常用的接口&#xff0c;变量等的创建及使用方法希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易…

程序包org.apache.commons.XXX不存在

看了好几个博客找这个出现的原因&#xff0c;最后亲测有用的&#xff1a; [IDEA]Java&#xff1a;“程序包XXX不存在”问题的三种解决方案 - lodalo - 博客园 (cnblogs.com) 使用第一种方式&#xff0c;不需要重启&#xff0c;就是在这个条件下输入&#xff1a;mvn idea:idea…

Ruby语言基础知识

Ruby是一种简单快捷的面向对象脚本语言&#xff0c;由日本人松本行弘&#xff08;Yukihiro Matsumoto&#xff09;在20世纪90年代开发&#xff0c;遵守GPL协议和Ruby License。它的灵感和特性来自于Perl、Smalltalk、Eiffel、Ada以及Lisp语言。 以下是Ruby语言的一些特点&#…

Mini小主机All-in-one搭建教程1-安装Esxi7.0虚拟机系统

Mini小主机All-in-one搭建教程1-安装Esxi7.0虚拟机系统 最近小主机似乎很火&#xff0c;知名不知名的品牌&#xff0c;都出了各自的小主机。今天主要介绍小主机下搭建教程安装Esxi、Openwrt、群晖NAS、Win11、centos7、黑苹果、Android-x86系统&#xff0c;这戏系统 搞得好是…

嵌入式C语言自我修养《GNU C编译器扩展语法》学习笔记

目录 一、C语言标准和编译器 二、指定初始化 三、宏构造“利器”&#xff1a;语句表达式 四、typeof与container_of宏 五、零长度数组 六、属性声明&#xff1a;section 七、属性声明&#xff1a;aligned 一、C语言标准和编译器 C语言标准的发展过程&#xff1a; ●…

想要精通算法和SQL的成长之路 - 前缀和的应用

想要精通算法和SQL的成长之路 - 前缀和的应用 前言一. 区域和检索 - 数组不可变二. 二维区域和检索 - 矩阵不可变2.1 前缀和的计算2.2 用前缀和计算二维区域和 三. 矩形区域不超过 K 的最大数值和 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 区域和检索 - 数组不可变 原…

c# xml 参数读取的复杂使用

完整使用2 生产厂家里面包含很多规格型号,一个规格型号里面包含很多出厂序列号,点击下一步如果检测到填充的和保存的不一样 就新增一条(如检测到生产厂家相同,但是规格型号不同,就新增一组规格型号)。 界面一:新增界面 界面2 删除界面 界面一:新增界面 load 其中…

导入Maven项目遇到的一些问题及解决

开发工具是IDEA&#xff0c; 一个Maven项目初次导入IDEA中&#xff0c;需要注意的几件事&#xff1a; 设置项目的编码格式&#xff08;或者提前设置全局的编码格式&#xff09;&#xff0c;一般是UTF-8&#xff1b;检查JDK版本和编译级别&#xff1b;检查Maven的版本&#xf…

centos7下安装elasticsearch7.8.1并配置远程连接

1、下载安装包 sudo wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.8.1-linux-x86_64.tar.gz 2、解压 sudo tar -zxvf elasticsearch-7.8.1-linux-x86_64.tar.gz 3、添加用户并设置密码 sudo useradd es sudo passwd es # 设置密码 Lida15…