基于深度学习的车牌识别(YOLOv5和CNN)

基于深度学习的车牌识别(YOLOv5和CNN)

目录

一、综述

二、车牌检测

一、综述

本篇文章是面向的是小白,想要学习深度学习上的应用,本文中目前应用了YOLO v5和CNN来对车牌进行处理,最终形成一个完整的车牌信息记录,如果我写的有什么不对或者需要改进的地方,可以私信给我。

我们假设已经获得包含有车牌的照片,那么我们

第一步:是车牌的检测获取车牌的那部分。

第二步:就是对车牌进行拆分成各个字符。

第三步:对于一张车牌的每个字符我们使用CNN得到的模型去预测每个字符

最终得到车牌信息。

二、车牌检测

概括

车牌检测的方法有许多,最初我用的是原始的图像形态学对图像的处理(基于opencv的形态学操作),发现这样的方法不能很好的应用到所有的车牌中。那么我在学习的过程中,其实已经有许多其他方法来实现。比如目标检测,它就是一个很好的方法,主要是可以把这样的方法应用到更多更广泛的应用场景。

目标领域中主要分为如下两个——One-stage和two-stage算法

他们的区别可以查看 目标检测算法基础介绍

首先YOLO系列下的模型都是属于One-stage,在One-stage包括SSD也是很常用的一种方法。

YOLOv5学习视频查看 火爆全网的YOLOv5目标检测项目 从P41开始学习就可以了。

我们这部分有几个前提必须准备好。

1.训练需要的车牌图片数据

车牌数据 我的来自于 中科大建立的CCPD数据集,其他的不要说,总之在学习阶段说一个不错的数据,论文和数据集下载地址:github.com/detectRecog… 以下说数据说明

截屏2022-06-10 22.23.27.png

2.安装YOLOv5模型 YOLO的安装可以直接 去GitHub上下载:github.com/ultralytics… 如果是第一次使用其他人模型,第一次都会有不知所措,但一旦掌握了其中一个,其他是类似的。比如图像分割中的U-net,ocr模型中PaddlePaddleOCR都是差不多的用法。

(1) YOLO文件中需要修改某些文件

在我的目录中,我将YOLO下载到与car文件夹的同目录下

我们需要关注YOLO文件夹下的几个文件,这是我的文件目录

截屏2022-06-10 21.02.39.png

我们要自己首先一个yaml文件来配置YOLO模型,图中化横线的文件 car.yaml

以下是我的简单的配置

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 path:图片数据的根目录

train:训练集的绝对路径,这里存放是所有图片的绝对路径

val: 验证集的绝对路径,与train一样

nc:分类个数

names:列表类型 所有类别名字 license plate 车牌

(2)预使用模型 YOLO已经给出以下模型 我们可以在他们这些模型的基础上进行训练自己的模型

截屏2022-06-10 21.10.29.png

我使用的是占内存比较小,准确率不错的yolov5s.yaml 详细其他模型有什么区别可以去官网去查看:github.com/ultralytics…

yolo5s.yaml 文件我们需要简单的进行修改,从而满足我们自己项目的需求

截屏2022-06-10 21.15.32.png

在我的项目中只有一个车牌需要关注,所以我们需要将nc的个数改为1,其他参数我们不需要修改。

好,YOLO文件夹下内容,暂时不需要修改了。

图片数据分析

数据的目录是如图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们简单的使用 ccpd_base 文件夹,图片很多,考虑电脑实际情况,我只选取其中任意的5000张照片来作为数据源。

ccpd_base文件内容如下

截屏2022-06-10 14.59.57.png

先建立文件夹结构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

markdown
复制代码
car
	images
		放入数据集照片5000张
	labels
		等会儿说到

详细查看第一个图片名字

数据中有详细的解释文件名字的意思 截屏2022-06-10 15.03.57.png

第一张图片名字是:01-86_91-298&341_449&414-458&394_308&410_304&357_454&341-0_0_14_28_24_26_29-124-24.jpg

less
复制代码

1) 01为区域,

