挑战杯 python+opencv+机器学习车牌识别

news2024/11/15 16:02:40

0 前言

🔥 优质竞赛项目系列,今天要分享的是

🚩 基于机器学习的车牌识别系统

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:4分
  • 工作量:4分
  • 创新点:3分

该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate


1 课题介绍

1.1 系统简介

车牌识别这个系统,虽然传统,古老,却是包含了所有这四个特侦的一个大数据技术的缩影.

在车牌识别中,你需要处理的数据是图像中海量的像素单元;你处理的数据不再是传统的结构化数据,而是图像这种复杂的数据;如果不能在很短的时间内识别出车牌,那么系统就缺少意义;虽然一副图像中有很多的信息,但可能仅仅只有那一小块的信息(车牌)以及车身的颜色是你关心,而且这些信息都蕴含着巨大的价值。也就是说,车牌识别系统事实上就是现在火热的大数据技术在某个领域的一个聚焦,通过了解车牌识别系统,可以很好的帮助你理解大数据技术的内涵,也能清楚的认识到大数据的价值。

1.2 系统要求

  • 它基于openCV这个开源库,这意味着所有它的代码都可以轻易的获取。
  • 它能够识别中文,例如车牌为苏EUK722的图片,它可以准确地输出std:string类型的"苏EUK722"的结果。
  • 它的识别率较高。目前情况下,字符识别已经可以达到90%以上的精度。

1.3 系统架构

整体包含两个系统:

  • 车牌检测
  • 车牌字体识别(中文 + 数字 + 英文)

整体架构如下:
在这里插入图片描述

2 实现方式

2.1 车牌检测技术

车牌检测(Plate Detection):

对一个包含车牌的图像进行分析,最终截取出只包含车牌的一个图块。这个步骤的主要目的是降低了在车牌识别过程中的计算量。如果直接对原始的图像进行车牌识别,会非常的慢,因此需要检测的过程。在本系统中,我们使用SVM(支持向量机)这个机器学习算法去判别截取的图块是否是真的“车牌”。

车牌检测这里不详细说明, 只贴出opencv图像处理流程, 需要代码的可以留下邮箱

在这里插入图片描述
使用到的图像处理算法

  • 高斯模糊
  • 灰度化处理
  • Sobel算子(边缘检测)
  • 开操作
  • 闭操作
  • 仿射变换
  • 霍姆线性检测
  • 角度矫正

2.2 车牌识别技术

字符识别(Chars Recognition):

有的书上也叫Plate
Recognition,我为了与整个系统的名称做区分,所以改为此名字。这个步骤的主要目的就是从上一个车牌检测步骤中获取到的车牌图像,进行光学字符识别(OCR)这个过程。其中用到的机器学习算法是著名的人工神经网络(ANN)中的多层感知机(MLP)模型。最近一段时间非常火的“深度学习”其实就是多隐层的人工神经网络,与其有非常紧密的联系。通过了解光学字符识别(OCR)这个过程,也可以知晓深度学习所基于的人工神经网路技术的一些内容。

我们这里使用深度学习的方式来对车牌字符进行识别, 为什么不用传统的机器学习进行识别呢, 看图就知道了:
在这里插入图片描述
图2 深度学习(右)与PCA技术(左)的对比
可以看出深度学习对于数据的分类能力的优势。

这里博主使用生成对抗网络进行字符识别训练, 效果相当不错, 识别精度达到了98%

在这里插入图片描述

2.3 SVM识别字符

定义

    
    class SVM(StatModel):
    	def __init__(self, C = 1, gamma = 0.5):
    		self.model = cv2.ml.SVM_create()
    		self.model.setGamma(gamma)
    		self.model.setC(C)
    		self.model.setKernel(cv2.ml.SVM_RBF)
    		self.model.setType(cv2.ml.SVM_C_SVC)
    #训练svm
    	def train(self, samples, responses):
    		self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)

调用方法,喂数据

    
    	def train_svm(self):
    		#识别英文字母和数字
    		self.model = SVM(C=1, gamma=0.5)
    		#识别中文
    		self.modelchinese = SVM(C=1, gamma=0.5)
    		if os.path.exists("svm.dat"):
    			self.model.load("svm.dat")

训练,保存模型

else:
​    			chars_train = []
​    			chars_label = []for root, dirs, files in os.walk("train\\chars2"):
    				if len(os.path.basename(root)) > 1:
    					continue
    				root_int = ord(os.path.basename(root))
    				for filename in files:
    					filepath = os.path.join(root,filename)
    					digit_img = cv2.imread(filepath)
    					digit_img = cv2.cvtColor(digit_img, cv2.COLOR_BGR2GRAY)
    					chars_train.append(digit_img)
    					#chars_label.append(1)
    					chars_label.append(root_int)
    			
    			chars_train = list(map(deskew, chars_train))
    			chars_train = preprocess_hog(chars_train)
    			#chars_train = chars_train.reshape(-1, 20, 20).astype(np.float32)
    			chars_label = np.array(chars_label)
    			print(chars_train.shape)
    			self.model.train(chars_train, chars_label)

