P10周:Pytorch实现车牌识别
本文为365天深度学习训练营中的学习记录博客原作者K同学啊学习目的自定义一个MyDataset加载车牌数据集并完成车牌识别一、 前期准备关于环境语言环境Python3.13编译器vsCode深度学习环境torch2.11.0cu130torchvision0.26.0cu130torchvision0.26.0cu1301.设置GPU设置分析环境from torchvision.transforms import transforms from torch.utils.data import DataLoader from torchvision import datasets import torchvision.models as models import torch.nn.functional as F import torch.nn as nn import torch,torchvision device torch.device(cuda if torch.cuda.is_available() else cpu) device运行结果2. 获取类别名import os,PIL,random,pathlib import matplotlib.pyplot as plt # 支持中文 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负号 data_dir ./015_licence_plate/ data_dir pathlib.Path(data_dir) data_paths list(data_dir.glob(*)) classeNames [str(path).split(\\)[1].split(_)[1].split(.)[0] for path in data_paths] print(classeNames)运行结果data_paths list(data_dir.glob(*)) data_paths_str [str(path) for path in data_paths] data_paths_str运行结果3. 数据可视化plt.figure(figsize(14,5)) plt.suptitle(数据示例K同学啊,fontsize15) for i in range(18): plt.subplot(3,6,i1) # plt.xticks([]) # plt.yticks([]) # plt.grid(False) # 显示图片 images plt.imread(data_paths_str[i]) plt.imshow(images) plt.show()运行结果4. 标签数字化import numpy as np char_enum [京,沪,津,渝,冀,晋,蒙,辽,吉,黑,苏,浙,皖,闽,赣,鲁,\ 豫,鄂,湘,粤,桂,琼,川,贵,云,藏,陕,甘,青,宁,新,军,使] number [str(i) for i in range(0, 10)] # 0 到 9 的数字 alphabet [chr(i) for i in range(65, 91)] # A 到 Z 的字母 char_set char_enum number alphabet char_set_len len(char_set) label_name_len len(classeNames[0]) # 将字符串数字化 def text2vec(text): vector np.zeros([label_name_len, char_set_len]) for i, c in enumerate(text): idx char_set.index(c) vector[i][idx] 1.0 return vector all_labels [text2vec(i) for i in classeNames]这段代码的核心目的是为了给每个图片进行编码把所有车牌的字符串都转成这种 7x69 的数字矩阵作为训练时的“标准答案”。5. 加载数据文件import os import pandas as pd from torchvision.io import read_image from torch.utils.data import Dataset import torch.utils.data as data from PIL import Image class MyDataset(data.Dataset): def __init__(self, all_labels, data_paths_str, transform): self.img_labels all_labels # 获取标签信息 self.img_dir data_paths_str # 图像目录路径 self.transform transform # 目标转换函数 def __len__(self): return len(self.img_labels) def __getitem__(self, index): image Image.open(self.img_dir[index]).convert(RGB)#plt.imread(self.img_dir[index]) # 使用 torchvision.io.read_image 读取图像 label self.img_labels[index] # 获取图像对应的标签 if self.transform: image self.transform(image) return image, label # 返回图像和标签total_datadir ./03_traffic_sign/ # 关于transforms.Compose的更多介绍可以参考https://blog.csdn.net/qq_38251616/article/details/124878863 train_transforms transforms.Compose([ transforms.Resize([224, 224]), # 将输入图片resize成统一尺寸 transforms.ToTensor(), # 将PIL Image或numpy.ndarray转换为tensor并归一化到[0,1]之间 transforms.Normalize( # 标准化处理--转换为标准正太分布高斯分布使模型更容易收敛 mean[0.485, 0.456, 0.406], std [0.229, 0.224, 0.225]) # 其中 mean[0.485,0.456,0.406]与std[0.229,0.224,0.225] 从数据集中随机抽样计算得到的。 ]) total_data MyDataset(all_labels, data_paths_str, train_transforms) total_data6.划分数据集train_size int(0.8 * len(total_data)) test_size len(total_data) - train_size train_dataset, test_dataset torch.utils.data.random_split(total_data, [train_size, test_size]) train_size,test_size运行结果train_loader torch.utils.data.DataLoader(train_dataset, batch_size16, shuffleTrue) test_loader torch.utils.data.DataLoader(test_dataset, batch_size16, shuffleTrue) print(The number of images in a training set is: , len(train_loader)*16) print(The number of images in a test set is: , len(test_loader)*16) print(The number of batches per epoch is: , len(train_loader))运行结果for X, y in test_loader: print(Shape of X [N, C, H, W]: , X.shape) print(Shape of y: , y.shape, y.dtype) break运行结果查看一个批次的数据形状X是图像张量形状为[16, 3, 224, 224]16张3 通道高宽 224y是标签形状为[16769]类型为torch.int64二、自建模型class Network_bn(nn.Module): def __init__(self): super(Network_bn, self).__init__() nn.Conv2d()函数 第一个参数in_channels是输入的channel数量 第二个参数out_channels是输出的channel数量 第三个参数kernel_size是卷积核大小 第四个参数stride是步长默认为1 第五个参数padding是填充大小默认为0 self.conv1 nn.Conv2d(in_channels3, out_channels12, kernel_size5, stride1, padding0) self.bn1 nn.BatchNorm2d(12) self.conv2 nn.Conv2d(in_channels12, out_channels12, kernel_size5, stride1, padding0) self.bn2 nn.BatchNorm2d(12) self.pool nn.MaxPool2d(2,2) self.conv4 nn.Conv2d(in_channels12, out_channels24, kernel_size5, stride1, padding0) self.bn4 nn.BatchNorm2d(24) self.conv5 nn.Conv2d(in_channels24, out_channels24, kernel_size5, stride1, padding0) self.bn5 nn.BatchNorm2d(24) self.fc1 nn.Linear(24*50*50, label_name_len*char_set_len) self.reshape Reshape([label_name_len,char_set_len]) def forward(self, x): x F.relu(self.bn1(self.conv1(x))) x F.relu(self.bn2(self.conv2(x))) x self.pool(x) x F.relu(self.bn4(self.conv4(x))) x F.relu(self.bn5(self.conv5(x))) x self.pool(x) x x.view(-1, 24*50*50) x self.fc1(x) # 最终reshape x self.reshape(x) return x # 定义Reshape层 class Reshape(nn.Module): def __init__(self, shape): super(Reshape, self).__init__() self.shape shape def forward(self, x): return x.view(x.size(0), *self.shape) device cuda if torch.cuda.is_available() else cpu print(Using {} device.format(device)) model Network_bn().to(device) modelview是 PyTorch 改变张量形状的方法。x.size(0)是批次大小16*self.shape是[7, 69]。最终输出形状为[16, 7, 69]即每个字符对应一个 69 维的独热向量。运行结果import torchsummary 显示网络结构 torchsummary.summary(model, (3, 224, 224))运行结果三、模型训练1. 优化器与损失函数optimizer torch.optim.Adam(model.parameters(), lr1e-4, weight_decay0.0001) loss_model nn.CrossEntropyLoss()2.编写训练和测试函数from torch.autograd import Variable def test(model, test_loader, loss_model): size len(test_loader.dataset) num_batches len(test_loader) model.eval() test_loss, correct 0, 0 with torch.no_grad(): for X, y in test_loader: X, y X.to(device), y.to(device) pred model(X) test_loss loss_model(pred, y).item() test_loss / num_batches print(fAvg loss: {test_loss:8f} \n) return correct,test_loss def train(model,train_loader,loss_model,optimizer): modelmodel.to(device) model.train() for i, (images, labels) in enumerate(train_loader, 0): #0是标起始位置的值。 images Variable(images.to(device)) labels Variable(labels.to(device)) optimizer.zero_grad() outputs model(images) loss loss_model(outputs, labels) loss.backward() optimizer.step() if i % 1000 0: print([%5d] loss: %.3f % (i, loss))3. 模型的训练test_acc_list [] test_loss_list [] epochs 30 for t in range(epochs): print(fEpoch {t1}\n-------------------------------) train(model,train_loader,loss_model,optimizer) test_acc,test_loss test(model, test_loader, loss_model) test_acc_list.append(test_acc) test_loss_list.append(test_loss) print(Done!)运行结果四、结果分析import numpy as np import matplotlib.pyplot as plt from datetime import datetime current_time datetime.now() # 获取当前时间 x [i for i in range(1,31)] plt.plot(x, test_loss_list, labelLoss, alpha0.8) plt.xlabel(Epoch) plt.ylabel(Loss) plt.title(current_time) # 打卡请带上时间戳否则代码截图无效 plt.legend() plt.show()运行结果五、ACC统计加入def test(model, test_loader, loss_model): size len(test_loader.dataset) num_batches len(test_loader) model.eval() test_loss, correct 0, 0 with torch.no_grad(): for X, y in test_loader: X, y X.to(device), y.to(device) pred model(X) test_loss loss_model(pred, y).item() # 预测索引 pred_ids pred.argmax(dim2) true_ids y.argmax(dim2) # 统计完全匹配的样本数 correct (pred_ids true_ids).all(dim1).sum().item() test_loss / num_batches accuracy correct / size print(fAvg loss: {test_loss:8f}, Accuracy: {accuracy:.4f} ({correct}/{size})\n) return correct, test_loss, accuracy模型输出pred形状是[16, 7, 69]。这意味着16张图每张图有7个位置每个位置上有69个概率值每个字符的概率。1.模型输出的是概率69个数字 → 2.用argmax转成具体的字符编号→ 3.和真实编号逐位比较→ 4.用all要求 7 个字符全对→ 5.累加正确的个数→ 6.除以总数得到准确率。六、总结本周主要是学习对于不同数据命名格式的时候要如何处理对于车牌号的识别考虑到每个车牌号都是一个独立的名称因此无法像之前的分类任务一样根据不同类型进行分类。在车牌号中一共有三个类型的变量字符、数字和字母所以为进行识别就需要对车牌号进行独热编码。

