我用AI回怼美女汽车销售系列[yolo车牌识别]
Posted DL-Practise
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我用AI回怼美女汽车销售系列[yolo车牌识别]相关的知识,希望对你有一定的参考价值。
上期回顾
上一期中,我们从数据增强角度,对车牌识别进行了mixup,彷射变换,模糊处理等,最终在ccpd数据集的测试集上面将t将top1准确率从0.9683提升到了0.991(提升了2.3个点),但是在实际拍摄的视频中,仍然出现了很多的误检。将一个车牌的不同角度图片识别成很多个不同的车牌。虽然没有达到最终目的,但是也让我们更加清晰的认识到,深度学习项目落地的困难。并不是在公开数据集效果很好,在落地项目中效果也会很棒。还是需要针对具体项目进行具体分析。这一期将会从网络结构的角度重新审视我们的车牌识别项目。
车牌识别网络分析
原来的车牌识别网络使用了shufflenet,并根据蓝牌和绿牌拆分成了两个网络。蓝牌网络输出7*34维的概率矩阵,绿牌网络输出了8*34维的概率矩阵。本质原因是由于CNN只能输出固定维度的预测,无法输出动态的预测。
实际上,车牌识别与OCR文字识别类似。只是车牌的格式比OCR简单很多。因为车牌的长宽,字符位置都是固定的,因此我们可以直接使用分类网络输出各个字符的概率。不过这种做法也是欠妥当的,首先我们分了两个网络,导致蓝牌和绿牌需要分开训练和推理。另外就是车牌的字符实际上是不均匀分布的。在第一个字母后面通常有个空格,但是我们设计网络的时候,默认字符是均匀分布的,这些都会导致CNN感受野学习的时候出现一定的偏差。因此我们需要借鉴成熟的OCR网络以及成熟的车牌识别网络如何解决这个问题的。很自然的,CTC技术就进入了我们的视野。
CTC技术简介
CTC技术主要是为了语音识别而提出来的,其全称为:Connectionist Temporal Classification(连接时序分类)。最初应用在语音上,现在OCR上面也在广泛使用。主要应用在预测长度不固定,且标签通常不包含位置信息的情形。例如OCR里面识别一句话,那么由于一句话的长度通常不是固定的,有长有短,但是网络的输出是固定的,因此假设一句话最长是9个字符(为了绘图方便),那么网络输出9*N的预测。假设一句话"hello",如下图所示(图中的'-'表示此处无字符),第一行的预测更加符合预期,每个字符的预测对应的感受野基本是正确的。而第二行的预测更加差一些,很多预测字符对应的感受野是不匹配的。但是仅仅通过标签“hello”,无法判断哪个预测的更好。那么就无法很好的给网络训练提供监督信号进行很好的训练了。
CTC技术主要就是为了解决这种问题的。首先引入一个空白符blank来表示此处没有字符。且连续的字符会合并成一个字符。例如预测输出 h,e,l,l,l,o,o会被当作helo来处理。那如果真的有两个"l"怎么办呢?例如"hello"中有两个连续的"l",CTC规定两个相同字符之间必须插入一个空白字符,用"-"表示,那么h,e,l,-,l,l,o,o就能被正确的解析为"hello"了。
CTC计算举例
下面以一个非常简单的例子来说明CTC具体是如何工作的。为了方便,我们假设我们的语言里面只有t,o两个字符。我们需要识别的图片如下图所示,该图片的标签是“to”。假设我们的网络输出的长度为5,那么网络最终输出的维度是5*(2+1)。之所以需要加上1,是因为CTC规定需要一个blank的空白符。
对于该矩阵,在训练的时候,如果识别成"ttooo",'-tooo','-t-oo','-to--','-too-','-tooo'......等都是正确的。因为在CTC里面相同字符连接在一起会被等价于一个字符,所以ttooo等价与to,而-字符为空白字符,可以删除,因此-t-ooo等级与to。后面几个也是同样的道理。也就是说这些预测都是当作正确的预测。那么loss如何求取的。实际上就是把这些概率求和,作为正确的最终概率:
- ttooo概率p1 = 0.6*0.7*0.5*0.6*0.7
- -tooo概率p2 = 0.2*0.7*0.5*0.6*0.7
- -t-oo概率p3 = 0.2*0.7*0.4*0.6*0.7
- 省略后续计算......
那么最终预测正确的概率 p = p1 + p2 + p3 + ...... ,预测错误的概率是 1 - p, 那么实际上最终就是一个二分类的问题,可以根据交叉熵来求loss,并进行梯度回传。总的来说,CTC是把所有预测都穷举了一遍,然后按照规则,把所有与标签等价的预测作为正确的预测。进而转化成一个二分类问题。
Pytorch中的CTC loss
pytorch中已经内置了ctc loss,可以非常方便的进行使用。主要就是两个API,一个是创建ctc loss;一个是计算ctc loss。
- 创建ctc loss的api
ctc_loss = nn.CTCLoss(blank=len(CHARS)-1, reduction='mean') #blank:表示空白符blank的序号。刚才我们在举例的时候说过,CTC增加了一个blank的符号。此处传入的就 #是空白符的序号。例如我们的预测文本中如果只包含26个英文字母,其序号分别用0~25表示,那么blank可以 #定义为26。
- 计算ctc loss
loss = ctc_loss(log_probs, targets, input_lengths, target_lengths) #log_probs:网络的输出,shape为:(T, N, C),T就是输出的序列长度,N对应的是batch size,C对应的 #是每个字符有多少中可能。例如刚才的预测26个字母+1个blank符号,那么C就是27 #targets:标签值。shape为:(X),指的是N个数据的标签合在一起(一维度) #input_lengths:每个图片的预测长度(实际上如果就是[T,T,T,T...]共N个) #target_lengths:每个图片的标签长度,根据实际情况指定
- ctc loss举例
假设我们使用ctc loss预测车牌号,每个字符有 31(省份) + 36(字母和数字) + 1(blank空白符) = 68种可能,如下所示:
dict=0: '京', 1: '沪', 2: '津', 3: '渝', ...... 31: '0', 32: '1', 33: '2', 34: '3', 35: '4', ...... 41: 'A', 42: 'B', 43: 'C', ...... 67: '-'];
车牌的长度有7个字符(蓝牌)和8个字符(绿牌),CTC建议的输出长度为2*max_len + 1, 为了考虑到每两个字符之间都有一个blank的情况。即输出长度为2*8+1 = 17个。
batch size 假设为2,那么最终网络的输出log_probs的shape为 T * N * C = 17 * 2 * 68;
假设batch size为2的两张图片的标签分别为“京A88888”以及“沪AD12345”,转换成字符对应的序号就是:[0,41,38,36,48,38,38] 和 [1,41,44,32,33,34,35,36]。那么最终的targets就是:[0,41,38,36,48,38,38,1,41,44,32,33,34,35,36]。
input_lengths 为[17, 17]
target_lengths为[7,8]
修改车牌识别网络
有了CTC loss之后,我们就不需要像以前那样对蓝牌和绿牌进行分开训练了,可以放在一个网络里面进行训练。如下图所示为网络的最终结构。网络最终输出的是17*68维度的预测矩阵。
预测矩阵与原车牌的对应关系如下图所示
网络训练
使用CTC技术之后,训练了6个epoch,精度就达到了惊人的0.9999.
使用CTC模型在几张测试图片上的推理结果如下图所示:
效果还是挺不错的,不过也有错误识别,说明CTC确实可行
视频误检
虽然上述图片测试效果比较好。但是使用真正的视频测试,仍然会出现误检的情况。即一个车牌由于角度的不同被识别成不同的车牌号(但是这些车牌号都比较接近)。如下图所示,视频中出现了三辆车,但是却识别出了多个车牌。
分析上面的误检,首先,省份比较容易预测错误。这是由于CCPD数据集主要从安徽的停车场中收集的,因此车牌中省份是“皖”的数据量特别大,而其他省份的就会少很多。因此如果不做一些数据增强或者训练策略,很容易导致车牌对“皖”的预测偏好。不过这个对于我们用车牌来识别车辆实体来说,问题不大,我们可以直接忽略省份位。因为在同时一时间,同一地点,出现两个省份不同而其他位全相同的车的概率几乎为0。然后处理一下多个相似车牌的问题,实际上可以通过计算两个车牌之间的相似性来排除误检。还是基于之前那个假设,同一地点,同一时间出现AT95S5与AT9SS5的概率是非常小的,因此当判断出两个车牌的相似性很高时,我们可以认为一个车牌。总结一下处理流程,如下图所示:
成果展示
通过上面的策略,目前的统计已经比较准确。如下图所示。
总结
这期我们通过引入CTC技术,解决了车牌识别中的不定长问题(蓝牌7位,绿牌8位),并且利用了去重的后处理方案,使得在视频中,也能够稳定的统计蓝牌车和绿牌车的数量。下一期我们就去户外统计,看看到底有多少新能源车吧。敬请期待哦!
以上是关于我用AI回怼美女汽车销售系列[yolo车牌识别]的主要内容,如果未能解决你的问题,请参考以下文章