竞赛保研 python+opencv+机器学习车牌识别

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.mfbz.cn/a/245934.html

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

相关文章

什么是纯净IP?如何判断IP地址的纯净度?有哪些干净IP推荐?

您是否想知道什么使代理“干净”或如何确保您的代理不会将您列入网站的黑名单&#xff1f;对于通过代理访问网络的人来说&#xff0c;干净的代理是无缝在线体验的重要组成部分。在这篇文章中&#xff0c;我们将深入研究干净代理的世界&#xff0c;并探讨决定其质量的因素。 一、…

k8s常用命令及示例(三):apply 、edit、delete

k8s常用命令及示例(三)&#xff1a;apply 、edit、delete 1. kubectl apply -f 命令&#xff1a;从yaml文件中创建资源对象。 -f 参数为强制执行。kubectl apply和kubectl create的区别如下&#xff1a;kubectl create 和 kubectl apply 是 Kubernetes 中两个常用的命令&…

加速数据采集:用OkHttp和Kotlin构建Amazon图片爬虫

引言 曾想过轻松获取亚马逊上的商品图片用于项目或研究吗&#xff1f;是否曾面对网络速度慢或被网站反爬虫机制拦截而无法完成数据采集任务&#xff1f;如果是&#xff0c;那么本文将为您介绍如何用OkHttp和Kotlin构建一个高效的Amazon图片爬虫解决方案。 背景介绍 亚马逊&a…

Spring Boot之自定义starter

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Spring Boot的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一. starter是什么 二.为什么要使…

万界星空科技AI低代码云MES系统

在企业生产管理过程中&#xff0c;从市场、生产现场到产品交付&#xff0c;生产制造行业都面临着诸多挑战&#xff0c;比如&#xff1a; 订单排产难度大&#xff1a;订单混乱&#xff0c;常漏排产、错排产&#xff1b;产能不明晰&#xff0c;无法承诺交期&#xff0c;常丢单&a…

智慧工地源码(微服务+Java+Springcloud+Vue+MySQL)

智慧工地系统是依托物联网、互联网、AI、可视化建立的大数据管理平台&#xff0c;是一种全新的管理模式&#xff0c;能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度&#xff0c;以及施工过程管理的进度、质量、安全三…

python selenium chrome114版本之后环境配置和携带缓存打开chrome

尽力局 chrome驱动环境配置chrome打开带缓存设置待缓存打开自动关闭浏览器自动关闭浏览器弹窗 最终代码找资料难啊最终效果代码 依赖包和生成依赖包方法关闭谷歌升级 chrome驱动环境配置 网上找到的资料&#xff0c;我现在安装的是120版本的&#xff0c;这个资料是可行的。比较…

物流实时数仓:数仓搭建(DWD)一

系列文章目录 物流实时数仓&#xff1a;采集通道搭建 物流实时数仓&#xff1a;数仓搭建 物流实时数仓&#xff1a;数仓搭建&#xff08;DIM&#xff09; 物流实时数仓&#xff1a;数仓搭建&#xff08;DWD&#xff09;一 文章目录 系列文章目录前言一、文件编写1.目录创建2.b…

亚信科技AntDB数据库——深入了解AntDB-M元数据锁的实现(一)

锁的获取 5.1 锁的强弱 当线程已经持有的锁比新申请的锁更强时&#xff0c;认为已经持有了锁&#xff0c;无需再对申请锁类型加锁。锁的强弱指持有的锁与其他锁的不兼容集合大小&#xff0c;集合相同锁相同&#xff0c;集合更大锁更强&#xff0c;否则无强弱关系。通过锁的兼…

Kafka-Kafka基本原理与集群快速搭建

一、Kafka介绍 ​ ChatGPT对于Apache Kafka的介绍&#xff1a; Apache Kafka是一个分布式流处理平台&#xff0c;最初由LinkedIn开发并于2011年开源。它主要用于解决大规模数据的实时流式处理和数据管道问题。 Kafka是一个分布式的发布-订阅消息系统&#xff0c;可以快速地处理…