车牌字符数据集如下

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

这些是字母的训练数据,同样的还有我们车牌的省份简写:

在这里插入图片描述

在这里插入图片描述

核心代码

   predict_result = []
    		roi = None
    		card_color = None
    		for i, color in enumerate(colors):
    			if color in ("blue", "yello", "green"):
    				card_img = card_imgs[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)
    				for i, part_card in enumerate(part_cards):
    					#可能是固定车牌的铆钉
    					if np.mean(part_card) < 255/5:
    						print("a point")
    						continue
    					part_card_old = part_card
    					w = abs(part_card.shape[1] - SZ)//2
    					
    					part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value = [0,0,0])
    					part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA)
    					
    					#part_card = deskew(part_card)
    					part_card = preprocess_hog([part_card])
    					if i == 0:
    						resp = self.modelchinese.predict(part_card)
    						charactor = provinces[int(resp[0]) - PROVINCE_START]
    					else:
    						resp = self.model.predict(part_card)
    						charactor = chr(resp[0])
    					#判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1
    					if charactor == "1" and i == len(part_cards)-1:
    						if part_card_old.shape[0]/part_card_old.shape[1] >= 7:#1太细,认为是边缘
    							continue
    					predict_result.append(charactor)
    				roi = card_img
    				card_color = color
    				break
    				
    		return predict_result, roi, card_color#识别到的字符、定位的车牌图像、车牌颜色

2.4 最终效果

最后算法部分可以和你想要的任何UI配置到一起:

可以这样 :
在这里插入图片描述

也可以这样:
在这里插入图片描述

甚至更加复杂一点:
在这里插入图片描述

最后

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

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

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

相关文章

PyTorch的10个基本张量操作

PyTorch是一个基于python的科学计算包。它的灵活性允许轻松集成新的数据类型和算法&#xff0c;并且框架也是高效和可扩展的&#xff0c;下面我们将介绍一些Pytorch的基本张量操作。 Tensors 张量Tensors是一个向量&#xff0c;矩阵或任何n维数组。这是深度学习的基本数据结构…

企业计算机服务器中了halo勒索病毒如何解密,halo勒索病毒数据恢复

对于众多的企业来说&#xff0c;数据是一个企业的发展的根基&#xff0c;通过数据可以更好地规划调整企业的发展方向&#xff0c;提高企业生产效率。但网络是一把双刃剑&#xff0c;网络技术的发展不仅会为企业带来极大便利&#xff0c;但也为企业数据安全带来严重威胁。近期&a…

谈谈BlueFS

目录 前言数据结构标识一个文件文件系统的全局记录事务记录超级块 启动流程磁盘管理读写流程创建文件流程为文件写数据把数据下刷到磁盘读流程 参考资料 前言 BlueFS具体是个什么东西呢&#xff1f; 如上图&#xff0c;在Ceph里&#xff0c;使用BlueStore作为默认的存储引擎。…

LLM(大语言模型)——大模型简介

目录 概述 发展历程 大语言模型的概念 LLM的应用和影响 大模型的能力、特点 大模型的能力 涌现能力&#xff08;energent abilities&#xff09; 作为基座模型支持多元应用的能力 支持对话作为统一入口的能力 大模型的特点 常见大模型 闭源LLM&#xff08;未公开源…

datax离线同步oracle表到clickhouse实践1

时间&#xff1a;2024.01 目录1、安装启动 oracle19c 容器 2、rpm包安装clickhouse 3、datax安装 4、datax同步 目标库根据要同步的表&#xff0c;按照clickhouse建表规范建表 编写json文件 编写增量同步shell脚本&#xff0c;加入 crond 定时任务 1、安装启动 oracle19c 容器…

关于如何在Mac上安装Windows,看这篇文章就差不多了

启动转换(Boot Camp)助手可以让你在一些Mac电脑上安装Windows并引导到其中,就像在普通电脑上一样。现代苹果硅型号(M1、M2等)不支持启动转换助手,必须使用其他方法来运行Windows。 可以在M1或M2 Mac上使用启动转换助手吗 只有当Mac上有Intel(x86)处理器时,才能使用启…

Arcgis使用过程中常见问题解决方法

Arcgis无法连接数据库/数据库连接或创建失败解决方法 最近在使用arcgis过程中出现无法连接数据库或者是无法创建数据库。连接到数据库失败&#xff1b;无法创建新的数据库&#xff0c;权限被拒绝&#xff08;如下图&#xff09;。 出现这个原因是你所用的电脑系统文件dao360.…

生存类游戏《幻兽帕鲁》从部署服务器到开始体验全过程

SteamDB数据显示&#xff0c;《幻兽帕鲁》上线24小时内&#xff0c;在线人数峰值便突破200万&#xff0c;跻身Steam历史排行榜第二位。随着热度进一步发酵&#xff0c;《幻兽帕鲁》官方发布推文称&#xff0c;游戏发售不到6天&#xff0c;销量已经突破了 800万份。欢迎大家在阿…

