# 蒙古文书籍文字识别
本范例将使用OCR技术实现蒙古文书籍文字识别检测和识别,通过本章您可以掌握:
- 蒙古文的基本知识
- 如何制作蒙古文字典与合成数据
- 如何进行识别模型微调
本范例由内蒙古阿尔泰电子信息技术有限公司CTO欧日乐克、苏日图、达布希腊图、歆琪乐与飞桨联合打造
## 背景介绍
蒙古文文字识别技术在蒙古文信息处理领域成为一个亟待解决的问题。但由于诸多主客观原因,产品化蒙古文文字识别技术上有一段距离。而书籍的数字化是其中一项重要的课题,但因为涉及相关技术较多,难度较高,在整体上解决蒙古文书籍文字识别技术还不成熟。
![pic_script](https://user-images.githubusercontent.com/50011306/206182800-a3029f08-dece-4cbe-9298-a66eb413137a.jpeg)
*基本概念
```txt
字:即字符,不同于汉字的字(Character)一字一形,并包含字意,蒙古文的字类似于英语的
字母(Letter)是一种表音文字,但却拥有若干字形(Glyph),若干个字构成一个词。
名义字符:Unicode十大法则中规定,"Character is not Glyph"(字符不是字形)。
于是像蒙古文一样有形态变化的文字就有了一个字形代表其他形态的字形。该字形被记录在
Unicode基本表中并分配编码。如蒙古文 ᠠ([a]) 为 a 的独立形式,分配码位\u1820,
记作uni1820.isol,代表所有词首uni1820.init、词中uni1820.medi和词尾1820.fina形式。
变形显现字符:除名义字符外的其他没有实际编码位置的字形。在蒙古文文本中看到的字符皆为通过
Unicode Scripts Processor(简称USP)处理后显示出来的字符。
词:语言里最小的可以独立运用的单位,等同于英语的word,以空格分割的字符串。
```
### 项目难点
- 1.蒙古文字符的复杂性
一形多字
![pic2](https://user-images.githubusercontent.com/50011306/206182327-b4a888a6-e67e-4d87-992d-0ddb830de85f.png)
多字一形
![pic3](https://user-images.githubusercontent.com/50011306/206182335-25b8c657-98da-4532-ae7d-608608a8f047.png)
- 2.蒙古文排版方向(竖写、换行左->右)
书写方向与换行方向会影响识别后的排序以及文字方向。
![pic4](https://user-images.githubusercontent.com/50011306/206182347-c5e2525a-f1fd-4ee6-936c-946435b3fe6b.png)
- 3.蒙古文字宽、行宽的不一致性
![pic5](https://user-images.githubusercontent.com/50011306/206182391-431c2441-1d1d-4f25-931c-b0f663bf3285.png)
- 4.字符中的部件难以区分(MVS、NNBSP点的处理,以及合体字形)
蒙古文中有一些有关形态变化的控制字符,其中最频繁出现的有 Mongolian Vowel Separator
(MVS,\u180E),和 Narrow No-Break Space(NNBSP,\u202F)。该两个控制符正常
情况下在文本中是透明的,比空格窄,不能换行。MVS用于连接词干与词尾a、e元音,NNBSP则
用于连接词与词附加成分(可以理解成分写后缀)。MVS会引发双向形变,而NNBSP则会引发后位
形变。
此外,蒙古文中有一些字形为另一个字形的组成部件,导致识别时不好对应结果。
针对以上问题, 本例选用PP-OCRv3这一开源超轻量OCR系统进行蒙古文文本识别系统的开发。我们首先使用数据合成工具合成了250万数据,基于这部分数据进行训练,通过精准切除白色边缘,随机加入标点符号,调整评估集数据使识别精度提升至75.78%。效果如下:
| 策略 | 精度 %|
| :--------------- | :-------- |
| 合成数据训练 | 42.38|
| 优化合成训练 | 75.78|
具体流程为:
- 第一步,选取真实语料并校对,并把语料副本转换为非Unicode编码版本
- 第二步,选择多种字体生成,按行生成,生成时建议使用非Unicode字体生成
- 第三步,从真实的扫描文本图片中按行切割保存,并保证对每个图进行Unicode编码的标注
评估集数据均采用真实图片样本。
- 第四步,开始训练
- 第五部,识别文字
评估集数据的质量对模型的训练效率也起到很大的作用。
## 快速体验
### 环境搭建
本任务基于Aistudio完成, 具体环境如下:
- 操作系统: Linux
- PaddlePaddle: 2.3
- PaddleOCR: Release/2.5
- text_renderer: master
下载PaddlleOCR代码并安装依赖库:
```bash
git clone -b dygraph https://gitee.com/paddlepaddle/PaddleOCR
# 安装依赖库
cd PaddleOCR
pip install -r PaddleOCR/requirements.txt
```
### 模型推理
将下载或训练完成的模型放置在`PaddleOCR/output`下, 然后使用如下命令即可快速进行模型推理
```bash
python tools/infer_rec.py -c configs/rec/PP-OCRv3/multi_language/Mongolian_PP-OCRv3_rec.yml \
-o Global.pretrained_model=output/v3_Mongolian_mobile/best_accuracy \
Global.infer_img=doc/imgs_words/
```
## 数据准备
本项目从真实语料中生成250万张图片作为训练集。另外生成1万张图片作为验证集。
### 语料准备
蒙古文由于编码原因生成图片时不能直接用 Unicode 字符串生成。蒙古文 Unicode 的本质是音码,伴随复杂的形态变化,如果没有对应的复杂文本处理程序则只能显示蒙古文的名义字符,而非变形显现字符。
因此如果想生成蒙古文图片则需要: 1.调用Windows系统的 USP10.dll,2.用支持形码的字体生成。
本项目使用了第二种方案,即使用形码的字体生成图片,并对应 Unicode 标签。
直接使用 Unicode 生成的情况(字符会分开并以名义字符显示):
![pic8](https://user-images.githubusercontent.com/50011306/206183135-d8be1ff7-4e3b-404f-bf5c-c0b47d5d4718.png)
$$\mbox{左列为Unicode生成图片,右列为Unicode文本}$$
![pic9](https://user-images.githubusercontent.com/50011306/206183154-3aec2415-66fb-41b8-872d-49aad4b62113.png)
$$\mbox{左列为Unicode文本,右列为形码生成图片}$$
生成图片时建议将字符串长度保持在5个词(平均30个字符),否则训练较为困难。
### 图片处理
部分训练图片示例如下:
![pic6](https://user-images.githubusercontent.com/50011306/206182740-d7e38be8-e857-45a4-8639-2a8656c9f8e5.png)
为验证模型对实际图片的效果,验证图片采用了真实扫描图片。在扫描完整的页面后对
标签文件格式如下:
|数据集类型|数量|
|---|---|
|训练集| 250万|
|验证集| 1.1万|
数据文件结构如下:
```txt
PaddleOCRv3
├── train_data # 训练数据文件夹
│ ├── texts
│ │ ├── train1.txt # 生成的训练数据标签,与图片文档一一对应
│ │ ├── train2.txt
│ │ ├── train3.txt
│ │ ├── train4.txt
│ │ ├── train11.txt
│ │ ├── train20.txt
│ │ ├── train21.txt
│ │ └── train22.txt
│ ├── image1 # 生成的训练图片
│ ├── image2
│ ├── image3
│ ├── image4
│ ├── image11
│ ├── image20
│ ├── image21
│ └── image22
├── test_data # 验证数据文件夹
│ ├── test_data.txt # 验证数据标签
│ ├── 0 # 每个文件夹有34张图片
│ ├── 1
: :
: :
│ └── 409
```
### 制作字典
根据 Unicode 编码顺序制作一个包含所有蒙古文字符的文本字典,建议保存到./ppocr/utils/dict目录下面,并在yml文件中更改地址。
## 基于合成数据训练
### 模型训练和评估
准备好合成数据后,我们可以使用以下命令训练数据:
```bash
cd ${PaddleOCR_root}
python tools/train.py -c configs/rec/PP-OCRv3/multi_language/Mongolian_PP-OCRv3_rec.yml
```
如果想从断点继续训练:
```bash
cd ${PaddleOCR_root}
python tools/train.py -c configs/rec/PP-OCRv3/multi_language/Mongolian_PP-OCRv3_rec.yml \
-o Global.checkpoints=./output/v3_Mongolian_mobile/best_accuracy
```
可填各参数含义如下:
```txt
-c: 指定使用的配置文件,Mongolian_PP-OCRv3_rec.yml对应于OCRv3识别模型。
-o: 覆盖配置文件中参数
Global.pretrained_model: 指定使用的预训练模型
Global.checkpoints: 断点位置
Global.epoch_num: 指定训练的epoch数
Global.eval_batch_step: 间隔多少step做一次评估
Train.dataset.data_dir: 训练数据集路径
Train.dataset.label_file_list: 训练集文件列表
Train.loader.batch_size_per_card: 训练单卡batch size
Eval.dataset.data_dir: 评估数据集路径
Eval.dataset.label_file_list: 评估数据集文件列表
Eval.loader.batch_size_per_card: 评估单卡batch size
```
### 模型推测
训练好的模型推测如下:
```bash
python tools/infer_rec.py -c configs/rec/PP-OCRv3/multi_language/Mongolian_PP-OCRv3_rec.yml \
-o Global.pretrained_model=output/v3_Mongolian_mobile/best_accuracy \
Global.infer_img=doc/imgs_words/
```
## 用真实数据测试模型
训练完成后可以测试模型。可将测试图片指定到某文件夹:
```shell
PaddleOCRv3
├── doc
├── imgs_words
│ ├── arabic
│ ├── belarusian
│ ├── bulgarian
: :
: :
│ ├── mongolian # 在此放入真实蒙古文图片,一个图片一行
│ └── uyghur
```
快速推测
```bash
python tools/eval.py -c configs/rec/PP-OCRv3/multi_language/Mongolian_PP-OCRv3_rec.yml \
-o Global.checkpoints=./output/v3_Mongolian_mobile/best_accuracy
```
推测结果将被记录在predicts_ppocrv3_Mongolian.txt文件中。
```shell
PaddleOCRv3
├── output
│ ├── rec
│ │ └── predicts_ppocrv3_Mongolian.txt
│ └── v3_Mongolian_mobile
```
部分结果:三列分别为推测结果、真实标签、图片
![pic7](https://user-images.githubusercontent.com/50011306/206182924-57472dc7-fd74-4872-8466-15c05eeb369d.png)
## 总结
本例选用PP-OCRv3这一开源超轻量OCR系统进行蒙古文文本识别系统的开发。加入250万合成数据,在现有模型基础上进行微调,通过修正训练集,设定评估标准,最终将蒙古文识别精度从42%提升至75%。