基于SVM的车牌识别算法

基于SVM的车牌识别系统(Python代码实现)

车牌识别系统是智能交通系统的重要组成部分,有着广泛的应用。车牌识别系统主要有车牌定位、字符分割和字符识别三部分组成,本文的研究重点是车牌字符识别这部分,本文提出了一种基于OpenCVSVM的车牌识别方法。首先通过Soble边缘检测算法与形态学算法相结合来确定大致的车牌轮廓,结合车牌的外接矩形的面积与长宽比来筛选出符合车牌特征的候选区域,然后使用投影法将车牌中的字符分割出来,最后使用SVM分类器来对分割出的字符进行识别,输出识别结果。经过验证,该车牌识别系统能够适用于比较复杂的环境,识别准确率相对较高。为了提升该系统的可操作性,本文使用PyQt5设计了GUI界面,提升了系统的可操作性,同时使界面更加美观。

一、算法流程

一个完整的车牌号识别系统要完成从图像采集到字符识别输出,过程相当复杂,基本可以分成硬件部分跟软件部分,硬件部分包括系统触发、图像采集,软件部分包括图像预处理车牌定位字符分割字符识别四大部分,一个车牌识别系统的基本结构如图:

在这里插入图片描述

二、图像预处理

获取蓝色和绿色通道:

    hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)  # 将RGB图像转换为HSV图像h, s, v = cv2.split(hsv)  # 分离H,S,Vlower = np.array([100, 90, 40])upper = np.array([124, 255, 255])  # 设置阈值mask = cv2.inRange(hsv, lower, upper)  # 获取图像蒙版img = cv2.bitwise_and(s, s, mask=mask)  # 在图像蒙版上使用“按位与”运算符吗,分离绿色和蓝色通道

处理结果:在这里插入图片描述

直方图均衡化:

    img = cv2.equalizeHist(img)  # 直方图均衡化,增强对比度:将已知灰度概率密度分布的图像经过变换,使其称为一个均匀灰度概率密度分布的新图像img = cv2.GaussianBlur(img, (3, 3), 0, 0, cv2.BORDER_DEFAULT)  # 高斯滤波

处理结果:
在这里插入图片描述
检测图像中的纹理:

    flipped = cv2.flip(img, 1)  # 图像翻转,1:水平翻转sobel1 = cv2.Sobel(img, cv2.CV_8U, 1, 0, ksize=3)  # 图像边缘检测,Sobel算子,对x轴方向求导sobel2 = cv2.flip(cv2.Sobel(flipped, cv2.CV_8U, 1, 0, ksize=3), 1)  # 先平滑图像边缘,再翻转img = sobel1 / 2 + sobel2 / 2img = img.astype('uint8')  # 强制类型转换

处理结果:
在这里插入图片描述
灰度图转为二进制图像:

    th = (np.mean(img) + (np.max(img) - np.mean(img)) * 0.6)ret, img = cv2.threshold(img, th, 255, cv2.THRESH_BINARY)  # 简单阈值函数,从灰度图像中获取二进制图像

处理结果:
在这里插入图片描述
形态学闭合操作:

img = close_op(img, 36)

处理结果:
在这里插入图片描述

三、车牌定位

    for contour in contours:area = cv2.contourArea(contour)  # 计算图像轮廓面积if area < 200 or area > 50000:  # 判断车牌轮廓区域continuerect = cv2.minAreaRect(contour)  # 求出点集contour的最小矩形面积,返回值rec[0]为矩形的中心点,rec[1]为矩形的长和宽,rec[2]矩形的旋转角度if rect[1][0] * rect[1][1] < 666 or area < rect[1][0] * rect[1][1] * 0.6:continuedy, dx = contour.flatten().reshape(contour.shape[0], -1).T.ptp(1)cwb = rect[1][1] / rect[1][0] if rect[1][1] > rect[1][0] else rect[1][0] / rect[1][1]if dy < dx or cwb < 2.5 or cwb > 6:continueif not check_plate(src, rect):continueplate = extract_plate(src, rect)  # src为原始图像,rect为车牌区域坐标

处理结果:
在这里插入图片描述

四、车牌字符分割

