前言
方针辨认如今以及迭代了这么多年,遍及受大家认可和欢迎的方针辨认框架便是YOLO了。依照官方描述,YOLOv8 是一个 SOTA 模型,它建立在以前 YOLO 版别的成功基础上,并引入了新的功能和改善,以进一步进步功能和灵活性。从根本的YOLOv1版别到如今v8版别,完结了多次蜕变,现在现已相当老练而且十分的亲民。
我见过许多初学方针辨认的同学根本上只花一周时刻就能够参照案例完结一个方针检测的项目,这全赖YOLO强大的解耦性和布置简易性。初学者甚至只需求修改部分超参数接口,调整数据集就能够完结方针检测了。
可是我想表达的并不是YOLO的原理有多么难了解,原理有多难推理。一般工作中要求咱们能够运转而且能够完结方针检测出来就能够了,更重要的是数据集的标示。
咱们不需求完结简直难以单人完结的造方针检测算法轮子的进程,咱们需求了解YOLO算法中每个超参数的作用以及影响。就算咱们能够练习出必定准确度的方针检测模型,咱们还需求依据实际情况对生成成果进行必定的改写:例如关于图片来说一共呈现了几种方针;关于一个视频来说,定位到具体时刻呈现了辨认的方针。这都是需求咱们重复学习再练习的身手。
完结方针检测后,咱们应该输出定位出来的信息,YOLO是提供输出设定的超参数的,咱们需求依据输出的信息对方针进行裁剪得到咱们想要的方针之后再做上层处理。假如是车牌方针辨认的项目,咱们裁剪出来的车牌就能够进行OCR技能辨认出车牌字符了,假如是安全帽辨认项目,那么咱们能够计算一张图片或者一帧中呈现检测方针的个数做出判断,一切都需求依据实际业务需求为主。
本篇文章首要是OCR模型对车牌进行字符辨认,结合YOLO算法直接定位方针进行裁剪,裁剪后生成OCR练习数据集即可。开源项目地址如下,假如有协助期望不惜点亮star~ :
其间数据集的质量是尤为重要的,决定了模型的上限,因此想要建立一个作用较好的方针辨认算法模型,就需求处理流程较为完善的开源数据集。
本篇文章选用的是CCPD数据集,上篇文章现已具体描述了整个项目的初步建立进程,包括数据集预备和数据预处理,大体系统框架和数据标签聚合,以及运用Yolov7进行模型练习和推理,能够得到图片或者视频帧中车牌的定位数据,现在咱们需求建立LPRNet网络来完结OCR车牌字符辨认输出。
一、车牌字符辨认
一般来说此类技能都成为OCR,OCR(Optical Character Recognition)技能是一种将图画中的文字转化为可编辑文本的技能。它能够通过计算机视觉和模式辨认的方法来辨认和提取图画中的文字信息。依据调研运用的常用网络框架有三种都能够作为车牌辨认:
CRNN:最经典的OCR模型了,选用CNN+RNN的网络结构,提出CTC-Loss对齐算法处理不定长序列对齐问题;原始源码是用于文字辨认的,略微改成车牌数据集,即可用于车牌辨认了
LPRNet* :*比较经典的CRNN模型,LPRNet 没有选用RNN结构;是专门规划用于车牌辨认的轻量级的模型,整个网络结构规划高度轻量化,参数量仅有0.48M
PlateNet:LPRNet网络结构中存在MaxPool3d等算子,在端上布置时,会存在OP不支持等问题,PlateNet模型去除MaxPool3d,改成运用MaxPool2d,保证模型可端上布置成功。
模型 | input-size | params(M) | GFLOPs |
---|---|---|---|
LPRNet | 9424 | 0.48M | 0.147GFlops |
CRNN | 16032 | 8.35M | 1.06GFlops |
PlateNet | 16848 | 1.92M | 1.25GFlops |
本项目采纳的是LPRNet,这儿简述一下LPRNet。
二、LPRNet
“LPRNet”是用于车牌辨认(License Plate Recognition,LPR)的神经网络模型。首要规划出方针便是针对检测和辨认车牌字符。 论文由Intel于2018年发表: LPRNet: License Plate Recognition via Deep Neural Networks,网络结构规划追求高度轻量化,为了能够方便在嵌入式设备运用,且辨认率还不低彻底够用。LPRNet的特色有:
-
End-to-End规划:LPRNet是一个端到端的网络,能够直接从原始图画中提取车牌信息,而无需手动规划特征提取器。
-
针对性强:LPRNet专门规划用于车牌辨认使命,因此在车牌辨认使命上具有很强的功能。
-
多使命学习:LPRNet一般包括字符分类使命和位置回归使命。字符分类使命用于辨认车牌上的每个字符,位置回归使命用于定位车牌的位置。
-
卷积神经网络:LPRNet一般运用卷积神经网络来提取特征,这使得它对图画的空间信息进行了很好的运用。
-
选用了特定的丢失函数:LPRNet一般会运用CTC(Connectionist Temporal Classification)丢失函数来处理字符等级的辨认,这是一种适用于序列标示使命的丢失函数。
Intel论文中规划了一个图画预处理网络,将车牌图画进行改换(如偏移、旋转车牌图片),得到合适的车牌图片输入到CNN中,论文运用的是LocNet网络主动学习最佳的转换参数。LocNet模型结构如下:
其间LPRNet的backbone模块是自行规划的一个轻量化的backbone,其间规划的一个Small basic block其实便是一个瓶颈型的结构。
Small basic block结构如下:
先经过第一个1×1卷积进行降维,再用一个3×1和一个1×3卷积进行特征提取,最终再用1个1×1卷积进行升维。不对称卷积能够代替对称矩阵,3×1+1×3发生和3×3一样的作用,参数量还更少了,而且还多了一个ReLU激活函数,增加了非线性。
class 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),
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)
backbone的全体架构:
self.backbone = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1), # 0
nn.BatchNorm2d(num_features=64),
nn.ReLU(), # 2
nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(1, 1, 1)),
small_basic_block(ch_in=64, ch_out=128), # *** 4 ***
nn.BatchNorm2d(num_features=128),
nn.ReLU(), # 6
nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(2, 1, 2)),
small_basic_block(ch_in=64, ch_out=256), # 8
nn.BatchNorm2d(num_features=256),
nn.ReLU(), # 10
small_basic_block(ch_in=256, ch_out=256), # *** 11 ***
nn.BatchNorm2d(num_features=256), # 12
nn.ReLU(),
nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(4, 1, 2)), # 14
nn.Dropout(dropout_rate),
nn.Conv2d(in_channels=64, out_channels=256, kernel_size=(1, 4), stride=1), # 16
nn.BatchNorm2d(num_features=256),
nn.ReLU(), # 18
nn.Dropout(dropout_rate),
nn.Conv2d(in_channels=256, out_channels=class_num, kernel_size=(13, 1), stride=1), # 20
nn.BatchNorm2d(num_features=class_num),
nn.ReLU(), # *** 22 ***
)
仅有需求注意的是:最终一层conv用的是一个13×1的卷积代替了原先的BiLSTM来结合序列方向(W方向)的上下文信息。大局上下文嵌入,这部分论文是运用一个全衔接层提取上下文信息的,只交融了两层,而这儿是运用的avg pool层,而且还在4个尺度上进行了交融:
global_context = list()
for i, f in enumerate(keep_features):
if i in [0, 1]:
f = nn.AvgPool2d(kernel_size=5, stride=5)(f)
if i in [2]:
f = nn.AvgPool2d(kernel_size=(4, 10), stride=(4, 2))(f)
f_pow = torch.pow(f, 2)
f_mean = torch.mean(f_pow)
f = torch.div(f, f_mean)
global_context.append(f)
x = torch.cat(global_context, 1)
不用再自己从新搭一遍神经网络,比较费事, 我这儿运用大佬的开源网络模型:GitHub – Fanstuck/LPRNet_Pytorch: Pytorch Implementation For LPRNet, A High Performance And Lightweight License Plate Recognition Framework.
作者:彻底适用于我国车牌辨认(Chinese License Plate Recognition)及国外车牌辨认!
目前仅支持一起辨认蓝牌和绿牌即新能源车牌等我国车牌,但可通过扩展练习数据或微调支持其他类型车牌及进步辨认准确率!
将该模型集成到咱们项目,
那么接下来咱们需求对裁剪的数据集进行练习得到模型权重即可。有几点需求注意:
- 预备数据集,图画巨细有必要为94×24。
- 若要显示测试成果,请添加“–show true”或“–show 1”以运转指令。
其他都挺好看清楚的,看作者提供的首要参数阐明:
- -max_epoch:假如想要精度更高一点,epoch能够设定更高一点。
- -dropout_rate:假设 Dropout rate 为 0.5,即躲藏层中 50% 的神经元将在每次练习迭中被随机封闭。防止过拟合,假如图片量过少的情况下需求高一点更好。
- -learning_rate:要是算力充足能够调小一点愈加准确。
- train_batch_size和test_batch_size的默许就行,假如数据集较小不用太大。
- resume_epoch重复练习,数据集小的能够,数据量大的没有必要。
练习模型
依据自己的数据集以及硬件条件设置train_LPRNet.py的超参数,这儿得注意咱们需求运用YOLOv7检测出来的定位信息去裁剪原图画的车牌坐标,裁剪到的图片需求转换为94,24的img_size的图片才干练习。之前咱们有过预备数据集,直接运用即可。
数据集足够大,练习时长给的足够多能够到达比较高的精度,我依据自己制造的数据集练习能够到达93.1%的正确率,该模型权重现已上传github大家不用再次练习了直接运用模型即可。
推理
开源的模型权重能够在我切割的数据集上面跑到73.2%准确率,咱们能够运用预练习模型在此基础之上练习得到准确度更高的模型,运用上述模型咱们能够进行车牌检测看看作用:
测试了20张图片到达50%,测试1000张图片到达92.3%,测试6000张图片到达了93.5%准确率,作用还是能够的。
备注
有问题的私信博主或者直接评论就能够了博主会长时间保护此开源项目,目前此项目运转需求多部操作比较繁琐,我将不断更新版别优化,下一版别将加入UI以及一键布置环境和添加sh指令一键运转项目代码。
下篇文章将具体解读LPRNet模型如何进行OCR辨认, 再次期望对大家有协助不惜点亮star~ : github.com/Fanstuck/Yo…