文章目录
前面一篇文章介绍了利用PyTorch实现的MTCNN/LPRNe车牌识别的理论框架,但是光有理论还不行,这篇文章主要是对里面的一些具体细节进行阐述。
车牌识别整体流程:
- 获取图片
- PNet网络处理
- ONet网络处理
- STN网络处理
- LPRNet网络识别
- 解码网络输出结果
来个流程图就是:
接下来就详细的把这几个步骤的情况说明一下:
1.获取车牌图片
目前已知的公开的数据集,最大的就是CCPD数据集了。
CCPD(中国城市停车数据集,ECCV)和PDRC(车牌检测与识别挑战)。这是一个用于车牌识别的大型国内的数据集,由中科大的科研人员构建出来的。发表在ECCV2018论文Towards End-to-End License Plate Detection and Recognition: A Large Dataset and Baseline
https://github.com/detectRecog/CCPD
该数据集在合肥市的停车场采集得来的,采集时间早上7:30到晚上10:00.涉及多种复杂环境。一共包含超多25万张图片,每种图片大小720x1160x3。一共包含9项。每项占比如下:
CCPD- | 数量/k | 描述 |
---|---|---|
Base | 200 | 正常车牌 |
FN | 20 | 距离摄像头相当的远或者相当近 |
DB | 20 | 光线暗或者比较亮 |
Rotate | 10 | 水平倾斜20-25°,垂直倾斜-10-10° |
Tilt | 10 | 水平倾斜15-45°,垂直倾斜15-45° |
Weather | 10 | 在雨天,雪天,或者雾天 |
Blur(已删除) | 5 | 由于相机抖动造成的模糊(这个后面被删了) |
Challenge | 10 | 其他的比较有挑战性的车牌 |
NP | 5 | 没有车牌的新车 |
数据标注:
文件名就是数据标注。eg:
025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg
由分隔符-
分为几个部分:
-
025
为车牌占全图面积比, -
95_113
对应两个角度, 水平倾斜度和垂直倾斜度,水平95°, 竖直113° -
154&383_386&473
对应边界框坐标:左上(154, 383), 右下(386, 473) -
386&473_177&454_154&383_363&402
对应四个角点右下、左下、左上、右上坐标 -
0_0_22_27_27_33_16
为车牌号码 映射关系如下: 第一个为省份0 对应省份字典皖, 后面的为字母和文字, 查看ads字典.如0为A, 22为Y…
provinces = [“皖”, “沪”, “津”, “渝”, “冀”, “晋”, “蒙”, “辽”, “吉”, “黑”, “苏”, “浙”, “京”, “闽”, “赣”, “鲁”, “豫”, “鄂”, “湘”, “粤”, “桂”, “琼”, “川”, “贵”, “云”, “藏”, “陕”, “甘”, “青”, “宁”, “新”, “警”, “学”, “O”]
alphabets = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’, ‘Y’, ‘Z’, ‘O’]
ads = [‘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’, ‘O’]
-
37
亮度 -
15
模糊度
所以根据文件名即可获得所有标注信息。
2.MTCNN数据处理
数据处理并不简单,主要包含三个部分:
- 对数据处理输入进PNet网络
- 对数据处理输入ONet网络
2.1 PNet网络数据预处理
返回最终结果:三种图片路径(positive,negative,part)+ 类别(positive=1,negative=0,part=-1)+ 回归框偏移值。
具体(以一张图片为例):
- 获取一张图片(不限大小)
- 获取图片已经标记好的boxes坐标(左上,右下)
- 生成大量候选框
- 计算候选框与实际框的IOU值:
· 大于0.65,positive=1
· 大于0.3,negative=0
· 0.3~0.65,part=-1 - 计算回归框偏移量
- 分别保存裁剪后的图片
- 统一整合成最终的输出结果
以下是MTCNN当中PNet人脸数据生成参考代码,仅供阅读:
# coding:utf-8
import os
import cv2
import numpy as np
import numpy.random as npr
def IoU(box, boxes):
"""Compute IoU between detect box and gt boxes
Parameters:
----------
box: numpy array , shape (4, ): x1, y1, x2, y2
predicted boxes
boxes: numpy array, shape (n, 4): x1, x2, y1, y2
input ground truth boxes
Returns:
-------
ovr: numpy.array, shape (n, )
IoU
"""
# 函数的传入参数为box(随机裁剪后的框)和boxes(实际人脸框)
box_area = (box[2] - box[0] + 1) * (box[3] - box[1] + 1)
# 计算随机裁剪后的框的面积,因为传入的box是以x1, y1, x2, y2这样的数组形式,所以分别对应着左上角的顶点坐标和右下角的顶点坐标,根据这两个坐
# 标点就可以确定出了一个裁剪框,然后横纵坐标的差值的乘积就是随机裁剪框的面积,
area = (boxes[:, 1] - boxes[:, 0] + 1) * (boxes[:, 3] - boxes[:, 2] + 1)
# 同上,得出的是实际的人脸框的面积,但是这里要注意一点,因为一张图片的人脸是一个或者多个,所以说实际的boxes是个n行4列的数组,n>=1,n表示实
# 际人脸的个数。故这里用到了boxes[:,2]-boxes[:,0]这样的写法,意思是取出所有维数的第3个元素减去对应的第1个元素,然后加上一,这样就把n个人
# 脸对应的各自的面积存进了area这个数组里面
xx1 = np.maximum(box[0], boxes[:, 0]) # 将随机裁剪框的x1和各个人脸的x1比较,得到较大的xx1
yy1 = np.maximum(box[1], boxes[:, 2]) # 将随机裁剪框的y1和各个人脸的y1比较,得到较大的yy1
xx2 = np.minimum(box[2], boxes[:, 1]