赛题理解
赛题是CV入门级赛题,通过街景字符识别来熟悉CV建模思路和竞赛流程。
目标为识别街景中的字符。
数据集样本展示如下:
评价指标如下:
主要考虑两种思路:
传统cv思路:先将图像二值化处理,然后做倾斜校正,根据投影做字符切割,根据0-9的字符的特征点与标准字符匹配来进行识别
深度学习思路:本题本质上是分类问题,需要对图片的字符进行识别。但是图像给定的数据及中不同图像中包含的字符数量不等。因此赛题难点在于对不定长字符进行识别,这区别于传统CV方法。
数据读取方法:
import matplotlib.pyplot as plt
import json
import numpy as np
import cv2
# 读取json文件---》json包读取
train_json = json.load(open('C:/Users/Administrator/Downloads/CVdataset/train.json'))
# 数据标注处理
def parse_json(d):
arr = np.array([
d['top'], d['height'], d['left'], d['width'], d['label']
])
arr = arr.astype(int) # 强制转换类型为int
return arr
# CV2读取图片,返回类型:ndarray:(height,width,channels)
img = cv2.imread('C:/Users/Administrator/Downloads/CVdataset/test/000000.png')
arr = parse_json(train_json['000000.png'])
plt.figure(figsize=(10, 10)) # 创建画布
# 显示原图的子图,subplot表示将位置划分为1*4的子图,该子图占第一个位置;arr.shape[1] = 1表示图中有一个数字
plt.subplot(1, arr.shape[1]+1, 1)
plt.imshow(img) # 展示原图,imshow的参数就是img矩阵
plt.xticks([]); plt.yticks([]) # 不显示坐标
for idx in range(arr.shape[1]):
plt.subplot(1, arr.shape[1]+1, idx+2) # 为图片中的数字创建画布子图
# 通过arr中标注好的数字的位置,将img切片并展示为图片形式。相当于是img[top:top+height, left:left+width]
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([])
Datawhale提供解题思路:
简单入门思路:定长字符识别
定长字符识别就是Google那篇文章的思路。将赛题抽象为一个定长字符识别问题,在赛题数据集中大部分图像中字符个数为2-4个,最多的字符 个数为6个。
因此可以对于所有的图像都抽象为6个字符的识别问题,字符23填充为23XXXX,字符231填充为231XXX。
经过填充之后,原始赛题变为6个字符的分类问题。在每个字符的分类中会进行11个类别的分类,假如分类为填充字符,则表明该字符为空。
这个入门思路比Google的论文更简化了一点,去掉了预测数字个数的输出,但这个是baseline,目的是给选手更多的发挥空间。
专业字符识别思路:不定长字符识别
在字符识别研究中,有特定的方法来解决此种不定长的字符识别问题,比较典型的有CRNN字符识别模型。
CRNN的结构是CNN-RNN-CTC,CNN提取特征,RNN预测出不太好的序列,CTC把不太准确的序列翻译成正确的词。详细可以看论文和大佬们的博客。
专业分类思路:检测再识别
这种思路就要用到目标检测了,Faster R-CNN、YOLO等方法。
为了得到更高精度的识别率, 必须使用更好的方法。