Python 基于机器学习模型的车牌检测和识别系统 有GUI界面 【含Python源码 MX_004期】

一、系统介绍

        车牌的检测和识别技术在现代社会中的应用场景可谓十分广泛,不仅涉及交通管理领域,还延伸至社区安保等多个方面。例如,在交通违章管理中,通过车牌追踪可以有效追踪违章车辆,维护交通秩序;在小区或地下车库的门禁系统中,车牌识别则能实现快速、准确的车辆进出管理。在车牌识别和检测的过程中,由于车牌具有独特的物理特性,如规整的矩形形状、固定的长宽比、特定的色调和纹理等,使得我们可以利用多种方法来进行有效的识别和检测。传统的基于形状的方法,通过识别车牌的矩形轮廓来定位车牌位置;基于色调的方法,则利用车牌特有的颜色和色调信息来区分车牌和其他物体;而基于纹理的方法,则是通过分析车牌表面的纹理特征来识别车牌。此外,有基于文字特征的方法,通过分析车牌上的字符特征来进行识别。

本文在车牌检测和识别的项目中,主要的流程可以分为以下几个步骤:

        首先我们需要输入原始图片,并对其进行预处理。通过二值化操作,将图片转换为黑白二值图像,以简化后续的处理过程;接着利用边缘检测技术,提取出图片中的边缘信息,进一步确定车牌的轮廓;最后通过基于色调的颜色微调方法,对车牌的颜色进行微调,以提高车牌识别的准确性。

        其次我们需要定位并裁剪出车牌区域。在预处理后的图像中,我们可以根据车牌的矩形形状和长宽比等特征,利用图像分割技术将车牌区域从背景中分离出来;然后通过裁剪操作,将车牌区域从原始图像中提取出来,为后续的识别工作做好准备。

        接下来我们需要对裁剪出的车牌进行进一步的处理和识别。一种常用的方法是基于直方图的波峰波谷分割法。这种方法通过分析车牌图像的直方图特征,找到波峰和波谷的位置,从而将车牌字符从背景中分割出来;然后通过训练好的机器学习模型对分割出的字符进行识别。在这个项目中,我们训练了两个支持向量机(SVM)模型,一个用于识别省份简称(如“鲁”),另一个用于识别字母和数字。这些模型通过大量的训练数据学习车牌字符的特征表示,从而实现对车牌字符的准确识别。

        最后为了方便用户使用和部署,我们利用PyQt5框架将整个算法封装成一个图形用户界面(GUI)程序。通过GUI程序,用户可以方便地输入原始图片、查看识别和检测结果、以及进行其他相关操作。此外我们还对整个程序进行了打包和发布,使其可以作为一个独立的安装软件供用户使用。

二、系统界面

三、部分代码:

def Cardseg(rois,colors,save_path):
	'''
	把一个roi列表和color列表,对应的每个车牌分割成一个一个的字
	然后做预测分类

	当然也可以考虑OCR的办法,这里使用的是传统的分类问题解决的!!!!

	'''
	seg_dic = {}
	old_seg_dic = {}
	for i, color in enumerate(colors):
		if color in ("blue", "yello", "green"):
			card_img = rois[i]
			gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY)
			#黄、绿车牌字符比背景暗、与蓝车牌刚好相反,所以黄、绿车牌需要反向
			if color == "green" or color == "yello":
				gray_img = cv2.bitwise_not(gray_img)
			ret, gray_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
			#查找水平直方图波峰
			x_histogram  = np.sum(gray_img, axis=1)
			x_min = np.min(x_histogram)
			x_average = np.sum(x_histogram)/x_histogram.shape[0]
			x_threshold = (x_min + x_average)/2
			wave_peaks = find_waves(x_threshold, x_histogram)
			if len(wave_peaks) == 0:
				# print("peak less 0:")
				continue

			#认为水平方向,最大的波峰为车牌区域
			wave = max(wave_peaks, key=lambda x:x[1]-x[0])
			gray_img = gray_img[wave[0]:wave[1]]

			#查找垂直直方图波峰
			row_num, col_num= gray_img.shape[:2]
			#去掉车牌上下边缘1个像素,避免白边影响阈值判断
			gray_img = gray_img[1:row_num-1]
			y_histogram = np.sum(gray_img, axis=0)
			y_min = np.min(y_histogram)
			y_average = np.sum(y_histogram)/y_histogram.shape[0]
			y_threshold = (y_min + y_average)/5 #U和0要求阈值偏小,否则U和0会被分成两半

			wave_peaks = find_waves(y_threshold, y_histogram)

			#for wave in wave_peaks:
			#	cv2.line(card_img, pt1=(wave[0], 5), pt2=(wave[1], 5), color=(0, 0, 255), thickness=2) 

			#车牌字符数应大于6
			if len(wave_peaks) <= 6:
				# print("peak less 1:", len(wave_peaks))
				continue
			wave = max(wave_peaks, key=lambda x:x[1]-x[0])
			max_wave_dis = wave[1] - wave[0]
			
			#判断是否是左侧车牌边缘
			if wave_peaks[0][1] - wave_peaks[0][0] < max_wave_dis/3 and wave_peaks[0][0] == 0:
				wave_peaks.pop(0)
			
			#组合分离汉字
			cur_dis = 0
			for i,wave in enumerate(wave_peaks):
				if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6:
					break
				else:
					cur_dis += wave[1] - wave[0]
			if i > 0:
				wave = (wave_peaks[0][0], wave_peaks[i][1])
				wave_peaks = wave_peaks[i+1:]
				wave_peaks.insert(0, wave)
			
			#去除车牌上的分隔点
			point = wave_peaks[2]
			if point[1] - point[0] < max_wave_dis/3:
				point_img = gray_img[:,point[0]:point[1]]
				if np.mean(point_img) < 255/5:
					wave_peaks.pop(2)
			
			if len(wave_peaks) <= 6:
				# print("peak less 2:", len(wave_peaks))
				continue
			part_cards = seperate_card(gray_img, wave_peaks)
