车牌识别 远距离监控视角 自创简化模型 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

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', '']

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

输入车牌尺寸是 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)

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

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

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

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

不足:

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

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

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

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值