2) 86_91 对应两个角度, 水平86°, 竖直91°

3) 298&341_449&414对应边界框坐标:左上(298, 341), 右下(449, 414)

4) 458&394_308&410_304&357_454&341对应四个角点坐标

5) 0_0_14_28_24_26_29-124-24为车牌号码 映射关系如下: 第一个为省份0 对应省份字典皖, 后面的为字母和文字, 查看ads字典.如0为A, 22为Y....

现在对于我们这个阶段我们用到四个点的坐标。

代码如下 Car_Model:

ini
复制代码
import os
import numpy as np
# 访问图片获得图片名字的字符
def load_files(path, cuted=False): # cuted=False 可以不需要写
    total_info = []
    car_numbers = []   # 车牌号码
    angels = []         # 倾斜角度
    areas = []          # 区域
    positions = []      # 车牌四个角的位置
    areas_positions = []  # 车牌左上和右下区域位置
    for i, j, names in os.walk(path):
        # 假设现在已经获得了路径
        # 首先要删除前面没有用的路径,现在获得的是一个str
        for name in names:
            if len(name) < 50:
                continue
            if cuted is True:
                    path = name.split("-", 5)
                    areas.append(path[0])
                    angels.append(path[1])
                    areas_positions.append(path[2])
                    positions.append(path[3])
                    car_numbers.append(path[4])
            else:
                total_info.append(name)

    if cuted is True:    # 其他情况下可能需要得到每段信息,可以不需要
        total_info.append(areas)
        total_info.append(angels)
        total_info.append(areas_positions)
        total_info.append(positions)
        total_info.append(car_numbers)
        total_info.append(names)
    return total_info

因为YOLO对于图片有要求,我们要对图片相关对文件进行一定的改变。

通常我们需要对图片进行标注,通常使用labelme工具来进行图片标注 以下是常用图片标注工具的对比,对于目标检测我们使用labelme就可以了。

blog.csdn.net/sinat_29957…

这个标注是把图片中的车牌框选出来,从而成为一个json文件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

框中的数据就是一个车牌左上点(x1,y1)和右下点数据(x2,y2),我们需要取出这些数据出来。

但对于我们的中科大CCPD数据而言,这些数据已经写在文件名字中了,我们只需对名字进行处理,满足YOLO的一个要求。

文件名Car_data.py

ini
复制代码
import os
import Car_Model
import numpy as np
from PIL import Image
DATA_PATH = "/Users/pengpeng/Resources/Python/ccpd_base/car"

# 处理文件名中的4个点坐标,并且满足YOLO要求
def process_position(data, data_name):
    for name, title in zip(data[3], data_name):
        yolo_data = []
        bounding_boxes = name.split("_", 4)
        real_positions = []
        image_name = []
        title1 = title.split('.', 2)
        image_name.append(title1[0])
        # 获得4个点数据
        for bbox in bounding_boxes:
            values = bbox.split("&", 1)
            for index in range(len(values)):
                values[index] = int(int(values[index]))
            real_positions.append(values)
        real_positions = np.int0(np.array(real_positions))
        # 得到整个最大的值
        Xs = [i[0] for i in real_positions]
        Ys = [i[1] for i in real_positions]
        x1 = abs(min(Xs))
        x2 = abs(max(Xs))
        y1 = abs(min(Ys))
        y2 = abs(max(Ys))
        '''
            YOLO要求这个框满足以下要求
            (1)需要这个框的中心坐标位置,宽度(width)和高度(height)
            (2)每个值必须在0-1之间的小数,所以需要进行归一化
            (3)还需要对每个框进行标注属于哪一个分类, 按照 分类 x, y,w,h 这五个值进行写入
            (4)需要对一张照片所有的框进行新建一个txt文件,存取以上内容
        '''
        # 获得图片信息,获得图片大小分别是width和height
        img_path = DATA_PATH+"/images/"+title
        img  = Image.open(img_path)
        imgSize = img.size
        img_width = imgSize[0]
        img_height = imgSize[1]

        # 进行归一化,直接把这些内容copy就可以了
        dw = 1. / img_width # 1/w
        dh = 1. / img_height  # 1/h
        x = (x1 + x2) / 2.0 - 1  # 物体在图中的中心点x坐标
        y = (y1 + y2) / 2.0 - 1  # 物体在图中的中心点y坐标
        w = x2 - x1  # 物体实际像素宽度
        h = y2 - y1  # 物体实际像素高度
        x = x * dw  # 物体中心点x的坐标比(相当于 x/原图w)
        w = w * dw  # 物体宽度的宽度比(相当于 w/原图w)
        y = y * dh  # 物体中心点y的坐标比(相当于 y/原图h)
        h = h * dh  # 物体宽度的宽度比(相当于 h/原图h)

        # 把这五个值写入到文件中
        yolo_data.append([0, x, y, w, h])
        yolo_data = np.array(yolo_data)
        # 保存bbox的图片信息
        np.savetxt(
            os.path.join(DATA_PATH, f'labels/{title1[0]}.txt'),
            yolo_data,
            fmt=['%d', '%f', '%f', '%f', '%f']
        )