def accurate_place(card_img_hsv, limit1, limit2, color,cfg):
	row_num, col_num = card_img_hsv.shape[:2]
	xl = col_num
	xr = 0
	yh = 0
	yl = row_num
	#col_num_limit = cfg["col_num_limit"]
	row_num_limit = cfg["row_num_limit"]
	col_num_limit = col_num * 0.8 if color != "green" else col_num * 0.5 # 绿色有渐变
	for i in range(row_num):
		count = 0
		for j in range(col_num):
			H = card_img_hsv.item(i, j, 0)
			S = card_img_hsv.item(i, j, 1)
			V = card_img_hsv.item(i, j, 2)
			if limit1 < H <= limit2 and 34 < S and 46 < V:
				count += 1
		if count > col_num_limit:
			if yl > i:
				yl = i
			if yh < i:
				yh = i
	for j in range(col_num):
		count = 0
		for i in range(row_num):
			H = card_img_hsv.item(i, j, 0)
			S = card_img_hsv.item(i, j, 1)
			V = card_img_hsv.item(i, j, 2)
			if limit1 < H <= limit2 and 34 < S and 46 < V:
				count += 1
		if count > row_num - row_num_limit:
			if xl > j:
				xl = j
			if xr < j:
				xr = j
	return xl, xr, yh, yl

四、完整代码:Python 基于机器学习模型的车牌检测和识别系统

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【UML用户指南】-05-对基本结构建模-类

在UML中&#xff0c;所有的事物都被建模为类。类是对词汇表中一些事物的抽象。类不是个体对象&#xff0c;而是描述一些对象的一个完整集合。 强调抽象的最重要的部分&#xff1a;名称、属性和操作 类 &#xff08;class&#xff09;是对一组具有相同属性、操作、关系和语义的对…

JVM垃圾收集器和内存分配策略

概述 Java内存运行时数据区的程序计数器、虚拟机栈、本地方法栈3个区域会随着线程而产生&#xff0c;随线程而消失。这几个区域分配多少内存时在类结构确定下来即已知的&#xff0c;在这几个区域内就不需要过多考虑如何回收内存的问题&#xff0c;当方法结束或者线程结束时&am…

第三届大湾区算力大会丨暴雨开启数字未来新篇

5月30-31日&#xff0c;韶关市迎来主题为“算启新篇智创未来”的第三届粤港澳大湾区(广东)算力产业大会暨第二届中国算力网大会&#xff0c;活动由广东省人民政府主办&#xff0c;广东省政数局、韶关市人民政府共同承办。暴雨信息作为算力产业发展的重要构建者受邀赴会&#xf…

【C++进阶】深入STL之string:模拟实现走进C++字符串的世界

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;C模板入门 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之string &#x1f4d2;1. string…

力扣575. 分糖果

题目&#xff1a; Alice 有 n 枚糖&#xff0c;其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长&#xff0c;所以前去拜访了一位医生。 医生建议 Alice 要少摄入糖分&#xff0c;只吃掉她所有糖的 n / 2 即可&#xff08;n 是一个偶数&#xff09;。Alic…

Java中连接Mongodb进行操作

文章目录 1.引入Java驱动依赖2.快速开始2.1 先在monsh连接建立collection2.2 java中快速开始2.3 Insert a Document2.4 Update a Document2.5 Find a Document2.6 Delete a Document 1.引入Java驱动依赖 注意&#xff1a;启动服务的时候需要加ip绑定 需要引入依赖 <dependen…

Java的数据库编程-----JDBC

目录 一.JDBC概念&使用条件&#xff1a; 二.mysql-connector驱动包的下载与导入&#xff1a; 三.JDBC编程&#xff1a; 使用JDBC编程的主要五个步骤&#xff1a; 完整流程1&#xff08;更新update&#xff09;&#xff1a; 完整流程2(查询query)&#xff1a; 一.JDB…

