竞赛保研 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)#训练svmdef 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:continueroot_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 = Nonecard_color = Nonefor 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)/2wave_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) #车牌字符数应大于6if len(wave_peaks) <= 6:print("peak less 1:", len(wave_peaks))continuewave = 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 = 0for i,wave in enumerate(wave_peaks):if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6:breakelse: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))continuepart_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")continuepart_card_old = part_cardw = abs(part_card.shape[1] - SZ)//2part_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])#判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1if charactor == "1" and i == len(part_cards)-1:if part_card_old.shape[0]/part_card_old.shape[1] >= 7:#1太细,认为是边缘continuepredict_result.append(charactor)roi = card_imgcard_color = colorbreakreturn predict_result, roi, card_color#识别到的字符、定位的车牌图像、车牌颜色

2.4 最终效果

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

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

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

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

最后

🧿 更多资料, 项目分享:

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

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

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

相关文章

Amazon Q:对话智能赋能企业发展

授权说明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 。 在最近举办的亚马逊云科技大会上&#xff0c;引人瞩目的消息是A…

西米支付:微信支付发布了一则重大公告!从2024年1月8日开始执行。

最近&#xff0c;微信支付发布通告表示对服务商合作协议和规则进行了修订。这次修订进一步明确了收单外包服务机构的备案义务&#xff0c;并加强了对违约合作伙伴的处理措施。 修订后的协议将于2024年1月8日开始生效。 根据修订后的协议&#xff0c;服务商需在开始提供收单外包…

斑马zebra目标检测数据集VOC+YOLO格式2300张

斑马是由四百万年前的原马进化出来的&#xff0c;最早出现的斑马可能是细纹斑马。有关史前马科动物的化石现存于美国爱达荷州克文的克文化石床国家博物馆。斑马的史前马为“克文马”&#xff08;美洲斑马或者克文斑马&#xff09;&#xff0c;学名为“Equussimplicidens”&…

Llinux面试题2

请描述一下 chmod 命令。 答&#xff1a;chmod 命令用于修改文件或目录的权限。它可以添加或删除对文件的读、写和执行权限。 在 Linux 中&#xff0c;如何修改文件的权限&#xff1f; 答&#xff1a;可以使用“chmod”命令来修改文件的权限。例如&#xff0c;通过以下命令将文…

​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案

随着“第四次工业革命”的爆炸式发展&#xff0c;众多企业都将自己的业务与迅速发展的应用开发和网站建设领域高度绑定。而对于众多有上云需求的企业和个人用户来说&#xff0c;选择一款自己的服务器配置就成为了一项至关重要的任务。而随着需求端的不断扩大&#xff0c;云服务…

第二步:私有镜像仓库Harbor的使用

前序&#xff1a; &#x1f517;第一步&#xff1a;私有镜像仓库Harbor的安装部署 一、将容器打包为镜像&#xff0c;上传到Harbor 1、查看镜像 输入命令 docker images打印返回 REPOSITORY TAG IMAGE ID CREATED …

Nacos-NacosRule 负载均衡—设置集群使本地服务优先访问

userservice: ribbon: NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 NacosRule 权重计算方法 目录 一、介绍 二、示例&#xff08;案例截图&#xff09; 三、总结 一、介绍 NacosRule是AlibabaNacos自己实现的一个负载均衡策略&…

《教育信息化论坛》期刊杂志论文发表投稿

《教育信息化论坛》由中原大地传媒股份有限公司主管&#xff0c;河南电子音像出版社、文心出版社主办&#xff0c;我刊立足于教育信息化、教育现代化科研&#xff0c;重点介绍国内外信息化、现代化教学手段、教学方式、教学传播研究的新成果和新观点&#xff0c;推广成功的国内…

【嵌入式开发 Linux 常用命令系列 14 -- source hello.sh 和 ./hello.sh 的区别】

文章目录 source hello.sh 和 ./hello.sh 的区别source hello.sh./hello.sh使用场景 source hello.sh 和 ./hello.sh 的区别 问题背景&#xff1a; 创建了目录~/.local/bin 并将其在.bashrc文件中添加到path 中&#xff0c;export PATH$PATH:/home/sam/.local/bin。 在 ~/.loc…

KVO(键值观察)

KVO&#xff08;键值观察&#xff09;是Objective-C 对观察者设计模式的一种实现。 举个栗子&#xff1a;指定一个被观察对象(A类)&#xff0c;当被观察对象某个属性(A中的字符串name)发生更改时&#xff0c;对象&#xff08;B类&#xff09;会获得通知&#xff0c;并作出相应…

【Spring教程28】Spring框架实战:从零开始学习SpringMVC 之 请求与请求参数详解

目录 1 设置请求映射路径1.1 环境准备 1.2 问题分析1.3 设置映射路径 2 请求参数2.1 环境准备2.2 参数传递2.2.1 GET发送单个参数2.2.2 GET发送多个参数2.2.3 GET请求中文乱码2.2.4 POST发送参数2.2.5 POST请求中文乱码 欢迎大家回到《Java教程之Spring30天快速入门》&#xff…

记录 | docker报错:Key permissions are too open: Set correct permissions

docker 报错&#xff1a; Key permissions are too open: Set correct permissions 具体的&#xff1a; WARNING: UNPROTECTED PRIVATE KEY FILE! Permissions 0777 for /app/.ssh/id_rsa are too open. It is required that your private key files are NOT accessibl…

ls高级用法

1 使用通配符列出文件夹的内容 ls ~/videos/*.wmv 刚才你已经学会了如何在包含多个文件的目录中查找文件&#xff0c;但是还有一种更快的方法。如果你知道正在找的Tiger Woods的视频文件是Windows Media格式的&#xff0c;那么这个文件名一定是以.wmv为后缀的&#xff0c;这时…

认识缓存,一文读懂Cookie,Session缓存机制。

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

一、CM4树莓派系统烧录

操作系统&#xff08;Raspberry Pi OS&#xff09;应用程序 Raspberry Pi OS系统&#xff08;树莓派推荐系统&#xff09;&#xff1a;较小的内存占用、较高的易用性以及对浮点单元的支持 浮点单元&#xff1a;浮点运算单元&#xff08;FPU&#xff09;是处理器中专门进行浮点…

windows redis 允许远程访问配置

安装好windows版本的redis&#xff0c;会以服务方式启动&#xff0c;但是不能远程访问&#xff0c;这个时候需要修改配置。redis安装路径下会有2个配置文件&#xff0c;究竟需要怎么修改才能生效呢&#xff1f;看下图 这里的redis服务指定了是redis.windows-service.conf文件&…

【CMU15445】Fall 2019, Project 4: Logging Recovery 实验记录

目录 实验准备实验测试Task 1: LOG MANAGER 实验准备 官方说明&#xff1a;https://15445.courses.cs.cmu.edu/fall2019/project4/ 实验测试 Task 1: cd build make log_manager_test ./test/log_manager_testTask 1: LOG MANAGER Log Manager 有一个全局的实例&#xff0…

Docker | 发布镜像到镜像仓库

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏:Docker系列 ✨特色专栏: MySQL学习 🥭本文内容:Docker | 发布镜像到镜像仓库 📚个人知识库: [Leo知识库]https://gaoziman.gitee.io/bl…

骨灰级程序员那些年曾经告诉我们的高效学习的态度

一、背景 以前阅读陈皓老师的左耳听风专栏中关于如何高效学习的总结让我收货颇丰&#xff0c;今天总结了一下&#xff0c;分享给大家 老师说&#xff1a; 学习是一件“逆人性”的事&#xff0c;就像锻炼身体一样&#xff0c;需要人持续付出&#xff0c;会让人感到痛苦&#…

c语言堆排序(详解)

堆排序 堆排序是一种基于二叉堆数据结构的排序算法&#xff0c;它的基本概念包括&#xff1a; 建立堆&#xff1a;将待排序的列表构建成一个二叉堆&#xff0c;即满足堆的性质的完全二叉树&#xff0c;可以是最大堆或最小堆。最大堆要求父节点的值大于等于其子节点的值&#x…