漢字手寫訓練和識別
一、簡介
本文是屬於手寫體文字識別應用,旨在基於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%以上。
五、后續可擴展性
本文聚焦於少量手寫漢字的識別任務。后續可以擴展到包含復雜背景的大量手寫漢字識別場景,比如手寫作文文字的檢測與識別等任務。