【深度神经网络(DNN)】实现车牌识别

文章目录

  • 前言
  • 一、数据集介绍
  • 二、步骤
    • 1.导包
    • 2.参数配置
    • 3.数据处理
    • 4.模型定义
    • 5.模型训练
    • 6.模型预测
  • 总结


前言

课内实践作业 车牌识别


一、数据集介绍

1.车牌识别数据集:VehicleLicense车牌识别数据集包含16151张单字符数据,所有的单字符均为严格切割且都转换为黑白二值图像(如下第一行:训练数据所示)。
2.characterData:车牌识别数据集

二、步骤

1.导包

代码如下(示例):


#导入需要的包
import os
import zipfile
import random
import json
import cv2
import numpy as np
from PIL import Image
import paddle
import matplotlib.pyplot as plt
print(cv2.__version__)

在这里插入图片描述

2.参数配置

'''
参数配置
'''
train_parameters = {"input_size": [1, 20, 20],                           #输入图片的shape"class_dim": -1,                                     #分类数"src_path":"data/data47799/characterData.zip",       #原始数据集路径"target_path":"/home/aistudio/data/dataset",        #要解压的路径 "train_list_path": "/home/aistudio/train_data.txt",              #train_data.txt路径"eval_list_path": "/home/aistudio/val_data.txt",                  #eval_data.txt路径"label_dict":{},                                    #标签字典"readme_path": "/home/aistudio/data/readme.json",   #readme.json路径"train_batch_size": 32                           #训练的轮数
}

3.数据处理

