汉字手写训练和识别

汉字手写训练和识别

一、简介
本文是属于手写体文字识别应用,旨在基于MindSpore AI计算框架和Atlas实现手写汉字拍照识别系统。该系统能够对写在纸上的多个汉字,使用摄像头拍摄视频,实时检测字符区域并给出识别类别。该系统包括手写汉字模型训练(云上)、模型转换、模型部署、摄像头图像采集、模型推理(端侧)、结果展示等完整训练和应用流程。其中模型采用的是深度神经网络,目前深度学习在文字识别方面有着广泛的应用,多分类问题是其中重要的一类。然而,深层网络模型的结构通常很复杂,对于一般的多类别分类任务,所需的深度网络参数通常随着类别数量的增加而呈现超线性增长。本文需要识别字库中字的类别数高达3755类,模型训练是整个流程中耗时最长且决定识别精度的重要环节,模型推理在识别流程中占据较大部分。所以这两个环节的速度和精度对于用户体验至关重要。如何研究高性能、高精度、实用性强的方案变得极具挑战性。

二、文开发目的和意义
手写汉字是几乎所有国人的最自然技能之一。日常生活中有很多场景需要对写在纸上的汉字进行识别或者录入电脑。如下图是一位同事咨询该字如何发音,如果能够识别,就能达到认识,的目的。

 

 生活中遇到的手写汉字  

本文是属于手写体文字识别应用,在华为云ModelArts平台上基于MindSpore AI计算框架进行手写汉字模型的训练,然后通过ATC模型转化工具和ACL接口,将模型部署到Atlas上,实现手写汉字拍照识别系统。该系统能够对写在纸上的多个汉字,使用摄像头捕获视频/图像,实时检测手写文字区域并给出识别类别。本文的单字版使用MindSpore AI计算框架在3755类手写汉字数据集上进行模型训练,然后将训练好的模型转换为Ascend310支持的离线推理模型,在华为Atlas上借助摄像头对少量手写汉字进行实时检测和识别,具有完整性、代表性和实用性,满足了在实际场景下用摄像头进行文字的拍照感知、实时检测和识别的需求。

三、系统设计
系统可以划分为数据处理、模型构建、文字实时感知等三个主要子系统,各子系统相对独立,但存在数据关联。其中数据处理包括手写汉字数据集划分、新数据集制作、图像增强等字符图像预处理;模型构建和训练包括网络定义、模型训练等模块;文字实时感知包括视频解析、单字检测、图像预处理和字符识别与展示。为了说明各模块之间的结构关系,细化的整体结构图如下图所示。系统的各模块将在给出系统整体设计流程之后进行详细介绍。

 

 

 

系统整体功能结构图


3.1 基于MindSpore的系统流程

整个系统流程分为两个阶段。训练阶段在HITHCD-2018数据子集上借助MindSpore生成定制版ResNet模型。推断阶段包括摄像头图像采集、字符检测、图像预处理、文字识别等模块,具体流程见下图所示。

 

 

 基于MindSpore训练的系统流程图


3.2 手写数据集
3.2.1数据集介绍
本文使用了HITHCD-2018数据集的子数据集。HITHCD-2018是哈尔滨工业大学收集的、用于手写汉字识别(HCCR)的大型数据库,有超过5346名书写者书写,目前规模最大、字类最多的数据库(Tonghua Su et al. HITHCD–2018: Handwritten Chinese Character Database of 21K-Category, ICDAR, 2019)。使用子数据集,共563,250个样本,覆盖了3755个类别的国标第一级字符(GB2312-1980 Level 1)。其中训练数据中为每个字符类提供了120个样本,测试集每类提供30个样本,后者可以用于超参数验证。

3.2.2数据集制作
在MindSpore中经常使用的数据类型是mindrecord,不是常见的jpg,jpeg,png,tif等格式。比起单张图片,,具有I/O效率高、支持多线程并发读写、节省内存、语义完全符合ACID性等特点。由于本文所用HITHCD数据集存储形式为gnt,需要对其进行格式转换,输出成mindrecord文件。gnt的存储形式如下图所示,前4个字节是当前图片所占的字节数,紧跟的2个字节是图片对应标签的ASCII编码,再往后4个字节分别是宽和高,最后是图片具体信息,如此往复。

 

gnt文件存储情况


生成mindrecord的流程如下图所示。为了更高效地制作数据集,在制作mindrecord之前,在buffer中先对图像进行打乱和预处理,预处理的具体操作将在后面板块介绍。得到已经预处理完成的gnt格式数据后,再使用tensorflow制作mindrecord数据集。

 

 

 制作mindrecord流程图


3.3 图像预处理
图像的亮度、对比度等属性对识别的影响很大,书写的同个汉字在不同环境下也有不同。然而,在识别问题中,这些因素不应该影响最后的识别结果。为了尽可能减少无关因素的影响,对原始数据进行了预处理和增强,提高了网络的泛化能力。该部分流程如下图所示:

 

 

 

 数据增强流程

大津法二值化主要是利用最大类间方差,将图片分为前景和背景两部分。本文中,目的是为了保持手写汉字灰度不变,将背景统一为纯白底色,增加识别的鲁棒性。调用threshold(img, img, 0, 255, THRESH_TOZERO | THRESH_OTSU)函数,可实现文需求。如示意图所示。

 

 

 大津法二值化效果图(左为原始图像,右为大津法校正图像)

灰度均衡法由Cheng-Lin Liu, Fei Yin等人在“Online and offline handwritten Chinese character recognition: Benchmarking on new databases”中提出,目的是为了尽可能使得训练样本汉字灰度值相近,提高识别的准确率。对于给定的像素值在0到255之间的汉字样本,首先进行灰度均值计算,若大于110,即样本图片更接近白色、笔画颜色偏浅,则对其进行笔画增粗、增黑,其前后效果如图所示。

 

 

 灰度均衡效果图(左为原始图像,右为灰度均衡校正图像)

对于给定的MindSpore网络,训练的样本需为统一尺寸。因此,在预处理过程中,还需要对汉字进行居中padding和大小归一化。该部分的主要步骤为:1.根据长宽比,将汉字resize到尽可能接近目标尺寸;2.采用邻接线性插值法,将样本padding为正方形。如图所示的“知”字,将原有68*72大小处理为了112*112的标准图片,并采用cvtColor(img, img, COLOR_GRAY2BGR)将其转为单通道,完成了整个预处理流程。

 

 

 居中padding及归一化示意图(左为原始图像,右为预处理后标准图像)


3.4 文字检测
针对onCameraFrame里内容进行单字检测,整个过程见文字检测流程示意图,关键步骤的效果见单字检测关键过程的示意图。首先考虑到摄像头中真实场景的复杂背景信息,以及OpenCV有限的区域提取能力,固定手写汉字颜色为红色,以简化轮廓提取难度。因为红色在BGR颜色空间是不连续的,将图片转为HSV颜色空间进行颜色过滤操作。具体做法为:首先接收摄像头发送的格式为YUV420SP的图片,对该图片转为BGR格式,转换后如图所示。

 

 

 文字检测流程

 

 

 (a) 原图

 

 

 (b) hsv图

 

 

 (c) 轮廓提取图

 

 

 (d) 轮廓膨胀图

 

 

 (e) 区域提取图

单字检测关键过程的示意图

 

接着使用H(170,180),S(100,255), V(100,255),做为颜色阈值对图像进行颜色提取,结果如图(b)和图(c)所示。随后使用OpenCV的膨胀方法对提取的文本区域进行膨胀处理,以便于更明显的区分文本区域和背景,结果如图(d)所示。接下来在膨胀后的图像上提取轮廓,并针对该轮廓求最小水平矩形。考虑到存在可能的误差区域以及一个字分成多个区域,使用轮廓间的相对距离(即轮廓间距离/图像对角线距离)进行是否属于同一区域的判断,具体做法是设定距离阈值,计算两两轮廓间距离除以图像对角线距离得到相对距离,该距离小于距离阈值时,属于同一区域,该距离大于等于距离阈值时,属于不同区域,最后使用交并集算法进行区域合并。然后设定面积阈值,计算合并后的每个水平矩形的面积,并除以图像面积得到相对面积,当相对面积在距离阈值区间时,判定为文字区域,否则,舍弃,最后返回标定的文字区域坐标范围。最后的提取区域如图(c)所示。

3.5文字识别
本节按照模型定义、上传数据、模型训练、过程展示、训练结果等多个方面展开。
3.5.1模型定义
文字识别部分采用ResNet-18来完成模型的学习与推断,的作用是用来对检测出来的文字进行分类,如图所示。

 

 

 ResNet-18网络结构图


3.5.2上传数据和脚本
Step1:选择华为云服务中的对象存储服务OBS
Step2:点击“创建桶”,根据需要选择不同计费标准

 

 

 Step3:OBS授权,参考链接: https://bbs.huaweicloud.com/videos/101366