FS212E 系列PD协议

PD快充协议芯片FS212EL、FS212EH可以智能的识别插入的手机类型&#xff0c;选择最为合适的协议应对手机快充需要。兼容多类USB Type-C协议&#xff0c;包括TypeC协议、TypeC PD2.0、TypeC PD3.0、TypeC PD3.2等协议。集成OPTO输出&#xff0c;通过电阻直驱反馈光耦。FS212E 的调…

【STL】C++ queue队列(包含优先级队列) 基本使用

目录 一 queue 1 常见构造 1 空容器构造函数 2. 使用指定容器构造 3 拷贝构造函数 2 empty 3 size 4 front && back 5 push && pop 6 emplace 7 swap 二 优先级队列( priority_queue) 1 常见构造 2 其他操作 3 大堆和小堆 1. 大小堆切换 2 自…

961题库 北航计算机 MIPS基础选择题 附答案 选择题形式

有题目和答案&#xff0c;没有解析&#xff0c;不懂的题问大模型即可&#xff0c;无偿分享。 第1组 习题 MIPS处理器五级流水线中&#xff0c;涉及DRAM的是 A. 取指阶段 B. 译码阶段 C. 执行阶段 D. 访存阶段 MIPS处理器五级流水线中&#xff0c;R型指令保存结果的阶段是 A.…

Mixly UDP局域网收发数据

一、开发环境 软件&#xff1a;Mixly 2.0在线版 硬件&#xff1a;ESP32-C3&#xff08;立创实战派&#xff09; 固件&#xff1a;ESP32C3 Generic(UART) 测试工具&#xff1a;NetAssist V5.0.1 二、实现功能 ESP32作为wifi sta连接到路由器&#xff0c;连接成功之后将路由器…

基于Django的博客系统之增加类别导航栏(六)

上一篇&#xff1a;基于Django的博客系统之用HayStack连接elasticsearch增加搜索功能&#xff08;五&#xff09; 下一篇&#xff1a; 功能概述 博客类型导航栏。 需求详细描述 1. 博客类型导航栏 描述&#xff1a; 在博客首页添加类型导航栏&#xff0c;用户可以通过导航…

属性(property)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 1 创建用于计算的属性 在Python中&#xff0c;可以通过property&#xff08;装饰器&#xff09;将一个方法转换为属性&#xff0c;从而实现用于计算…

vue3-调用API实操-调用开源头像接口

文档部分 这边使用是开源的API 请求地址: &#xff1a;https://api.uomg.com/api/rand.avatar 返回格式 : json/images 请求方式: get/post 请求实例: https://api.uomg.com/api/rand.avatar?sort男&formatjson 请求参数 请求参数说明 名称必填类型说明sort否strin…

探索安全之道 | 企业漏洞管理:从理念到行动

如今&#xff0c;网络安全已经成为了企业管理中不可或缺的一部分&#xff0c;而漏洞管理则是网络安全的重中之重。那么企业应该如何做好漏洞管理呢&#xff1f;不妨从业界标准到企业实践来一探究竟&#xff01;通过对业界标准的深入了解&#xff0c;企业可以建立起完善的漏洞管…

算法每日一题(python,2024.05.28) day.10

题目来源&#xff08;力扣. - 力扣&#xff08;LeetCode&#xff09;&#xff0c;中等&#xff09; 解题思路&#xff1a; 辅助数组 找规律&#xff0c;设旋转前某点matrix[i][j]&#xff0c;则旋转后改点变为matrix[j][n&#xff0d;1&#xff0d;i]&#xff08;n为len(matr…

LLVM后端__llc中值定义信息的查询方法示例

关于LiveIntervals pass中相关数据结构的含义&#xff0c;在寄存器分配前置分析(5.1) - LiveInterval这篇博客中已经做了清晰的讲解&#xff0c;此处不再赘述&#xff0c;本文主要讲解值定义信息VNInfo的使用方法和注意事项。 1. VNInfo含义 在LLVM的源码中&#xff0c;VNInf…

!力扣 108. 将有序数组转换为二叉搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按升序排列&#xff0c;请你将其转换为一棵 平衡二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,null,9] 也将被视为正确答案…

Java——异常

1.什么是异常 将程序执行过程中发生的不正常行为称为异常。 常见的异常有&#xff1a;算数异常&#xff0c;空指针异常&#xff0c;数组越界异常 每一种异常都有对应的类对齐描述 为了对每一种异常进行管理&#xff0c;Java内部实现了一个对异常的体系结构 1. Throwable&#x…

HNCTF2022 REVERSE

[HNCTF 2022 WEEK2]esy_flower 简单花指令 Nop掉 然后整段u c p然后就反汇编 可能反编译的不太对&#xff0c;&#xff0c;看了别人的wp就是ida反编译的有问题 #include<stdio.h> #include<string.h> int main() {int i,j;char ch[]"c~scvdzKCEoDEZ[^roDICU…