if __name__ == '__main__':
    total_infos = Car_Model.load_files(DATA_PATH, True)
    title = Car_Model.load_files(DATA_PATH, False)
    process_position(total_infos, title)

另一文件processing_character.py

目的是将图片的绝对路径写入train.txt 和test.txt中

ini
复制代码
import os
import random

# train所占的比例 70%
train_percet = 0.7

# 文件绝对路径 Mac电脑与windows电脑的地址不同,它类似与Linux的地址
path = "/Users/pengpeng/Resources/Python/ccpd_base/car"

# car文件夹下的images文件夹
images = "images"

# 新建的train.txt和test.txt
names = ["train", "test"]

# 访问images文件夹并把绝对地址写入train和test文件中
images_path = os.path.join(path, images)
images_path = os.listdir(images_path)
total_labels = []
for label in images_path:
    # 因为Mac电脑比较特殊,在每个文件中都有一个名字叫.DS_Store的隐藏文件,必须排除掉这个文件
    if label ==".DS_Store":
        continue
    total_labels.append(label)
    
# 按照之前的概率,对数据进行随机
num = len(total_labels)
digit = range(num)
trd = int(num * train_percet)
ted = int(num * (1-train_percet))
trdr = random.sample(digit, trd)  # train_digit_random 
tedr = random.sample(trdr, ted)   # test_digit_random

# 分别写入以下两个文件中
ftrain = open(path+'/train.txt', 'w')
ftest = open(path+'/test.txt', 'w')

# 根据随机进行分成train和test比例 这个是按照机器学习对train和test进行安排,当然可以按照自己对要求进行调整
for i in digit:
    name_path = path + "/" + images + "/" + total_labels[i] + "\n"
    print(name_path)
    if i in trdr:
        ftrain.write(name_path)
    else:
        ftest.write(name_path)
# 写完文件,要关闭文件
ftrain.close()
ftest.close()

按照顺序执行完以上三个,我们可以得到以下文件包含它的相应内容

截屏2022-06-10 21.50.24.png 截屏2022-06-10 21.50.03.png

截屏2022-06-10 21.50.12.png

完成到这里,我们车牌的检测就已经完成了大半了。

接着是打开我们的terminal或cmd 找到yolo的根目录,我这使用的是anconda的虚拟环境

截屏2022-06-10 21.55.27.png

在命令行上输入以下命令

css
复制代码
python train.py --data car.yaml --cfg models/yolov5s.yaml --weights weights/yolov5s.pt --batch-size 10 --epochs 3
# --data 后面是刚刚写的配置文件 以yolo为根本目录找的文件
# --cfg 使用配置,然后对这个文件进行修改
# --weights 使用模型的权制
# --batch-size 批量大小
# --epochs 简单理解为运行次数

因为使用的是mac m1pro 不能使用pytorch的gpu ,按照现在的2022 6月份 是不能使用的,只能使用cpu。计算时间很长,计算3次的时间是2个小时吧(不记得了)

