当前位置:   article > 正文

车牌识别 远距离监控视角 自创简化模型 Pytorch_车牌识别模型

车牌识别模型

甲方一拍脑门,让我去实现车牌识别,还是远距离监控视角的,真开心。
在这里插入图片描述
数据?呵~ 不会有人期待甲方提供数据吧??
先逛逛某宝,一万张车辆图片,0.4元/张。
甲方:阿巴阿巴…
嗯,那没事了。
在这里插入图片描述
再逛逛全球同性交友网站,感谢CCPD数据集~ 数量挺多的,补充了新能源绿色车牌,标注也很详细,除了车牌矩形框坐标,居然还有车牌4个角点坐标。我看了一下,矩形框标的有点随意了,于是我把角点坐标的最小包络矩形作为新的标注框,随手一个YOLOv5,这车牌检测的任务不就完成了嘛~ 四舍五入,车牌识别项目收工!
在这里插入图片描述
由于数据搜集的地域原因,其中一大半车牌的开头都是皖A,这…不得训练出来个人工智障,见个车牌就说是皖A?哎,只能含泪筛选出1W张用作车牌识别训练。

这数据量肯定不够呀,只能造假了…参考车牌生成代码,调调参数,解决个别字符的小bug,最终效果这样婶儿滴:
在这里插入图片描述

生成10+W张假车牌,再去全网捡捡零碎数据,东拼西凑了20+W张。凑合过吧,要啥自行车。

接下来进入正题,车牌切出来了,咋识别?

用传统方法,字符分割再识别单个字符?emmm,算了叭,传统是不可能传统的(我也不会!!)。

最典型的字符识别模型是CRNN+CTC,CTC Loss是为了解决字符对齐问题。因为车牌字符数目是固定的,这就大大简化了问题,其实没必要使用CTC Loss,直接用CNN、RNN和全连接,根据心情搭配一下都能训练。

之前我学习的时候,也玩过一个Seq2Seq的车牌识别模型(在这里!),但如果不加注意力机制,效果不咋样,我试了一下,直接暴力增大LSTM隐藏层的size,也能训练出来,只是模型有100+M。

咳…你才捞呢!
在这里插入图片描述
还是决定自己搭个网络玩儿,参考了CRNN的原网络和GitHub上的一些实现,先整一套尝尝,噔噔蹬蹬~

import torch.nn as nn

class Crnn(nn.Module):
    def __init__(self):
        super(Crnn, self).__init__()
        self.cnn = nn.Sequential(  # (N,3,32,100)
            nn.Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=1),     # (N,64,32,100)
            nn.ReLU(),
            nn.MaxPool2d((2, 2), 2),  # (N,3,16,50)
            nn.Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=1),   # (N,128,16,50)
            nn.ReLU(),
            nn.MaxPool2d((2, 2), 2),  # (N,128,8,25)
            nn.Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=1),  # (N,256,8,25)
            nn.ReLU(),
            nn.Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=1),  # (N,256,8,25)
            nn.ReLU(),
            nn.MaxPool2d((2, 1), stride=(2, 1)),  # (N,256,4,25)
            nn.Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=1),  # (N,512,4,25)
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=1),  # (N,512,4,25)
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.AdaptiveMaxPool2d([1, 25])
        )
        self.lstm = nn.LSTM(input_size=512,
                             hidden_size=140,
                             batch_first=True,
                             bidirectional=True,
                             num_layers=2)

    def forward(self, x):
        cnn_out = self.cnn(x).reshape(-1, 512, 25).transpose(2, 1)  # (N,25,512)
        lstm_out, (h_n, c_n) = self.lstm(cnn_out, None)
        lstm_out = lstm_out[:, -1, :]  # (N, 140)
        out = lstm_out.reshape(-1, 8, 35)

        return out
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

32个中文字符和34个数字字母(不含I和O)由列表定义:

c1 = ['皖', '沪', '津', '渝', '冀', '晋', '蒙', '辽', '吉', '黑', '苏', '浙', '京', '闽', '赣', '鲁',
      '豫', '鄂', '湘', '粤', '桂', '琼', '川', '贵', '云', '西', '陕', '甘', '青', '宁', '新', '藏']
c2 = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S',
      'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '']
  • 1
  • 2
  • 3
  • 4

拆成两个列表是节约输出的维度,减少参数量。

输入车牌尺寸是 100 ∗ 32 100*32 10032,因为CNN最后我用了个自适应平均池化,所以图片尺寸不对也不会报错。网络输出shape为 ( N , 8 , 35 ) (N, 8,35) (N,8,35),普通车牌是7位的,新能源绿色车牌是8位的,所以需要增加一个空字符串,如果是7位车牌,最后一个字符就为空。

将标签做one-hot,损失函数直接用MSELoss。看起来有点捞,训练效果却出奇的好,10轮验证精度就到99%。模型大小26M,推理速度还行。拿实际的监控视频测试了一下,效果也还能看。

但用MSELoss做分类问题,多少有点别扭,而且输出的值无法表示概率。思考了一下怎么改用CrossEntropyLoss,直接把标签的one-hot去掉是会报错的,因为我们的输出是 ( N , 8 , 35 ) (N, 8,35) (N,8,35),相当于是8个字符的分类结果,CrossEntropyLoss算的是一个分类结果,于是我把输出 ( N , 8 , 35 ) (N, 8,35) (N,8,35)reshape成 ( N ∗ 8 , 35 ) (N*8,35) (N8,35),把标签 ( N , 8 ) (N, 8) (N,8)拉平成 ( N ∗ 8 ) (N*8) (N8),这样就可以计算辣~

蓝鹅,效果很不好,精度到60+%就上不去了…在这里插入图片描述
经过一番深思(才不是瞎猜的 哼!),我觉得循环网络的输出直接跟交叉熵损失不合适,一般的分类问题最后一层都是全连接输出的,于是把lstm层改成了全连接:

self.fc = nn.Linear(512, 280)
  • 1

这样就可以训练辣,模型还更小了点,24M~
在这里插入图片描述
最后尝试将LSTM替换成GRU,再次减少参数。以及将pytorch自带的交叉熵损失改成Focal Loss,以增加对困难样本(主要是第一个中文字符)的训练力度。
在这里插入图片描述
之前领导为了跟甲方展示(吹niubility),按量买了百度的车牌识别。
在这里插入图片描述
卖的死贵,效果就这?就这??

在这里插入图片描述
咱的效果:

在这里插入图片描述
哼哼哼~ 走咯~ 卖算法去咯~
在这里插入图片描述
我不是在黑百度,对不起!!

百度的技术是很厉害的,只是人家针对的是近距离的车牌。实际上,现在车牌识别使用最多的应该是停车场的道闸系统,都是近距离的,这种监控视角的,确实有难度,精度还达不到要求,我这个模型只是最简单的一种实现。

不足:

  1. 货车的黄色车牌数据量太少,容易检测不到。(百度也是)
  2. 汉字字符的识别精度不高。(百度也是)
  3. 新能源绿色车牌的字符识别精度不高。(百度也是…)

在实际使用中,如果每一帧都识别的话,不仅费时,而且显示上会闪烁,就很鬼畜。所以我结合DeepSort跟踪算法,跟踪每一个车牌目标,设计规则,如在连续数帧都识别为同一车牌号后,就稳定显示,不再识别。

数据集还在筛选和补充,模型也还在改进,就不上传辣~
真有需要的同学私撩

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/524860
推荐阅读
相关标签
  

闽ICP备14008679号