相关新闻

X推荐算法开源技术解析与工程实践

X推荐算法开源技术解析与工程实践

1. X推荐算法开源的技术背景与行业影响推荐算法作为互联网内容分发的核心技术,近年来经历了从闭源到开源的重大转变。X算法的开源标志着推荐系统领域进入了一个新阶段——头部企业开始将经过海量用户验证的核心算法向社区开放。这种转变背后是三个关键因素&#xff…

2026/10/20 1:54:58 阅读更多 →
OpenObserve架构深度解析:如何实现140倍存储成本优化的可观测性平台

OpenObserve架构深度解析:如何实现140倍存储成本优化的可观测性平台

OpenObserve架构深度解析:如何实现140倍存储成本优化的可观测性平台 【免费下载链接】openobserve Open source observability platform for logs, metrics, traces, frontend monitoring, pipelines and LLM observability. A sophisticated, simple and highly pe…

2026/10/19 11:18:24 阅读更多 →
3分钟掌握开源AI瞄准系统:基于YOLOv8的智能游戏辅助解决方案

3分钟掌握开源AI瞄准系统:基于YOLOv8的智能游戏辅助解决方案

3分钟掌握开源AI瞄准系统:基于YOLOv8的智能游戏辅助解决方案 【免费下载链接】RookieAI_yolov8 基于yolov8实现的AI自瞄项目 AI self-aiming project based on yolov8 项目地址: https://gitcode.com/gh_mirrors/ro/RookieAI_yolov8 RookieAI_yolov8是一款基…