最终进行简单的炼丹,也能达到一个还行的结果 val_batch0_pred.jpg

这些结果会最终得到一个文件夹存在以下中

截屏2022-06-10 22.15.35.png

这样我们简单的得到一个自己的车牌检测模型。

接着我们要做的就是预测我们检测车牌的结果。

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

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

相关文章

强网杯2023 crypto

speed up 当时看到这个题目 也是觉得易懂 并且可以解出来的 但是数字实在是过大了兄弟 题目意思是计算2^27的阶乘,并获取得到每一位数的数字之和,flag即为该数字的sha256编码 2^27为134217728 gmpy2包是支持大数运算的,故利用其fac方法进行尝试,在等待一段时间后可以得到对…

第二次作业

1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 创建文件 编辑文件 创建目录 添加内容 重启系统 更改host文件 在host追加域名 最后在网页查看及可 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网…

flutter获取地理定位:geolocator依赖详细用法

本文使用geolocator插件实现app物理定位功能。 该插件的主要功能有&#xff1a; 获取最后已知位置&#xff1b;获取设备当前位置&#xff1b;获取连续的位置更新&#xff1b;检查设备是否启用了定位服务&#xff1b;计算两个地理坐标之间的距离&#xff08;米&#xff09;&am…

数据结构——排序

前言&#xff1a;哈喽小伙伴们好久不见&#xff0c;也是顺利的考完试迎来了寒假。众所周知&#xff0c;不怕同学是学霸&#xff0c;就怕学霸放寒假&#xff0c;假期身为弯道超车的最佳时间&#xff0c;我们定然是不能懒散的度过。 今天我们就一起来学习数据结构初阶的终章——…

眼镜用超声波清洗机好不好?洗眼镜比较好用的超声波清洗机推荐

眼镜是我们日常生活中必不可少的用品&#xff0c;它不仅能帮助我们矫正视力&#xff0c;更是我们与外界进行交流的重要工具。然而&#xff0c;随着眼镜的长时间佩戴&#xff0c;眼镜表面容易积累灰尘、污垢和细菌&#xff0c;这不仅影响了我们的视野&#xff0c;也可能对眼睛健…

Docker(一)简介和基本概念:什么是 Docker?用它会带来什么样的好处?

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; 一、简介 本章将带领你进入 Docker 的世界。 什么是 Docker&#xff1f; 用它会带来什么样的好处&#xff1f; 好吧&#xff0c;让我们带…

Python连接数据库的梳理

我们通常用的数据库类型主要有关系型数据库&#xff0c;非关系型数据库等&#xff0c;其中关系型数据库主要有Microsoft SQL Server ,MySQL,Oracle&#xff0c;SQLite等&#xff0c;常用的非关系型数据库包括Redis、DynamoDB&#xff0c;MongoDB等 ​​​​​​​ 一 关系型…

hdu 3709 Balanced Number

Balanced Number 题意 定义一个非负整数在第 p p p 位为 p i v o t pivot pivot 的权重为&#xff1a;这个数位的值 \times 这个数位到 p i v o t pivot pivot 的距离 之和。如果在 p i v o t pivot pivot 左边的权重等于在 p i v o t pivot pivot 右边的权重&#xf…

uni-app小程序:文件下载打开文件方法苹果安卓都适用

api: const filetype e.substr(e.lastIndexOf(.)1)//获取文件地址的类型 console.log(文档,filetype) uni.downloadFile({url: e,//e是图片地址success(res) {console.log(res)if (res.statusCode 200) {console.log(下载成功,);var filePath encodeURI(res.tempFilePath);…

python开发之远程开发工具对比

前言 除了本地开发外&#xff0c;还有一种常见的开发方式就是远程开发&#xff0c;一般情况是一台Windows或mac笔记本作为日常使用的电脑&#xff0c;另有一台linux服务器作为开发服务器。开发服务器的性能往往较强&#xff0c;这样远程开发的方式一方面可以让我们在习惯的系统…

