深度学习实战项目(一)-基于cnn和opencv的车牌号识别

news/2024/10/22 13:18:07/

深度学习实战项目(一)-基于cnn和opencv的车牌号识别

网上大部分是关于tensorflow,使用pytorch的比较少,本文也在之前大佬写的代码的基础上,进行了数据集的完善,和代码的优化,效果可比之前的pytorch版本好一点。

数据集

数据集来自github开源的字符数据集:
在这里插入图片描述
在这里插入图片描述
数据集有:0-9,26个字母减去I和O,还有中文字,这里可以看看几张图片:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

opencv提取车牌字符

网上开源的方法都差不多,主要分为以下几个步骤:
1.图像预处理
(1)加载原始图片
(2)RGB图片转灰度图:减少数据量
(3)均值模糊:柔化一些小的噪声点
(4)sobel获取垂直边缘:因为车牌垂直边缘比较多
(5)原始图片从RGB转HSV:车牌背景色一般是蓝色或黄色
(6)从sobel处理后的图片找到蓝色或黄色区域:从HSV中取出蓝色、黄色区域,和sobel处理后的图片相乘
(7)二值化:最大类间方差法
(8)闭运算:将车牌垂直的边缘连成一个整体,注意核的尺寸

2.车牌定位
(1)获取轮廓
(2)求得轮廓外接矩形
(3)通过外接矩形的长、宽、长宽比三个值排除一部分非车牌的轮廓
(4)通过背景色进一步排除非车牌区域
这里主要用到漫水填充算法(类似PS的魔术棒),通过在矩形区域生成种子点,种子点的颜色必须是蓝色或黄色,在填充后的掩模上绘制外接矩形,再依次判断这个外接矩形的尺寸是否符合车牌要求,最后再把矩形做仿射变换校准位置。做漫水填充的目的有两个,第一个是预处理的时候车牌轮廓可能有残缺,做完漫水填充后可以把剩余的部分补全,第二个目的是进一步排除非车牌区域。

3.字符分割
水平投影方法:将二值化的车牌图片水平投影到Y轴,得到连续投影最长的一段作为字符区域,因为车牌四周有白色的边缘,这里可以把水平方向上的连续白线过滤掉。

CNN网络搭建与训练

网络设计:

