1 综述
(1)代码Github地址:
(2)论文贡献:
LPRNet结构不需要预先进行车牌字符分割,可以端到端的训练
LPRNet没有使用RNN网络结构,足够的轻量化
LPRNet具有良好的鲁棒性,不会受各种相机参数、视角、光照等的影响
2 代码解读
2.1 图像预处理
LPRDataLoader类:
(1)__init__()函数:
1)加载图片的目录
2)指定图片预处理函数,默认为transform,该函数主要是对图像做缩放(-127.5应该是width和heigth的最大值),同时调换图像的shape顺序让通道数放第一位
(2)__getitem__()函数
1)加载图片,并将图片统一到94*24的大小
2)通过transform做缩放
3)将图片名称作为label,针对名称长度为8的单独进行校验,最终输出Image, label, label长度
2.2 LPRNet模型
(1)small_basic_block网络结构
操作 | 参数 | 说明 |
conv2d | (ch_in, ch_out//4, kernel_size=1) | 只改变输出通道数,H和W均未改变 |
relu |
| 通道数、H、W均未改变 |
conv2d | (ch_out//4, ch_out//4, kernel_size=(3,1), padding=(1,0) | 通道数、H、W均未改变,卷积了相邻高度的像素信息 |
relu |
| 通道数、H、W均未改变 |
conv2d | (ch_out//4, ch_out//4, kernel_size=(1,3), padding=(0,1) | 通道数、H、W均未改变,卷积了相邻宽度的像素信息 |
relu |
| 通道数、H、W均未改变 |
conv2d | (ch_out//4, ch_out, kernel_size=1) | 只改变输出通道数,H和W均未改变 |
备注:卷积维度的计算公式:
(2)LPRNet网络结构
操作1为LPRNet的骨干网络结构操作。骨干网络以原始RGB图像作为输入,用CNN提取图像特征。宽卷积(1*13的卷积核)利用本地字符的上下文从而取代了基于LSTM的RNN网络,因为字符串是序列,传统方式是使用RNN提取序列信息。骨干网络的输出可认为是一个代表对应字符概率的序列。
操作2:取第2、6、13步的数据池化后,再与第22步的数据进行concat操作。这一步操作是为了提升模型的表现,增强解码器所得的中间特征图,采用全局上下文关系进行嵌入。主要就是第2、6、13步的特征处理成所需的大小,然后再与骨干网络的输出在channel维度进行拼接。
操作3:第2步的数据con2d后再进行mean操作,得到最终的数据,其维度为:[None, 68, 18],68为总字符集长度,18为预测输出长度。此步的conv应用了1*1卷积进行降维操作,将特征图的深度调整到字符类数。输出序列长度T尽量在模型设计时就要考虑模型需要预测的最长序列,如需要预测的最长序列其长度为l,则理论上T应大于等于2*l+1,这是因为CTCLoss假设在最坏情况下每个真实标签前后都至少有一个空白标签进行隔开以区分重复项。
即输出为概率矩阵,对应上图的纵坐标为68个元素,对应上图的横坐标为18个时间段的元素。CTC中会对每个字符前后增加空格,所以T要大于等于2*l+1。后续针对这个概率矩阵,通过CTCloss可以在没有事先对齐的序列化上做训练。
2.3 loss计算
Lprnet网络输出的预测值,修改为T * N * C的维度
再取log_softmax(先softmax后再取log值)的值后进行ctcloss的计算。
2.4 验证集评估
整体是通过Greedy Decode寻找最优解。
(1)获取每一条数据,其shape为68*18
(2)在shape[0]中寻找最大的值的argmax作为预测值,总共有18个数据。
(3)定义一个多对一的映射B,目的是合并有相同输出的路径。规则为:仅仅合并两个’-‘间多余的字符并且移除所有的’-‘,那么B(a-ab-) = B(-aa—abb) = abb。
(4)验证第(3)的输出与目标字符的差距:
- 如果预测字符集长度与目标字符不一致,则Tn_1个数加1
- 如果预测字符集长度与目标字符一致,且字符内容都一模一样,则Tp个数加1
- 如果预测字符集长度与目标字符一致,但是字符内容不一致,则Tn_2个数加1
通过上述信息计算验证集的准确率。