JAVA:深入探讨Map的多种遍历方式

1、简述 在现代编程中&#xff0c;Map&#xff08;映射&#xff09;是一种常见的数据结构&#xff0c;用于存储键-值对。在许多编程语言中&#xff0c;Map提供了灵活的数据组织方式&#xff0c;但为了充分发挥其功能&#xff0c;我们需要了解多种遍历方式。本文将深入探讨Map的…

龙迅LT2611UXC 双PORT LVDS转HDMI(2.0)+音频

描述&#xff1a; LT2611UXC是一个高性能的LVDS到HDMI2.0的转换器&#xff0c;用于STB&#xff0c;DVD应用程序。 LVDS输入可配置为单端口或双端口&#xff0c;有1个高速时钟通道&#xff0c;3~4个高速数据通道&#xff0c;最大运行1.2Gbps/通道&#xff0c;可支持高达9.6Gbp…

牛客网SQL训练2—SQL基础进阶

文章目录 一、基本查询二、数据过滤三&#xff1a;函数四&#xff1a;分组聚合五&#xff1a;子查询六&#xff1a;多表连接七&#xff1a;组合查询八&#xff1a;技能专项-case when使用九&#xff1a;多表连接-窗口函数十&#xff1a;技能专项-having子句十一&#xff1a;技能…

桂电|《操作系统》实验一:UNIX/LINUX及其使用环境(实验报告)

桂林电子科技大学2023-2024学年 第 一 学期 操作系统A 实验报告 实验名称 实验一 UNIX/LINUX及其使用环境 实验指导老师&#xff1a; 成绩 院 系 计算机与信息安全学院 专业 计算机科学与技术(卓越工程) 学 号 姓名 课内序…

保姆级 Keras 实现 YOLO v3 三

保姆级 Keras 实现 YOLO v3 三 一. 分配 anchor box二. 正负样本匹配规则三. 为每一个 anchor box 打标签3.1 anchor box 长什么样?3.2 每一个 anchor box 标签需要填充的信息有哪些?3.3 ( Δ x , Δ y , Δ w , Δ h ) (\Delta x, \Delta y, \Delta w, \Delta h) (Δx,Δy,…

uniapp交互反馈api的使用示例

官方文档链接&#xff1a;uni.showToast(OBJECT) | uni-app官网 1.uni.showToast({}) 显示消息提示框。 常用属性&#xff1a; title:页面提示的内容 image&#xff1a;改变提示框默认的icon图标 duration&#xff1a;提示框在页面显示多少秒才让它消失 添加了image属性后。 注…

vs code 设置了自动格式化保存 但是json 配置文件不想自动格式化

vscode 点击文件>首选项>设置>点击打开设置 >转化成文本格式 "editor.formatOnSave": true, "[json]": { "editor.formatOnSave": false }, 即可

智安网络|计算机视觉在城市交通中的前景与变化

随着科技的不断发展&#xff0c;计算机视觉技术在各个领域扮演着越来越重要的角色。在交通领域&#xff0c;计算机视觉为智能交通系统带来了许多机遇&#xff0c;为城市交通管理和出行体验提供了前所未有的可能性。 首先&#xff0c;计算机视觉技术可以用于智能交通监控。传统…

力扣题:数字与字符串间转换-12.15

力扣题-12.15 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;592. 分数加减运算 解题思想&#xff1a;首先通过对表达式进行分离&#xff0c;然后利用分数的加法原则进行计算&#xff0c;最后除以最大公因数即可 class Solution(object):def fra…

【MATLAB】数据拟合第10期-二阶多项式的局部加权回归拟合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 二阶多项式局部加权回归拟合算法是一种用于回归分析的方法&#xff0c;主要通过局部加权线性回归模型来实现。以下是对二阶多项式局部加权回归拟合算法的介绍&#xff1a; 局部加权线性回…
最新文章