Python网络爬虫步骤是什么?新手小白必看 !

python网络爬虫步骤&#xff1a;首先准备所需库&#xff0c;编写爬虫调度程序&#xff1b;然后编写url管理器&#xff0c;并编写网页下载器&#xff1b;接着编写网页解析器&#xff1b;最后编写网页输出器即可。 本教程操作环境&#xff1a;windows7系统、python3.9版&#xff…

Spring | Spring中的Bean--下

Spring中的Bean: 4.Bean的生命周期5.Bean的配装配式 ( 添加Bean到IOC容器的方式 依赖注入的方式 )5.1 基于XML的配置5.2 基于Annotation (注解) 的装配 (更常用&#xff09;5.3 自动装配 4.Bean的生命周期 Spring容器可以管理 singleton作用域的Bean的生命周期&#xff0c;在此…

【Github搭建网站】零基础零成本搭建个人Web网站~

Github网站&#xff1a;https://github.com/ 这是我个人搭建的网站&#xff1a;https://xf2001.github.io/xf/ 大家可以搭建完后发评论区看看&#xff01;&#xff01;&#xff01; 搭建教程&#xff1a;https://www.bilibili.com/video/BV1xc41147Vb/?spm_id_from333.999.0.0…

sql570 | 至少有5名下属的经理 | join on | group by | having

讲给一张表&#xff0c;表字段分别为 id 、姓名、部分、经理id&#xff0c;可能存在张三既是下属也是经理 现在找出下属起码有5名员工的经理 CREATE TABLE Employee (id INT,name VARCHAR(255),department VARCHAR(255),managerId INT );INSERT INTO Employee (id, name, depar…

HarmonyOS 页面跳转控制整个界面的转场动画

好 本文 我们来说 页面间的转场动画 就是 第一个界面到另一个界面 第一个界面的退场和第二个界面的进场效果 首先 我这里 创建了两个页面文件 Index.ets和AppView.ets index组件 编写代码如下 import router from "ohos.router" Entry Component struct Index {b…

架构的演进

1.1单体架构 单体架构也称之为单体系统或者是单体应用。就是一种把系统中所有的功能、模块耦合在一个应用中的架构方式。 存在的问题&#xff1a; 代码耦合&#xff1a;模块的边界模糊、依赖关系不清晰&#xff0c;整个项目非常复杂&#xff0c;每次修改代码都心惊胆战迭代困…

LeetCode.2788. 按分隔符拆分字符串

题目 题目链接 分析 题目的意思是给我们一个字符串数组和一个分隔符&#xff0c;让我们按照分隔符把字符串数组分割成新的字符串数组。 看到这个描述&#xff0c;这不就是直接就是利用 按照分隔符分割字符串的系统库函数split()&#xff0c;这个函数的意思就是 把一个字符串…

SpringBoot解决Slow HTTP慢速攻击漏洞

项目场景&#xff1a; 扫描到的漏洞截图&#xff1a; 攻击原理&#xff1a; Web应用在处理HTTP请求之前都要先接收完所有的HTTP头部&#xff0c;因为HTTP头部中包含了一些Web应用可能用到的重要的信息。攻击者利用这点&#xff0c;发起一个HTTP请求&#xff0c;一直不停的发送…

H3C交换机S6850配置M-LAG三层转发

正文共&#xff1a;1999 字 30 图&#xff0c;预估阅读时间&#xff1a;3 分钟 前面提到M-LAG是一种跨设备链路聚合技术&#xff0c;将两台物理设备在聚合层面虚拟成一台设备来实现跨设备链路聚合&#xff0c;从而提供设备级冗余保护和流量负载分担。 之前已经做了DRNI的三层转…

MySQL之外键约束和表关系

前言 一个项目中如果将所有的数据都存放在一张表中是不合理的&#xff0c;比如一个员工信息&#xff0c;公司只有2个部门&#xff0c;但是员工有1亿人&#xff0c;就意味着员工信息这张表中的部门字段的值需要重复存储&#xff0c;极大的浪费资源&#xff0c;因此可以定义一个…