说明
ocr的用途还是比较广的,可以将大量的图片转为文字。如果从NLP的角度来说,这算是数据的清洗和提取吧。本篇使用cnocr做一些简单的应用。
内容
1 关于数据处理
使用深度学习来识别字符,哪怕是手写字符也有不低的成功率。但是这个前提是图片是规整的,干净的。通常我们获得的图片格式比较多,所以第一步事实上是要索引蕴含相关目标的图片区域。所以,类似时间序列的分割,或者是数据表格的分割,机器学习的第一步总是把要关注的点放在合适的尺度上。
所以,通用的OCR处理方案(甚至是其他的图像识别方案)应该都是:
- 1 目标发现/图像分割:将原始图片分割成几部分,或者从中间抠出我们认为蕴含信息的部分,这就是入模原始数据
- 2 入模原始数据分割:数据的再分割,将识别的主要部分再进行切割,形成若干部分。这一步有时候可以不必做。
- 3 数据清洗:将待处理的数据进行必要的处理,包括不限于形状纠偏(仿射变换),噪点处理,边缘锐化/钝化等
- 4 训练/测试:训练产生了模型文件,测试时则是调用形成的模型文件进行预测
- 5 评估:评估模型的有效性
通常来说,数据的预处理是非常关键的,真的到了模型部分反而简单。
2 cnocr
这个包的效果还是不错的,用起来也比较省事。如果不是专门做ocr业务的,调这样的包就差不多了,把前面的数据预处理做的好一些就行了。
项目的介绍如下:
cnocr 是 Python 3 下的中英文OCR工具包,自带了多个训练好的识别模型(最小模型仅 4.7M),安装后即可直接使用。
cnocr 主要针对的是排版简单的印刷体文字图片,如截图图片,扫描件等。目前内置的文字检测和分行模块无法处理复杂的文字排版定位。如果要用于场景文字图片的识别,需要结合其他的场景文字检测引擎使用,例如同样基于 MXNet 的文字检测引擎 cnstd 。
本项目起源于我们自己 (爱因互动 Ein+) 内部的项目需求,所以非常感谢公司的支持。
2.1 安装
有一个接近70M的包,所以下载安装过程不会很快(大概几分钟吧)。
pip3 install cnocr -i https://mirrors.aliyun.com/pypi/simple/
项目对应的github地址,有兴趣的可以去看看,可以学到不少。
2.2 使用示例
from cnocr import CnOcr
ocr = CnOcr()
第一次示例化时,程序会自动从公网下载模型(估计是用wget
之类的方法,挺方便的)
- 第一张图片,官网提供的,可以看出来一些生僻字也可以识别
res = ocr.ocr('ptest1.jpg')
print("Predicted Chars:", res)
Predicted Chars: [['铑', '泡', '胭', '释', '邑', '疫', '反', '隽', '寥', '缔']]
- 第二张图片,主要是看中英文混杂的情况,可以看到大部分都对了,除了把O识别成了0
res = ocr.ocr('ptest2.png')
print("Predicted Chars:", res)
print('结果', ''.join(sum(res,[])))
---
虽然现在的对话机器人主要理解的还是用户的文本信息,但对图片(尤其是表情)、视频和语音的理解,也逐渐地会成为机器人的标配能力。理解图片的一种最简单的方式,就是识别图片中的文字,做这个事的技术主要有两种:0cR(0ptical character Recognition,光学字符识别),或者STR(Scene Text Recognition,场景文字识别)。0CR主要针对文字比较规范,没什么底色或底色单一的图片,类文字扫描后获得的图片,如:
- 第三张图片主要看一些特殊标点是否能识别,例如名字中间那个大圆点
res = ocr.ocr('ptest3.png')
print("Predicted Chars:", res)
print('Result:', ''.join(sum(res, [])))
Result: 迪丽热巴的全名叫迪丽热巴·迪力木拉提,当初她第一次在节目中说出自己全名的时候大家都震惊了
总体上使用起来还是很方便的,效果也不错。
补充一下
因为官网的使用没有介绍对于流文件的调用方法,我查了一下源码,发现预测函数入口是允许几种格式的:
- 1 文件路径字符串
- 2 mx.nd.NDArray(这个用不上)
- 3 np.array:所以如果是流文件,转为numpy array就可以了。
def ocr(self, img_fp):
"""
:param img_fp: image file path; or color image mx.nd.NDArray or np.ndarray,
with shape (height, width, 3), and the channels should be RGB formatted.
:return: List(List(Char)), such as:
[['第', '一', '行'], ['第', '二', '行'], ['第', '三', '行']]
"""
if isinstance(img_fp, str):
if not os.path.isfile(img_fp):
raise FileNotFoundError(img_fp)
img = mx.image.imread(img_fp, 1).asnumpy()
elif isinstance(img_fp, mx.nd.NDArray):
img = img_fp.asnumpy()
elif isinstance(img_fp, np.ndarray):
img = img_fp
else:
raise TypeError('Inappropriate argument type.')
一些对应的代码,这里又要注意,如果是png文件形状不太对,要转为rgb。
new_img = Image.open('ptest3.png').convert('RGB')
new_img_array = np.array(new_img)
res = ocr.ocr(new_img_array)
print("Predicted Chars:", res)
print('Result:', ''.join(sum(res, [])))