整个车牌识别有两部分组成,一个是目标检测部分,可以用yolov4等,另一个部分就是车牌识别部分,用LPRNet。
LPRNet 的官方github是 LPRNet.py
LPRNet主要需要了解三个部分
分别是 1. STN网络部分;2.主体网络部分 3.Loss部分

主体网络backbone属于轻量级模型,其中基础模块叫small_basic_block,具体参考下面注释

import torch.nn as nn
import torchclass small_basic_block(nn.Module):def __init__(self, ch_in, ch_out):super(small_basic_block, self).__init__()self.block = nn.Sequential(nn.Conv2d(ch_in, ch_out // 4, kernel_size=1), #1x1的average pooling,降维和减少参数#下面经过3x1和1x3卷积的学习 [替代3x3卷积],然后再进行升维nn.ReLU(),nn.Conv2d(ch_out // 4, ch_out // 4, kernel_size=(3, 1), padding=(1, 0)),nn.ReLU(),nn.Conv2d(ch_out // 4, ch_out // 4, kernel_size=(1, 3), padding=(0, 1)),nn.ReLU(),nn.Conv2d(ch_out // 4, ch_out, kernel_size=1),)def forward(self, x):return self.block(x)class LPRNet(nn.Module):def __init__(self, lpr_max_len, phase, class_num, dropout_rate):super(LPRNet, self).__init__()self.phase = phaseself.lpr_max_len = lpr_max_lenself.class_num = class_numself.backbone = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1),    # 0  [bs,3,24,94] -> [bs,64,22,92]nn.BatchNorm2d(num_features=64),                                       # 1  -> [bs,64,22,92]nn.ReLU(),                                                             # 2  -> [bs,64,22,92]nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(1, 1, 1)),                 # 3  -> [bs,64,20,90]small_basic_block(ch_in=64, ch_out=128),                               # 4  -> [bs,128,20,90]nn.BatchNorm2d(num_features=128),                                      # 5  -> [bs,128,20,90]nn.ReLU(),                                                             # 6  -> [bs,128,20,90]nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(2, 1, 2)),                 # 7  -> [bs,64,18,44]small_basic_block(ch_in=64, ch_out=256),                               # 8  -> [bs,256,18,44]nn.BatchNorm2d(num_features=256),                                      # 9  -> [bs,256,18,44]nn.ReLU(),                                                             # 10 -> [bs,256,18,44]small_basic_block(ch_in=256, ch_out=256),                              # 11 -> [bs,256,18,44]nn.BatchNorm2d(num_features=256),                                      # 12 -> [bs,256,18,44]nn.ReLU(),                                                             # 13 -> [bs,256,18,44]nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(4, 1, 2)),                 # 14 -> [bs,64,16,21]nn.Dropout(dropout_rate),  # 0.5 dropout rate                          # 15 -> [bs,64,16,21]nn.Conv2d(in_channels=64, out_channels=256, kernel_size=(1, 4), stride=1),   # 16 -> [bs,256,16,18]nn.BatchNorm2d(num_features=256),                                            # 17 -> [bs,256,16,18]nn.ReLU(),                                                                   # 18 -> [bs,256,16,18]nn.Dropout(dropout_rate),  # 0.5 dropout rate                                  19 -> [bs,256,16,18]nn.Conv2d(in_channels=256, out_channels=class_num, kernel_size=(13, 1), stride=1),  # class_num=68  20  -> [bs,68,4,18]nn.BatchNorm2d(num_features=class_num),                                             # 21 -> [bs,68,4,18]nn.ReLU(),                                                                          # 22 -> [bs,68,4,18])self.container = nn.Sequential(nn.Conv2d(in_channels=448+self.class_num, out_channels=self.class_num, kernel_size=(1, 1), stride=(1, 1)),# nn.BatchNorm2d(num_features=self.class_num),# nn.ReLU(),# nn.Conv2d(in_channels=self.class_num, out_channels=self.lpr_max_len+1, kernel_size=3, stride=2),# nn.ReLU(),)def forward(self, x):keep_features = list()for i, layer in enumerate(self.backbone.children()):x = layer(x)if i in [2, 6, 13, 22]: #2: [bs,64,22,92]  6:[bs,128,20,90] 13:[bs,256,18,44] 22:[bs,68,4,18]keep_features.append(x)global_context = list()# keep_features: [bs,64,22,92]  [bs,128,20,90] [bs,256,18,44] [bs,68,4,18]for i, f in enumerate(keep_features):if i in [0, 1]:# [bs,64,22,92] -> [bs,64,4,18]# [bs,128,20,90] -> [bs,128,4,18]f = nn.AvgPool2d(kernel_size=5, stride=5)(f)if i in [2]:# [bs,256,18,44] -> [bs,256,4,18]f = nn.AvgPool2d(kernel_size=(4, 10), stride=(4, 2))(f)# 没看懂这是在干嘛?有上面的avg提取上下文信息不久可以了?f_pow = torch.pow(f, 2)     # [bs,64,4,18]  所有元素求平方f_mean = torch.mean(f_pow)  # 1 所有元素求平均f = torch.div(f, f_mean)    # [bs,64,4,18]  所有元素除以这个均值 global_context.append(f)x = torch.cat(global_context, 1) #[bs,64,4,18]+[bs,128,4,18]+[bs,256,4,18]+[bs,68,4,18]=[bs,516,4,18]x = self.container(x)  # [bs,516,4,18] -> [bs, 68, 4, 18]   head头logits = torch.mean(x, dim=2)  # -> [bs, 68, 18]  # 68 字符类别数   18字符序列长度return logits
CHARS = ['京', '沪', '津', '渝', '冀', '晋', '蒙', '辽', '吉', '黑','苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘', '粤','桂', '琼', '川', '贵', '云', '藏', '陕', '甘', '青', '宁','新','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K','L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V','W', 'X', 'Y', 'Z', 'I', 'O', '-']
len(CHARS) = 68
def sparse_tuple_for_ctc(T_length, lengths):input_lengths = []target_lengths = []for ch in lengths:input_lengths.append(T_length)target_lengths.append(ch)return tuple(input_lengths), tuple(target_lengths)for iteration in range(start_iter, max_iter):.........images, labels, lengths = next(batch_iterator) #labels是[3,44,68,33,22,55,36,39]代表8个字符,length=8input_lengths, target_lengths = sparse_tuple_for_ctc(T_length, lengths) # T_length=18, length=8#input_lengths bsx18 target_lengths=bsx8# forwardlogits = lprnet(images) # [bs. 68. 18] 64是字符串个数,18是字符序列长度log_probs = logits.permute(2, 0, 1) # for ctc loss: T x N x C  [18,bs,68]log_probs = log_probs.log_softmax(2).requires_grad_()# log_probs = log_probs.detach().requires_grad_()# print(log_probs.shape)# backpropoptimizer.zero_grad()loss = ctc_loss(log_probs, labels, input_lengths=input_lengths, target_lengths=target_lengths)# 【18,bs,68】【bs,8】【bsx18】【bsx8】注意标签可能是变长的 比如 18, 45, 33, 37, 40, 49, 63  -->> 车牌 “湘E269JY”4, 54, 51, 34, 53, 37, 38   -->> 车牌 “冀PL3N67”22, 56, 37, 38,33, 39, 34, 46  -->> 车牌 “川R67283F”2, 41, 44, 37, 39, 35, 33, 40  -->> 车牌 “津AD68429”长度分别是7 7 8 8 代表labels.........

关于ctc_loss:

ctc_loss = nn.CTCLoss() #下面的N=batch size
log_probs = torch.randn(50, 16, 20).log_softmax(2).detach().requires_grad_()
#T=50 N=16 C=20 ;
targets = torch.randint(1, 20, (16, 30), dtype=torch.long) # [16,30]
input_lengths = torch.full((16,), 50, dtype=torch.long) #1x16
target_lengths = torch.randint(10,30,(16,), dtype=torch.long)#16x1
loss = ctc_loss(log_probs, targets, input_lengths, target_lengths)
loss.backward()

log_probs:shape为(T, N, C)的模型输出张量,其中,T表示CTCLoss的输入长度也即输出序列长度,N表示训练的batch size长度,C则表示包含有空白标签的所有要预测的字符集总长度,log_probs一般需要经过torch.nn.functional.log_softmax处理后再送入到CTCLoss中;

targets为shape是(N, S)的张量 ,其中第一种类型,N表示训练的batch size长度,S则为标签长度,第二种类型,则为所有标签长度之和,但是需要注意的是targets不能包含有空白标签;

input_lengths:shape为(N)的张量或元组,但每一个元素的长度必须等于T即输出序列长度,一般来说模型输出序列固定后则该张量或元组的元素值均相同;

target_lengths:shape为(N)的张量或元组,其每一个元素指示每个训练输入序列的标签长度,但标签长度是可以变化的;

关于ctc loss的解释 https://zhuanlan.zhihu.com/p/67415439

https://blog.csdn.net/ckqsars/article/details/108312750?spm=1001.2101.3001.6650.10&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-10-108312750-blog-106143755.pc_relevant_aa_2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-10-108312750-blog-106143755.pc_relevant_aa_2&utm_relevant_index=11

https://blog.csdn.net/qq_38253797/article/details/125054464

https://blog.csdn.net/weixin_39027619/article/details/106143755

LPRNet, 车牌识别网络相关推荐

  1. 【项目三、车牌检测+识别项目】四、使用LPRNet进行车牌识别

    目录 前言 一.数据集 二.训练 三.验证 四.测试结果 五.推理代码 Reference 前言 马上要找工作了,想总结下自己做过的几个小项目. 之前已经总结过了我做的第一个项目:xxx病虫害检测项目 ...

  2. 车牌识别之LPRNet

    论文: LPRNet: License Plate Recognition via Deep Neural Networks Github:https://github.com/sirius-ai/L ...

  3. 我用AI回怼美女汽车销售系列[yolo车牌识别](四)

    上期回顾 上一期中,我们从数据增强角度,对车牌识别进行了mixup,彷射变换,模糊处理等,最终在ccpd数据集的测试集上面将t将top1准确率从0.9683提升到了0.991(提升了2.3个点),但是 ...

  4. 我用AI回怼美女汽车销售系列[yolo车牌识别](三)

    前期回顾: 在上一期中,正当我信心满满的准备将模型应用在车牌识别的时候,遇到了很大的问题.就是在视频中,会把同一个车牌识别成很多不同的车牌号.这样会严重影响最终的统计精度.如下图所示,同一个这牌,由于 ...

  5. 车牌识别——AidLux2023年2月智慧社区AI实战训练营

    AidLux社区文章位置:https://community.aidlux.com/postDetail/1344 AidLux2023年2月智慧社区AI实战训练营的车牌识别项目作业展示 项目为车牌识 ...

  6. 基于MATLAB的多方法车牌识别识别系统【GUI,多方法,对比,语音播报,出入库,剩余车位】...

    一.课题介绍 该课题为基于MATLAB的多方法车牌识别识别系统,带有丰富的人机交互GUI界面.目前毕业设计选题中,传统的中规中矩的车牌识别不易得到高分,甚至过不了. 必须要在此基础上有所创新方得可以避 ...

  7. 快准狠!Intel论文揭示自家车牌识别算法:LPRNet

    (关注52CV--有价值有深度的公众号~) 来自工业界的最佳实践. 车牌识别是一个老生常谈的话题,在工业界已经得到广泛应用.当深度学习在各种视觉识别任务上刷新更高精度的时候,却常常被认为计算量远大于传 ...

  8. 基于yolov3的目标检测与LPRnet字符识别的车牌识别(CCPD2020新能源车牌数据集)

    文章目录 前言 一.程序思路 二.使用步骤 1.配置环境 2.文件结构 3.准备数据集 4.训练 有问题欢迎指正 前言 项目放这:车牌识别 基于python和pytorch平台,使用CCPD2020新 ...

  9. 智能驾驶 车牌检测和识别(三)《CRNN和LPRNet实现车牌识别(含车牌识别数据集和训练代码)》

    智能驾驶 车牌检测和识别(三)<CRNN和LPRNet实现车牌识别(含车牌识别数据集和训练代码)> 目录 智能驾驶 车牌检测和识别(三)<CRNN和LPRNet实现车牌识别(含车牌识 ...

最新文章

  1. Djang1.8+Python2.0迁移到Django2.0+Python3.6注意事项(转)
  2. Python-EEG工具库MNE中文教程(3)-MNE中数据结构Epoch及其用法简介
  3. hdu1466 计算直线的交点数
  4. Zookeeper基本概念
  5. 【Jquery系列】之DOM属性
  6. mysql 将a表数据插入b表_查询A表数据插入到B表中 sql
  7. 计算机领域有哪些常见的比赛
  8. Hive建表语句解释
  9. 无线安全之破解WPA/WPA2 加密WiFi
  10. ipad 的android模拟器,苹果IPAD模拟器(iPadian)
  11. JDK各个版本新特性介绍及使用
  12. phpnow mysql升级,phpnow升级apache版本
  13. UG二次开发GRIP成品工具
  14. 围棋棋盘怎么编程python_python围棋_python围棋程序_python实现围棋ai - 云+社区 - 腾讯云...
  15. 金融工程中的蒙特卡罗方法
  16. FAST-LIO2代码解析(五)
  17. Python写网络爬虫(三)
  18. Docker build创建指定容器镜像
  19. NAO机器人高尔夫中的视觉系统设计
  20. 135.如何进行离线计算-1

热门文章

  1. 独家算力支持|腾讯“开悟”AI大赛启动
  2. 视觉感知堪比人眼:这款突破性光学传感器模仿人类视网膜,有望带来 AI 重大进展
  3. 语音处理/语音识别基础(四)- 语音文件读取与播放
  4. 郑州医疗卫生服务迈入大数据时代
  5. flexslider图片轮播
  6. 【产业互联网周报】BAT加速布局智慧城市:百度14.43亿元投资东软控股、腾讯签约武汉、阿里签约杭州...
  7. 记录一下HALCON基于可变形,利用CAD画dxf模板进行模板匹配(一)
  8. 太空射击 第02课:使用精灵
  9. 关于今年五一调休。。
  10. 一周热点:IBM新技术使网速达400G/s,硬盘会“烧掉”吗