def plate_cut_text(img):'''车牌字符分割,将分割好的车牌区域进行字符分割'''sum = np.sum(img, 1)limit = np.mean(sum) * 0.2bound = []start = 0for i in range(len(sum) - 1):if sum[i] < limit and sum[i + 1] >= limit:start = ielif sum[i] >= limit and sum[i + 1] < limit:bound.append([start, i])start = 0if start != 0:bound.append([start, len(sum - 1)])up, down = 0, 0for b in bound:if b[1] - b[0] > down - up:up = b[0]down = b[1]return img[up: down + 1, :]

五、基于SVM的车牌字符识别

reader = SVM_ocr.Reader()
def plate_recognition(plate):  #字符识别代码'''车牌识别核心代码,使用SVM对分割的车牌字符进行识别,并将识别结果返回'''img = cv2.cvtColor(plate, cv2.COLOR_BGR2GRAY)th = (np.mean(img) + (np.max(img) - np.mean(img)) * 0.2)_, img = cv2.threshold(img, th, 255, cv2.THRESH_BINARY) #阈值函数img = plate_cut_text(img)display('plate th', img, 360)bound = plate_split(img) #调用plate_split函数,对车牌字符进行拆分,返回一个列表,列表每个值记录车牌每个字符起始位置print('拆分出来的各个字符起始位置:',bound)plate_res = []for i, b in enumerate(bound):display('character_'+str(i), img[:,b[0]:b[1]], 50)if b[1] - b[0] > 5 and b[1] - b[0] < 28: #判断每个分割出来的字符宽度是否正常if len(plate_res) == 0:ch = reader.recognize_chinese(adjust_vision(img[:, b[0]:b[1]+1]))[0] #识别车牌汉字else:ch = reader.recognize_alnum(adjust_vision(img[:, b[0]:b[1]+1]))[0] #识别车牌字符plate_res.append(ch) #将识别结果添加到变量ch中return plate_res #返回车牌识别结果

六、使用Qtdesigner进行UI界面设计

在这里插入图片描述

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

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

相关文章

RT-Thread Hoist_Motor PID

本节介绍的是一个举升电机&#xff0c;顾名思义&#xff0c;通过转轴控制物体升降&#xff0c;为双通道磁性译码器&#xff0c;利用电调进行操控&#xff0c;具体驱动类似于大学期间最大众的SG180舵机&#xff0c;在一定的频率下&#xff0c;通过调制脉宽进行控制。 设备介绍…

数据结构 图

树是无环连通图&#xff0c;是一种特殊的图。 分类 图分为有向图[边是有方向的]和无向图[边是无方向的]。 无向图(a—b)&#xff0c;建立两条有向图(a—>b&#xff0c;b—>a)&#xff0c;无向图是一种特殊的有向图。 存储有向图 邻接矩阵 ——用于存储比较稠密的图【…

MyBatis的xml实现

1.下载插件MyBatisX 2.添加依赖 <!--Mybatis 依赖包--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency><!--…

Rust错误处理机制:优雅地管理错误

大家好&#xff01;我是lincyang。 今天&#xff0c;我们要探讨的是Rust语言中的错误处理机制。 Rust作为一种系统编程语言&#xff0c;对错误处理的重视程度是非常高的。它提供了一套既安全又灵活的机制来处理可能出现的错误。 Rust错误处理的两大类别 在Rust中&#xff0…

vue下载xlsx表格

vue下载xlsx表格 // 导入依赖库 import XLSX from xlsx; import FileSaver from file-saver; methods:{btn(){let date new Date()let Y date.getFullYear() -let M (date.getMonth() 1 < 10 ? 0 (date.getMonth() 1) : date.getMonth() 1) -let D (date.getDat…

【设备树添加节点】

节点结束位置都需要加分号 of_iomap 完成映射 of_property_read_u32_array of_property_read_string of_fine_node_by_path

如何优雅的避免空指针异常

文章目录 1.数据准备2.实战&#xff1a;获取用户所在的城市2.1.直接获取&#xff1b;容易出现空指针异常。2.2.使用if-else判断&#xff1b;避免了出现空指针的问题&#xff0c;但是代码结构层次嵌套多&#xff0c;不美观2.3.使用工具类美化一下if判断代码2.4.使用Optional解决…

MySQL数据库:开源且强大的关系型数据库管理系统

大家好&#xff0c;我是咕噜-凯撒&#xff0c;数据在当今信息化时代的重要性不可忽视。作为企业和组织的重要资产&#xff0c;数据的管理和存储变得至关重要&#xff0c;MySQL作为一种关系型数据库管理系统&#xff0c;具有非常多的优势&#xff0c;下面简单的探讨一下MySQL数据…

基于卷尾猴算法优化概率神经网络PNN的分类预测 - 附代码

基于卷尾猴算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于卷尾猴算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于卷尾猴优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…

【Java程序员面试专栏 专业技能篇】Java SE核心面试指引(二):面向对象思想

关于Java SE部分的核心知识进行一网打尽,包括四部分:基础知识考察、面向对象思想、核心机制策略、Java新特性,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 本篇Blog为第二部分:面向对象思想,子节点表示追问或同级提问 面向对象基…

按照指定条件对数据进行分组并对每个分组内的全部数据应用自定义函数进行聚合计算groupby().apply()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 按照指定条件对数据进行分组 并对每个分组内的全部数据 应用自定义函数进行聚合计算 groupby().apply() [太阳]选择题 下列输出正确的是&#xff1a; import pandas as pd data {Name: [A, B,…

多线程的概念

点击链接返回标题-> 什么是进程&#xff1f; 进程&#xff08;Process&#xff09;&#xff0c;是程序的基本执行实体。 在早期面向进程设计的计算机结构中&#xff0c;进程是程序的基本执行实体&#xff1b; 在当代面向线程设计的计算机结构中&#xff0c;进程是线程的容器…

求二叉树中指定节点所在的层数(可运行)

运行环境.cpp 我这里设置的是查字符e的层数&#xff0c;大家可以在main函数里改成自己想查的字符。&#xff08;输入的字符一定是自己树里有的&#xff09;。 如果没有输出结果&#xff0c;一定是建树错误&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&…

Maven环境配置

Maven环境配置 下载Maven 网址&#xff1a;https://maven.apache.org/download.cgi 如果你的系统是Windows的直接按照箭头指示下载即可 环境变量配置 配置环境变量&#xff1a;将 Maven 的安装目录添加到您的系统环境变量中。 右键点击“我的电脑”&#xff08;或“此电脑…

Startdrive中上传参数设置的具体方法和注意事项

Startdrive中上传参数设置的具体方法和注意事项 适用于配 SINAMICS S120、G130、G150、S150和MV(基于CU3x0-2的驱动器)和所有启动驱动器版本INAMICS G115D/G120/G120D/G120C/G120P/G110M(基于CU2x0-2的驱动器) 根据SINAMICS类型的不同,Startdrive中的Upload参数有所不同。…

leetcode刷题详解——粉刷房子

1. 题目链接&#xff1a;LCR 091. 粉刷房子 2. 题目描述&#xff1a; 假如有一排房子&#xff0c;共 n 个&#xff0c;每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种&#xff0c;你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。 当然&#xff0c;因为…

Ubuntu20上离线安装samba

如果联网&#xff0c;一条 sudo apt-get install samba就可能解决问题&#xff0c;但是没有网&#xff0c;那么只能一个一个的解决问题&#xff1a; 我以为装了samba-common就可以了&#xff0c;发现smbd.serverice not found,于是开始了漫长的下载依赖包&#xff0c;安装&…

Linux中Team链路聚合配置

目录 一、Team介绍 二、网卡的bonding和Teaming技术 三、Teaming常用工作模式 四、实验环境 五、添加物理网卡 1、给虚拟机新增四张物理网卡 2、查看网卡信息 六、Team链路聚合配置 1、创建team0的网络接口 2、为team0设置静态IP,掩码位&#xff0c;网关&#xff0c;dns…

Java并发编程第12讲——cancelAcquire()流程详解及acquire方法总结

上篇文章介绍了AQS的设计思想以及独占式获取和释放同步状态的源码分析&#xff0c;但是还不够&#xff0c;一是感觉有点零零散散&#xff0c;二是里面还有很多细节没介绍到——比如cancelAcquire()方法&#xff08;重点&#xff09;&#xff0c;迫于篇幅原因&#xff0c;今天就…

Spring Cloud实战 |分布式系统的流量控制、熔断降级组件Sentinel如何使用

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…