def unzip_data(src_path,target_path):'''解压原始数据集,将src_path路径下的zip包解压至data/dataset目录下'''if(not os.path.isdir(target_path)):    z = zipfile.ZipFile(src_path, 'r')z.extractall(path=target_path)z.close()else:print("文件已解压")
``
```py
def get_data_list(target_path,train_list_path,eval_list_path):'''生成数据列表'''#存放所有类别的信息class_detail = []#获取所有类别保存的文件夹名称data_list_path=target_path class_dirs = os.listdir(data_list_path)if '__MACOSX' in class_dirs:class_dirs.remove('__MACOSX')# #总的图像数量all_class_images = 0# #存放类别标签class_label=0# #存放类别数目class_dim = 0# #存储要写进eval.txt和train.txt中的内容trainer_list=[]eval_list=[]#读取每个类别for class_dir in class_dirs:if class_dir != ".DS_Store":class_dim += 1#每个类别的信息class_detail_list = {}eval_sum = 0trainer_sum = 0#统计每个类别有多少张图片class_sum = 0#获取类别路径 path = os.path.join(data_list_path,class_dir)# print(path)# 获取所有图片img_paths = os.listdir(path)for img_path in img_paths:                                  # 遍历文件夹下的每个图片if img_path =='.DS_Store':continuename_path = os.path.join(path,img_path)                       # 每张图片的路径if class_sum % 10 == 0:                                 # 每10张图片取一个做验证数据eval_sum += 1                                       # eval_sum为测试数据的数目eval_list.append(name_path + "\t%d" % class_label + "\n")else:trainer_sum += 1 trainer_list.append(name_path + "\t%d" % class_label + "\n")#trainer_sum测试数据的数目class_sum += 1                                          #每类图片的数目all_class_images += 1                                   #所有类图片的数目# 说明的json文件的class_detail数据class_detail_list['class_name'] = class_dir             #类别名称class_detail_list['class_label'] = class_label          #类别标签class_detail_list['class_eval_images'] = eval_sum       #该类数据的测试集数目class_detail_list['class_trainer_images'] = trainer_sum #该类数据的训练集数目class_detail.append(class_detail_list)  #初始化标签列表train_parameters['label_dict'][str(class_label)] = class_dirclass_label += 1#初始化分类数train_parameters['class_dim'] = class_dimprint(train_parameters)#乱序  random.shuffle(eval_list)with open(eval_list_path, 'a') as f:for eval_image in eval_list:f.write(eval_image) #乱序        random.shuffle(trainer_list) with open(train_list_path, 'a') as f2:for train_image in trainer_list:f2.write(train_image) # 说明的json文件信息readjson = {}readjson['all_class_name'] = data_list_path                  #文件父目录readjson['all_class_images'] = all_class_imagesreadjson['class_detail'] = class_detailjsons = json.dumps(readjson, sort_keys=True, indent=4, separators=(',', ': '))with open(train_parameters['readme_path'],'w') as f:f.write(jsons)print ('生成数据列表完成!')
'''
参数初始化
'''
src_path=train_parameters['src_path']
target_path=train_parameters['target_path']
train_list_path=train_parameters['train_list_path']
eval_list_path=train_parameters['eval_list_path']
batch_size=train_parameters['train_batch_size']
'''
解压原始数据到指定路径
'''unzip_data(src_path,target_path)#每次生成数据列表前,首先清空train.txt和eval.txt
with open(train_list_path, 'w') as f: f.seek(0)f.truncate() 
with open(eval_list_path, 'w') as f: f.seek(0)f.truncate() #生成数据列表   
get_data_list(target_path,train_list_path,eval_list_path)

在这里插入图片描述

'''
自定义数据集
'''
import paddle
from paddle.io import Dataset
class MyDataset(Dataset):"""步骤一:继承paddle.io.Dataset类"""def __init__(self, mode='train'):"""步骤二:实现构造函数,定义数据集大小"""self.data = []self.label = []super(MyDataset, self).__init__()if mode == 'train':#批量读入数据print(train_list_path)with open(train_list_path, 'r') as f:lines = [line.strip() for line in f]for line in lines:#分割数据和标签img_path, lab = line.strip().split('\t')#读入图片img = cv2.imread(img_path)img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img = np.array(img).astype('float32')#图片归一化处理img = img/255.0#将数据同一添加到data和label中self.data.append(img)self.label.append(np.array(lab).astype('int64'))else:#测试集同上with open(eval_list_path, 'r') as f:lines = [line.strip() for line in f]for line in lines:img_path, lab = line.strip().split('\t')img = cv2.imread(img_path)img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img = np.array(img).astype('float32')img = img/255.0self.data.append(img)self.label.append(np.array(lab).astype('int64'))def __getitem__(self, index):"""步骤三:实现__getitem__方法,定义指定index时如何获取数据,并返回单条数据(训练数据,对应的标签)"""#返回单一数据和标签data = self.data[index]label = self.label[index]#注:返回标签数据时必须是int64# print(data)return data, np.array(label, dtype='int64')def __len__(self):"""步骤四:实现__len__方法,返回数据集总数目"""#返回数据总数return len(self.label)# 测试定义的数据集
train_dataset = MyDataset(mode='train')
eval_dataset = MyDataset(mode='val')
print('=============train_dataset =============')
#输出数据集的形状和标签
print(train_dataset.__getitem__(1)[0].shape,train_dataset.__getitem__(1)[1])
#输出数据集的长度
print(train_dataset.__len__())
print('=============eval_dataset =============')
#输出数据集的形状和标签
for data, label in eval_dataset:print(data.shape, label)break
#输出数据集的长度
print(eval_dataset.__len__())

在这里插入图片描述

4.模型定义

import paddle.fluid as fluid
from paddle.fluid.dygraph import Linearclass MyDNN(fluid.dygraph.Layer):def __init__(self):super(MyDNN,self).__init__()####请完善网络模型定义# self.hidden1 = paddle.nn.Linear(in_features=20*20,out_deatures=200)# self.hidden2 = paddle.nn.Linear(in_features=200,out_deatures=100)# self.hidden3 = paddle.nn.Linear(in_features=100,out_deatures=100)# self.out = paddle.nn.Linear(in_features=100,out_deatures=65)self.hidden1 = Linear(20*20,200,act='relu')self.hidden2 = Linear(200,100,act='relu')self.hidden3 = Linear(100,100,act = 'relu')self.hidden4 = Linear(100,65,act='softmax')# forward 定义执行实际运行时网络的执行逻辑def forward(self,input):       #-1 表示这个维度的值是从x的元素总数和剩余维度推断出来的,有且只能有一个维度设置为-1x = fluid.layers.reshape(input, shape=[-1,20*20]) x=self.hidden1(x)x=self.hidden2(x)x=self.hidden3(x)y=self.hidden4(x)return y

5.模型训练

#step3:训练模型
# 用Model封装模型
model = paddle.Model(MyDNN())
# 定义损失函数model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),paddle.nn.CrossEntropyLoss(),paddle.metric.Accuracy(topk=(1,5)))
# model.prepare(paddle.optimizer.SGD(parameters=model.parameters()),paddle.nn.CrossEntropyLoss(),paddle.metric.Accuracy(topk=(1,5)))# 训练可视化VisualDL工具的回调函数
visualdl = paddle.callbacks.VisualDL(log_dir='visualdl_log')
# 启动模型全流程训练
model.fit(train_dataset,            # 训练数据集eval_dataset,            # 评估数据集epochs=100,            # 总的训练轮次batch_size = batch_size,    # 批次计算的样本量大小shuffle=True,             # 是否打乱样本集verbose=1,                # 日志展示格式save_dir='./chk_points/', # 分阶段的训练模型存储路径callbacks=[visualdl])     # 回调函数使用
#保存模型
model.save('model_save_dir')

在这里插入图片描述

license_plate = cv2.imread('work/车牌.png')
print(license_plate.shape)
gray_plate = cv2.cvtColor(license_plate, cv2.COLOR_RGB2GRAY) 
ret, binary_plate = cv2.threshold(gray_plate, 175, 255, cv2.THRESH_BINARY) #ret:阈值,binary_plate:根据阈值处理后的图像数据
# 按列统计像素分布
result = []
for col in range(binary_plate.shape[1]):result.append(0)for row in range(binary_plate.shape[0]):result[col] = result[col] + binary_plate[row][col]/255
# print(result) 
#记录车牌中字符的位置
character_dict = {}
num = 0
i = 0
while i < len(result):if result[i] == 0:i += 1else:index = i + 1while result[index] != 0:index += 1character_dict[num] = [i, index-1]num += 1i = index
# print(character_dict)        
#将每个字符填充,并存储
characters = []
for i in range(8):if i==2:continuepadding = (170 - (character_dict[i][1] - character_dict[i][0])) / 2#将单个字符图像填充为170*170ndarray = np.pad(binary_plate[:,character_dict[i][0]:character_dict[i][1]], ((0,0), (int(padding), int(padding))), 'constant', constant_values=(0,0))ndarray = cv2.resize(ndarray, (20,20))cv2.imwrite('work/' + str(i) + '.png', ndarray)characters.append(ndarray)def load_image(path):img = paddle.dataset.image.load_image(file=path, is_color=False)img = img.astype('float32')img = img[np.newaxis, ] / 255.0return img

在这里插入图片描述

将标签进行转换
print('Label:',train_parameters['label_dict'])
match = {'A':'A','B':'B','C':'C','D':'D','E':'E','F':'F','G':'G','H':'H','I':'I','J':'J','K':'K','L':'L','M':'M','N':'N','O':'O','P':'P','Q':'Q','R':'R','S':'S','T':'T','U':'U','V':'V','W':'W','X':'X','Y':'Y','Z':'Z','yun':'云','cuan':'川','hei':'黑','zhe':'浙','ning':'宁','jin':'津','gan':'赣','hu':'沪','liao':'辽','jl':'吉','qing':'青','zang':'藏','e1':'鄂','meng':'蒙','gan1':'甘','qiong':'琼','shan':'陕','min':'闽','su':'苏','xin':'新','wan':'皖','jing':'京','xiang':'湘','gui':'贵','yu1':'渝','yu':'豫','ji':'冀','yue':'粤','gui1':'桂','sx':'晋','lu':'鲁','0':'0','1':'1','2':'2','3':'3','4':'4','5':'5','6':'6','7':'7','8':'8','9':'9'}
L = 0
LABEL ={}
for V in train_parameters['label_dict'].values():LABEL[str(L)] = match[V]L += 1
print(LABEL)

6.模型预测

with fluid.dygraph.guard():model=MyDNN()#模型实例化model_dict,_=fluid.load_dygraph('model_save_dir.pdparams')model.load_dict(model_dict)#加载模型参数model.eval()#评估模式lab=[]for i in range(8):if i==2:continueinfer_imgs = []infer_imgs.append(load_image('work/' + str(i) + '.png'))infer_imgs = np.array(infer_imgs)infer_imgs = fluid.dygraph.to_variable(infer_imgs)result=model(infer_imgs)lab.append(np.argmax(result.numpy()))
print(lab)
display(Image.open('work/车牌.png'))
for i in range(len(lab)):print(LABEL[str(lab[i])],end='')

在这里插入图片描述

总结

通过对实现车牌识别让我对深度神经网络(DNN)有了更深的认识

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

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

相关文章

PTL仓储亮灯拣选系统优化仓库作业流程实现物料快速定位

随着现代企业的发展和生产模式的不断演进&#xff0c;仓库管理作为生产供应链中的重要环节&#xff0c;也在不断追求效率和精益化。为了实现企业的现代化仓库管理&#xff0c;实现仓库条码化、自动化、无纸化&#xff0c;做到物料和成品从入库、出库、退库、移库、盘点整个过程…

【UE4】UE编辑器乱码问题

环境&#xff1a;UE4.27、vs2019 如何解决 问题原因&#xff0c;UE的编码默认是UTF-8&#xff0c;VS的默认编码是GBK 通过"高级保存选项" 直接修改VS的 .h头文件 的 编码 为 UTF-8 步骤1. 步骤2. 修改编码后&#xff0c;从新编译&#xff0c;然后就可以解决编辑器…

Docker 介绍

Docker 介绍 1 介绍1.1 概述1.2 资源高效利用1.3 发展历程1.4 组件1.5 工具1.6 对环境部署和虚拟化的影响1.7 优点1.8 容器技术核心CgroupNamespaceUnionFS 2 命令信息、状态、配置info命令用于显示当前系统信息、docker容器、镜像个数、设置等信息 镜像容器资源 3 安装3.1 版本…

2022年电工杯数学建模B题5G网络环境下应急物资配送问题求解全过程论文及程序

2022年电工杯数学建模 B题 5G网络环境下应急物资配送问题 原题再现&#xff1a; 一些重特大突发事件往往会造成道路阻断、损坏、封闭等意想不到的情况&#xff0c;对人们的日常生活会造成一定的影响。为了保证人们的正常生活&#xff0c;将应急物资及时准确地配送到位尤为重要…

jacoco和sonar

目录 jacoco 引入依赖 构建配置修改 单元测试 生成报告 查看报告 报告说明 1. Instructions 2. Branches 3. Cyclomatic Complexity 4. Lines 5. Methods 6. Classes sonar7.7 基础环境 需要下载软件 解压文件并配置 运行启动 jacoco 引入依赖 <dep…

【论文阅读】PSDF Fusion:用于动态 3D 数据融合和场景重建的概率符号距离函数

【论文阅读】PSDF Fusion&#xff1a;用于动态 3D 数据融合和场景重建的概率符号距离函数 Abstract1 Introduction3 Overview3.1 Hybrid Data Structure3.2 3D Representations3.3 Pipeline 4 PSDF Fusion and Surface Reconstruction4.1 PSDF Fusion4.2 Inlier Ratio Evaluati…

Spring boot集成sentinel限流服务

Sentinel集成文档 Sentinel控制台 Sentinel本身不支持持久化&#xff0c;项目通过下载源码改造后&#xff0c;将规则配置持久化进nacos中&#xff0c;sentinel重启后&#xff0c;配置不会丢失。 架构图&#xff1a; 改造步骤&#xff1a; 接着我们就要改造Sentinel的源码。…

Hikyuu 1.3.0 发布,高性能量化交易研究框架

Hikyuu 是一款基于 C/Python 的高性能开源量化交易研究框架&#xff0c;用于快速策略分析及回测。与其他量化平台或回测软件相比&#xff0c;具备&#xff1a; 超快的回测速度&#xff1b;对完整的系统交易理念进行抽象&#xff0c;并分解为不同的组件&#xff0c;通过重用不同…

Windows下MSYS2下载与安装

下载地址&#xff1a; 官网下载地址 https://www.msys2.org/阿里云镜像下载 https://mirrors.aliyun.com/msys2/distrib/x86_64/https://mirrors.aliyun.com/msys2/distrib/x86_64/msys2-x86_64-20231026.exe?spma2c6h.25603864.0.0.12b92551XW5OSM官网下载 ![官网下载](htt…

使用vscode开发uniapp项目常用的辅助插件,提升开发效率

为什么不使用hbuilder开发呢&#xff1f;因为hbuilder对ts和vue3语法支持并不友好&#xff0c;而且代码提示不智能&#xff0c;也不能使用最近很流行的coplit和CodeGeex智能提示&#xff0c;所以就换掉hbulider&#xff0c;使用我们熟悉的vscode开发吧。 第一个&#xff1a;un…

高德地图设置电子围栏

高德地图设置电子围栏 需求效果图代码实现 需求 给地图上人员锚点设置围栏区域&#xff0c;如果在此区域内则是在线状态&#xff0c;不在此区域内则是离线状态 效果图 双击可编辑或清除当前围栏 代码实现 前端实现区域框选&#xff1a; //引入高德地图sdk"amap/amap…

将全连接层替换为卷积层的意义(CNN和FCN)

全连接层&#xff1a;CNN 将特征整合&#xff0c;用于分类&#xff0c;在图像中具体化为知道图像中有猫&#xff0c;但是不知道猫在哪儿。 在传统CNN中&#xff0c;输入是唯一确定大小的。因为全连接层要求输入是固定的。 全卷积网络&#xff1a;FCN 不仅可以用来分类&…

项目文件下载器,基于Thread多线程

目录 1、Http 工具类 2、关于下载的关系类 2.1 展示下载信息 #下载信息展现线程类 #在主下载类中&#xff0c;进行调用上述线程类 2.2 文件的分块下载 #文件分块下载类 #文件按分块进行分别切分的方法 # 使用 LongAdder 类型&#xff0c;更改 DownLoadInfoThread 展现…

计算机中丢失mfc140u.dll怎么解决

mfc140u.dll是一个Microsoft Visual C库文件&#xff0c;主要用于MFC&#xff08;Microsoft Foundation Class&#xff09;应用程序的开发。它包含了MFC应用程序所需的一些常用功能&#xff0c;如对话框、窗口、菜单等。当mfc140u.dll丢失时&#xff0c;可能会导致MFC应用程序无…

margin-bottom、margin-top设置不起效

问题&#xff1a; 如下&#xff0c;在uniapp项目中使用了tag标签&#xff0c;设置margin时&#xff0c;只有margin-left、margin-right生效&#xff0c;margin-bottom、margin-top设置不起效。f12直接在元素中修改也无效。 原因&#xff1a; uni-ui中的tag标签是行内元素&…

idea 模板参数注释 {@link}

1. 新增组 2. 设置方法注释及变量 增加模板文本 ** * $param$ * return {link $return$} */3. 设置变量表达式 勾选跳过param 参数表达式 groovyScript("def result ;def params \"${_1}\".replaceAll([\\\\[|\\\\]|\\\\s], ).split(,).toList();def param…

Vscode禁止插件自动更新

由于电脑的vscode版本不是很新。2022.10月份的版本1.7.2&#xff0c;电脑vscode的python插件装的也是2022年4月份的某个版本&#xff0c;但插件经常自动更新&#xff0c;导致python代码无法Debug,解决办法&#xff1a; 点设置&#xff0c;搜autoUpdate, 把红色框选成无

Linux中固定ip端口和修改ip地址

一&#xff0c;更改虚拟网络编辑器 1&#xff0c;首先启动VMware&#xff0c;选择自己要更改ip或固定ip的虚拟机&#xff0c;并找到虚拟网络配编辑器&#xff0c;点击进入 2&#xff0c;进入之后需要点击右下角获取管理员权限后才能修改&#xff0c;有管理员权限之后图片如下 …

setpci设定PCIe寄存器

PCIe寄存器信息读取、分析、配置 1.获取bdf &#xff08;bus:device.function&#xff09;地址2.根据bdf地址抓取pci信息3.结合PCIe Spec对读到的信息进行分析使用setpci修改 1.获取bdf &#xff08;bus:device.function&#xff09;地址 在Linux系统下使用命令&#xff1a; l…

django+drf+vue 简单系统搭建 (2) - drf 应用

按照本系统设置目的&#xff0c;是为了建立一些工具用来处理简单的文件。 1. 准备djangorestframework 关于drf的说明请参见&#xff1a;Django REST Framework教程 | 大江狗的博客 本系列直接使用drf的序列化等其他功能。 安装 conda install djangorestframework conda i…