3.5.3模型训练
Step1:选择华为云服务中的ModelArts,使用ModelArts控制台页面的训练作业功能(或者使用ModelArts Pycharm Tookit提供的训练作业功能)。
Step2:设置框架、代码目录、启动文件、数据存储位置和单卡多卡模式等参数,然后启动训练作业。

 

 

 3.5.4过程展示

在训练作业中打开作业,选择日志模块进行查看。若在本地配置了MindSpore,还可通过MindInsight可视化训练过程。

 

 

 ModelArts训练过程展示1

 

 

 ModelArts训练过程展示2

3.5.5训练结果
使用相同数据集,和TensorFlow进行精度和训练时长的对比如下图所示。

 

 

 与TensorFlow的精度和训练时长对比(TensorFlow使用GPU为TITAN X, MindSpore为V100)


网络训练完成后,可进一步导出为AIR(GEIR)或ONNX格式的PB模型,以便后续部署到Atlas或其,平台上进行推理。

input = np.random.uniform(0.0, 1.0, size=[1, 3, 112, 112]).astype(np.float32)
export(net, Tensor(input), file_name='/cache/ckpt/resnet.air', file_format='AIR')

 

3.6模型转换
要将训练好的MindSpore模型部署到Atlas上,首先要将其转换为Ascend 310 AI处理器支持的离线模型。使用ATC模型转换工具进行模型转换,转换代码如下。参数说明请查看ATC工具文档。

 

 

 模型转换时的关键配置

3.7推断时的数据结构设计
模型部署模块数据结构设计参考了人脸检测的数据类型,汉字识别在其基础上添加了如下数据类型:

// 每个汉字的矩形框
struct CRect {
hiai::Point2D lt; // left top
hiai::Point2D rb; // right bottom
};
// 每张图片的检测与识别结果
struct ImageResults{
int num;// 每帧图像中的汉字数量
std::vector OutputT output_datas;//每帧图像中汉字输出向量集合
std::vector <CRectrects>;//每帧图像中汉字的矩形框集合
};
// 多帧图像检测与识别结果集合
struct CEngineTransT{
bool status;
std::string msg; // error message
hiai::BatchInfo b_info;
std::vector <NewImageParaT> imgss;//每帧图像集合
std::vector <ImageResults> results;//每帧识别结果集合
};

 3.8部署流程设计

根据汉字检测与识别的需求,共设计了三个引擎模块,分别为摄像头模块、推理模块、后处理模块,部署流程图如图所示。摄像头模块与Camera驱动进行交互,设置摄像头的帧率、图像分辨率、图像格式等相关参数,从摄像头中获取YUV420SP格式的视频数据,每一帧传给推理引擎进行计算。以此工程为例,其中帧率fps为5,图像分辨率取1280x720,摄像头图像格式为默认的YUV420SP。推理模块接收摄像头数据,对YUV420SP格式的每帧图像进行以下两方面的处理:一方面将其转为RGB格式的图像,使用OpenCV对图像进行处理,检测出汉字的矩形框集合,接下来依次对每个汉字子图像通过模型进行推理,得到输出向量的结果集合;另一方面还需将每帧图像转换JPEG格式,以便于查看摄像头图像。将JPEG格式的每帧图像集合和每帧识别结果集合作为输入传给后处理引擎模块。后处理模块接收上一个引擎的推理结果与摄像头JPEG图像,将矩形框集合添加到Presenter Server记录检测目标位置信息的数据结构DetectionResult类中,作为摄像头图像的检测结果,通过调用Presenter Agent的API发送到UI Host上部署的Presenter Server服务进程。Presenter Server根据接收到的推理结果,求出汉字最大预测概率值所对应的索引,在索引表中查找对应汉字,在JPEG图像上进行汉字矩形框位置及汉字识别结果的标记,并将图像信息发送给Web UI。索引表为一个记录汉字与其对应索引值的表,为txt文件,在Ubuntu系统下以UTF-8的格式存储,其中每一行对应一个汉字。

 

 

 四、最终效果展示

最后,针对拍照识别的实际场景,进行了测试。硬件布局图如下图所示。

 

 Atlas与摄像头布局


最后,测算了系统的主要时间消耗情况。一帧图片的整图字符检测约60毫秒,识别阶段每个字的平均识别时间约为3毫秒。在光线稳定的情况下,单字识别准确率90%以上。

 

 

 五、后续可扩展性

本文聚焦于少量手写汉字的识别任务。后续可以扩展到包含复杂背景的大量手写汉字识别场景,比如手写作文文字的检测与识别等任务。

 

posted @ 2021-02-19 12:52  吴建明wujianming  阅读(1318)  评论(0编辑  收藏  举报