class Net(torch.nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = torch.nn.Conv2d(3, 64, kernel_size=3, padding=1)self.conv2 = torch.nn.Conv2d(64, 64, kernel_size=3, padding=1)self.conv3 = torch.nn.Conv2d(64, 128, kernel_size=3, padding=1)self.conv4 = torch.nn.Conv2d(128, 128, kernel_size=3, padding=1)self.conv5 = torch.nn.Conv2d(128, 256, kernel_size=3, padding=1)self.conv6 = torch.nn.Conv2d(256, 256, kernel_size=3, padding=1)self.maxpooling = torch.nn.MaxPool2d(2)self.avgpool = torch.nn.AvgPool2d(2)self.globalavgpool = torch.nn.AvgPool2d((5, 5))self.bn1 = torch.nn.BatchNorm2d(64)self.bn2 = torch.nn.BatchNorm2d(128)self.bn3 = torch.nn.BatchNorm2d(256)self.dropout50 = torch.nn.Dropout(0.5)self.dropout10 = torch.nn.Dropout(0.1)self.fc1 = torch.nn.Linear(256, 67)def forward(self, x):batch_size = x.size(0)x = self.bn1(F.relu(self.conv1(x)))x = self.bn1(F.relu(self.conv2(x)))x = self.maxpooling(x)x = self.dropout10(x)x = self.bn2(F.relu(self.conv3(x)))x = self.bn2(F.relu(self.conv4(x)))x = self.maxpooling(x)x = self.dropout10(x)x = self.bn3(F.relu(self.conv5(x)))x = self.bn3(F.relu(self.conv6(x)))# print(x.size())x = self.globalavgpool(x)# print(x.size())x = self.dropout50(x)x = x.view(batch_size, -1)x = self.fc1(x)return x

数据预处理:

transform = transforms.Compose([transforms.Resize(size=(20, 20)),  # 原本就是 32x40 不需要修改尺寸transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),# transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),]
)

训练函数:

model = Net()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=LR)def train(epoch, loss_list):running_loss = 0.0for batch_idx, data in enumerate(new_train_loader, 0):inputs, target = data[0], data[1]inputs, target = inputs.to(device), target.to(device)optimizer.zero_grad()outputs = model(inputs)# print(outputs.shape, target.shape)# print(outputs, target)loss = criterion(outputs, target)loss.backward()optimizer.step()loss_list.append(loss.item())running_loss += loss.item()if batch_idx % 10 == 9:print(f'[{time_since(start)}] Epoch {epoch}', end='')print('[%d, %5d] loss:%.3f' % (epoch + 1, batch_idx + 1, running_loss / 10))running_loss = 0.0return loss_list

结果

1.测试集准确率:
在这里插入图片描述
2.识别结果:
在这里插入图片描述
3.训练损失图
在这里插入图片描述

界面

在这里插入图片描述


http://www.ppmy.cn/news/75321.html

相关文章

SpringMVC学习总结(路由映射、参数传递、转发和重定向...)

目录 1. MVC简介 2. SpringMVC简介 3. 路由映射注解 3.1 RequestMapping 3.2 GetMapping与PostMapping 4. 接收前端传递参数 4.1 接收单/多个参数 4.2 接收对象 4.3 接收JSON对象 4.4 后端参数重命名/映射 4.5 设置参数必传/非必传 4.6 获取URL中的参数 4.7 获取文…

PHP程序员的工作内容复杂吗?如何更快完成交代的任务?

我们城里人大部分都是高富帅 ,你看那些想进入程序员行业的人,哪个不是冲着高薪而来的。互联网已经深入到我们生活的方方面面,比如你去购物啊,聊天啊,你玩游戏啊,哪个不是我们程序员经历过多少日日夜夜加班给…

mybatis的一对一与一对多

我现在有两个表,是一对多的关系,CREATE TABLE repayment_plan ( ,针对一个还款计划可多次进行还款; 下面请帮我映射成两个bean对象 ID bigint(20) NOT NULL COMMENT 主键, CONSUMER_ID bigint(20) DEFAULT NULL COMMENT 发标人用户标识, USER_NO varchar(50) DEFAULT NULL …

【leetcode】1373. 二叉搜索子树的最大键值和

二叉搜索子树的最大键值和 问题描述问题简单分析提交之旅第一次提交-失败第二次提交-失败第三次提交-成功 问题描述 二叉搜索子树的最大键值和 给你一棵以 root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。 二叉搜索树的定义如下: 任意节…

接口测试的流程?怎么设计接口测试用例?两张图给你讲的明明白白

目录 一、简介 二、接口测试的流程 三、为什么要写用例 四、接口用例设计 一、简介 在开始接口测试之前,我们想一下,接口测试的流程是什么?说到这里,有些人就会产生好奇和疑问,心里mmp:接口测试要什么流…

Android Qcom USB Driver学习(十一)

该系列文章总目录链接与各部分简介: Android Qcom USB Driver学习(零) 基于TI的Firmware Update固件升级的流程分析usb appliction layers的数据 USB Protocol Package ①/② map to check password correct Package Format: Byte[0] Report Id Byte[1] Valid L…

阿里三面过了,却无理由挂了,HR反问一句话:为什么不考虑阿里?

进入互联网大厂一般都是“过五关斩六将”,难度堪比西天取经,但当你真正面对这些大厂的面试时,有时候又会被其中的神操作弄的很是蒙圈。 近日,某位测试员发帖称,自己去阿里面试,三面都过了,却被…

IEEE独立出版 | 第七届计算机科学与智能控制国际会议(ISCSIC 2023)

会议简介 Brief Introduction 第七届计算机科学与智能控制国际会议(ISCSIC 2023) 会议时间:2023年10月27日-29日 召开地点:中国南京 大会官网: ISCSIC 2023-2023 7th International Symposium on Computer Science and Intelligent Control(I…