香港公司员工遭遇2亿港币Deepfake诈骗; 阿里巴巴Qwen1.5震撼发布;通义千问App推新功能迎佳节

&#x1f989; AI新闻 &#x1f680; 香港公司员工遭遇2亿港币Deepfake诈骗 摘要&#xff1a;近日&#xff0c;香港一家英国跨国企业的员工被Deepfake技术仿造的视频诈骗&#xff0c;损失2亿港币。骗子通过伪造高管的面貌和声音&#xff0c;用视频会议的形式命令其转账&#…

双非本科准备秋招(17.1)—— 力扣二叉树

1、257. 二叉树的所有路径 要求返回根节点到叶子节点的所有路径&#xff0c;这里用前序遍历就好。 每次递归前&#xff0c;都让字符串s加上当前节点的值和“->”&#xff0c;然后判断是否为叶子节点&#xff0c;如果是的话&#xff0c;说明这条路径是一个答案&#xff0c;因…

基于springboot实现二次元商品购物系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现二次元商品购物系统演示 摘要 时代的变化速度实在超出人类的所料&#xff0c;21世纪&#xff0c;计算机已经发展到各行各业&#xff0c;各个地区&#xff0c;它的载体媒介-计算机&#xff0c;大众称之为的电脑&#xff0c;是一种特高速的科学仪器&#xff0…

python + 蒙特卡罗 = 股市神器! 能用到A股吗?

蒙特卡罗模拟作为一种在金融领域广泛应用的强大统计技术&#xff0c;能够对金融资产&#xff08;例如股票&#xff09;的行为进行模拟建模。在本文中&#xff0c;我们将深入探讨如何在Python编程环境中实现蒙特卡罗模拟&#xff0c;以预测股票市场未来可能出现的情况。我们将利…

MySQL进阶45讲【12】为什么你的MySQL偶尔会卡一下

1 前言 平时的工作中&#xff0c;不知道大家有没有遇到过这样的场景&#xff0c;一条SQL语句&#xff0c;正常执行的时候特别快&#xff0c;但是有时也不知道怎么回事&#xff0c;它就会变得特别慢&#xff0c;并且这样的场景很难复现&#xff0c;它不只随机&#xff0c;而且持…

【Linux驱动】块设备驱动(二)—— 块设备读写(使用请求队列)

块设备的操作函数并没有类似于字符驱动中的read 和write函数&#xff0c;要实现读写操作&#xff0c;只能在请求处理函数中实现。这就分为两种&#xff0c;是否要使用请求队列&#xff0c;请求队列的主要作用是管理和调度IO请求。在以下情况中&#xff0c;一般需要用到请求队队…

Kafka 使用手册

kafka3.0 文章目录 kafka3.01. 什么是kafka&#xff1f;2. kafka基础架构3. kafka集群搭建4. kafka命令行操作主题命令行【topic】生产者命令行【producer】消费者命令行【consumer】 5. kafka生产者生产者消息发送流程Producer 发送原理普通的异步发送带回调函数的异步发送同步…

虚幻5源码版打包服务端

适用情况&#xff0c;windows系统&#xff0c;已经安装vs2022之类的&#xff0c;和UE5适配的版本 源码版使用 1.下载源码版&#xff0c;推荐下载 压缩包 tar.gz那个&#xff0c;zip和git clone我老是下载不下载来&#xff0c;只是这个压缩包要解压1个多小时… 2.点击 源码的…

C语言-4

排序算法简介 /*学习内容&#xff1a;冒泡排序&#xff08;最基本的排序方法&#xff09;选择排序&#xff08;冒泡的优化&#xff09;插入排序&#xff08;在合适的位置插入合适的数据&#xff09; *//*排序分类&#xff1a;1.内部排序待需要进行排序的数据全部存放到内存中&…

【Python基础】案例分析:电商分析

电商分析 1 案例:某年淘宝双12部分购物数据 1.1 数据&#xff1a;某年淘宝双12部分购物数据&#xff1b; 来源&#xff1a;天池数据平台 1.2 分析目的&#xff1a; 熟悉电商常用分析指标用户行为分析用户价值模型 2 熟悉数据 2.1 导入数据 import pandas as pd fpath …

Vscode编译运行多个C++文件

1.摘要 在使用Vscode编译单个文件网上很多教程&#xff0c;但是对多个文件编译会发现经常出问题&#xff0c;通过不断的借阅网友的教程改进终于完成C运行多个文件教程如下&#xff1a; 2.编译运行过程 2.1 初始配置过程 &#xff08;1&#xff09;Vscode以及MinGW配置教程很…

EasyRecovery数据恢复软件2024最新特别绿色版下载

EasyRecovery数据恢复软件是一款功能强大的工具&#xff0c;最新版本通常包含更多优化和新增功能&#xff0c;以提升用户体验和数据恢复成功率。由于软件版本会不断更新&#xff0c;我无法提供特定于最新版本的详细介绍&#xff0c;但我可以概述EasyRecovery的一般功能以及下载…