本文内容将对街景字符识别赛题的理解做相应记录,同时作为一个CV初学者,我也想借此练习一下撰写博客的能力,感谢批评指正。
1.赛题任务
本题以计算机视觉中字符识别为背景,要预测街道字符编码,采用SVHN数据集做一个简单的字符识别问题。
2.赛题数据
赛题用的是比赛给定的SVHN街道字符数据集,已进行匿名采样。训练集数据包括3W张照片,验证集数据包括1W张照片,每张照片包括颜色图像和对应的编码类别和具体位置。测试集包括4W张图片。
对SVHN数据集的进一步了解:
SVHN(Street View House Number)Dateset 来源于谷歌街景门牌号码,原生的数据集1也就是官网的 Format 1 是一些原始的未经处理的彩色图片,如下图所示(不含有蓝色的边框),下载的数据集含有 PNG 的图像和 digitStruct.mat 的文件,其中包含了边框的位置信息,这个数据集每张图片上有好几个数字,适用于 OCR 相关方向。
3.数据标签
Field | Description |
---|---|
top | 左上角坐标X |
height | 字符高度 |
left | 左上角坐标Y |
width | 字符宽度 |
label | 字符编码 |
字符的具体坐标如下所示:
在比赛数据(训练集、测试机和验证集)中,同一张图片中可能包括一个或多个字符,因此在比赛数据的json标注中,会有一个或多个字符的边框信息。例如:
图片的json标注:
可以看到,原始图片中有两个数字,因此在json标注中体现了两个字符的边框信息。
4.评测指标
选手提交结果与实际图片的编码进行对比,以编码整体识别准确率为评价指标。任何一个字符错误都为错误,最终评测指标结果越大越好,具体计算公式如下:
Score=编码识别正确的数量/测试集图片数量
5.读取数据
json中标签的读取方式如下:
import json
import cv2
import matplotlib.pyplot as plt
train_json = json.load(open('./input/train.json'))
# 数据标注处理
def parse_json(d):
arr = np.array([
d['top'], d['height'], d['left'], d['width'], d['label']
])
arr = arr.astype(int)
return arr
img = cv2.imread('./input/train/000000.png')
arr = parse_json(train_json['000000.png'])
## 原图读取
plt.figure(figsize=(10, 10))
plt.subplot(1, arr.shape[1]+1, 1)
plt.imshow(img)
plt.xticks([]); plt.yticks([])
## 数据标注区域图像
for idx in range(arr.shape[1]):
plt.subplot(1, arr.shape[1]+1, idx+2)
plt.imshow(img[arr[0, idx]:arr[0, idx]+arr[1, idx],arr[2, idx]:arr[2, idx]+arr[3, idx]])
plt.title(arr[4, idx])
plt.xticks([]); plt.yticks([])
6.解题思路
赛题的本质是分类问题,0-9十个字符为十个类别,但是问题在于数据集中的图片上不只是一个字符,有的字符个数为2,有的字符个数为3,有的字符个数为4,因此我们应该考虑的是对这种不定长的字符进行识别。
- 对于刚要入门的初学者,可以考虑入门版本的定长字符识别:
可以将赛题抽象为一个定长字符识别问题;本赛题数据集中大部分图像中字符个数为2-4个,最多字符 个数为6个。因此可以将问题都抽象为6个字符的识别问题,字符23填充为23XXXX,字符231填充为231XXX。
经过填充之后,原始的赛题可以简化了6个字符的分类问题。在每个字符的分类中会进行11个类别的分类,假如分类为填充字符,则表明该字符为空。
- 此外还有专业字符识别思路:不定长字符识别
字符识别研究中,有特定的方法来解决此种不定长的字符识别问题,典型的有CRNN字符识别模型。
在本次赛题中给定的图像数据都比较规整,可以视为一个单词或者一个句子。
3.专业分类思路:检测再识别
这就属于相对更高阶一些的思路了,首先将字符的位置进行识别,利用物体检测的思路完成。可以参考物体检测模型SSD或者YOLO来完成。
7.本章小结
作为一个初入门的CV学习者,可以从第一种思路开始,逐渐在学习过程中积累更多相关知识,从而尝试更多好用的算法。