2026/10/20 4:41:43 阅读更多 →

最新新闻

使用 Zafiro.Avalonia 语义容器构建可维护的 Avalonia 布局:HeaderedContainer、EdgePanel 与 Card 实战指南

使用 Zafiro.Avalonia 语义容器构建可维护的 Avalonia 布局:HeaderedContainer、EdgePanel 与 Card 实战指南

AI 技能AI 插件人工智能 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600 agentic skills. Includes CLI, local MCP, c…

2026/10/21 5:30:11 阅读更多 →
双线AI Agent架构:权限边界与安全机制的设计实践

双线AI Agent架构:权限边界与安全机制的设计实践

这半年我们团队一直在折腾一套双线 Agent 框架,内部代号分别是 QClaw 和 WorkBuddy。项目做到中期,周围人问得最多的一个问题就是:你们为什么不把两套能力合成一个 Agent,非要拆成两条线?等到权限事故出了两次之后&…

2026/10/21 5:30:11 阅读更多 →
Avalonia 交互逻辑分层实战:用 Xaml.Interaction.Behaviors 替代 Converter,打造干净的 Zafiro 视图层

Avalonia 交互逻辑分层实战:用 Xaml.Interaction.Behaviors 替代 Converter,打造干净的 Zafiro 视图层

AI 技能AI 插件人工智能 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600 agentic skills. Includes CLI, local MCP, c…

2026/10/21 5:30:11 阅读更多 →
用Claude Code实现多项目高效管理:上下文隔离与规则设计实践

用Claude Code实现多项目高效管理:上下文隔离与规则设计实践

1. 为什么需要一套多项目管理方案去年底我们团队接了一个跨平台系统集群的维护需求,手上同时有五个项目在推进。每个项目都有自己的技术栈、发布时间线和依赖组件,最要命的是这些项目之间还有公共服务层互相依赖。以前用传统命令行的方式逐个项目开终端、…

2026/10/21 5:30:11 阅读更多 →
基于K6的支付系统性能压测实战指南

基于K6的支付系统性能压测实战指南

做支付系统的性能验证,是我这几年踩坑最密集的领域之一。业务高峰期接口一抖,服务器CPU飙到99%,紧接着订单积压、支付超时、对账不平,最后大半夜一群人围着告警大屏开会。我后来把整套验证方式固化下来,核心选型就是K6…

2026/10/21 5:30:11 阅读更多 →
AI搜索时代的口碑优化:从口径库到内容证据链的实战指南

AI搜索时代的口碑优化:从口径库到内容证据链的实战指南

在各行业都在谈“数字化”的时候,真正影响消费决策的通道其实已经换了。以前大家搜一个品牌,是翻链接、看标题、挑网站;现在打开对话式AI,直接问一句“这座城有什么值得吃的”“这家店的真实口碑怎么样”,然后就看AI给…

2026/10/21 5:29:11 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →