OCR的全称是Optical Character Recoginition,光学字符识别技术。目前应用于各个领域方向,甚至这些应用就在我们的身边,比如身份证的识别、交通路牌的识别、车牌的自动识别等等。本篇就先讲一下基于开源软件和大厂服务的文字识别效果,后续会陆续讲解一下机器学习和深度学习实现的方案和原理,敬请期待吧。
还记得前一阵某小盆友拿过来一个全是图片的ppt,让我把里面的文字给抠出来(我当时很震惊!!!),随后在网上随便找了个OCR的在线文档转换软件,就给转过来了——这里面用到的技术就是OCR文字识别,所以本篇就带大家宏观上了解一下文字识别的技术方案与实现过程。
更多内容参考——我的AI之路
实现方案 1 大厂调包
有需求的地方就有市场,文字识别也不例外,很多大厂都提供了对应的服务,按照调用次数进行收费。比如网上找了一个产品服务的定价
可以看到,倘若你的服务只是偶尔用一次,完全可以使用这种体验型的免费服务。如果一天需要调用一万次,那么一个月基本的花费在5w左右——成本还是很高的,所以很多商用的场景大多都采用自主研发的方式来做。
如果使用这种大厂(我这里使用的讯飞),流程基本如下:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time
from urllib import request,parse
import json
import hashlib
import base64
import cv2
url = 'http://webapi.xfyun.cn/v1/service/v1/ocr/general'
x_appid = '5b4d9bbf'
api_key = 'a08332353b4df650842359129ffadb88'
param = {"language": "cn|en", "location": "true"}
x_param = str(base64.b64encode(bytes(json.dumps(param).replace(' ', ''),encoding='utf-8')),encoding = "utf8")
dict = {}
def main():
# 图片加载
f = open("名片.jpg", 'rb')
file_content = f.read()
body = parse.urlencode({'image': base64.b64encode(file_content)})
x_time = int(int(round(time.time() * 1000)) / 1000)
x_checksum = hashlib.md5((api_key + str(x_time) + x_param).encode("utf8")).hexdigest()
x_header = {
'X-Appid': x_appid,
'X-CurTime': x_time,
'X-Param': x_param,
'X-CheckSum': x_checksum
}
req = request.Request(url, data=body.encode("utf-8"), headers=x_header)
result = request.urlopen(req).read()
body = json.loads(result, encoding='utf-8')
img = cv2.imread('名片.jpg')
for text_line in body['data']['block'][0]['line']:
word = text_line['word'][0]
x1 = word['location']['top_left']['x']
y1 = word['location']['top_left']['y']
x2 = word['location']['right_bottom']['x']
y2 = word['location']['right_bottom']['y']
# 绘制文本框
cv2.line(img, (x1, y1), (x2, y1), (255, 0, 0), 2)
cv2.line(img, (x1, y1), (x1, y2), (255, 0, 0), 2)
cv2.line(img, (x1, y2), (x2, y2), (255, 0, 0), 2)
cv2.line(img, (x2, y1), (x2, y2), (255, 0, 0), 2)
# 输出对应文本
text = word['content']
print(text)
cv2.imshow('result', img)
cv2.waitKey(0)
if __name__ == '__main__':
main()
实现方案 2 基于开源软件tesseract实现
有的时候我们在写爬虫会遇到验证码校验的问题,这个时候使用大厂的接口就不现实了。验证码一般是数字+字母,因此识别起来复杂度不高,采用一些开源软件就能应付。说到开源软件,最有名的就是tesseract了,它目前由Google在进行维护,官方提供了3.05版本,貌似使用的还是传统机器学习的方式。
安装
安装的过程很简单,以我的mac为例,如果你只是想体验一下,那么可以使用下面的命令安装:
brew install tesseract
如果还想未来针对自己的使用数据重新训练,可以使用下面的命令安装(强烈推荐):
brew install --with-training-tools tesseract
如果不介意时间长一点,可以直接安装的时候下载所有的语言版本(不建议,因为语言包真的很大):
brew install --all-languages --with-training-tools tesseract
然后配置环境变量,比如vi ~/.bash_profile
增加下面的内容:
# 增加tesseract环境变量
export TESSERACT=/usr/local/Cellar/tesseract/3.05.02
export TESSDATA_PREFIX=/usr/local/Cellar/tesseract/3.05.02/share/
export PATH=$PATH:$TESSERACT/bin
然后执行source ~/.bash_profile
在命令行就可以使用tesseract了:
支持中文版本
如果想要支持中文,官方提供了语言包,可以去直接下载:
https://github.com/tesseract-ocr/tesseract/wiki/Data-Files#data-files-for-version-304305
这里3.04和3.05是通用的,下载后使用-l命令切换语言版本即可。
正常在使用tesseract的时候都会基于第三方的易用的接口来用
tesseract的自定义语言训练
另外tesseract对中文的支持还不是很好,如果想要优化可以使用jTessBoxEditor。
http://www.softpedia.com/get/Multimedia/Graphic/Graphic-Others/jTessBoxEditor.shtml
首先需要把图片转成tiff格式,这样它才能记录一些box的信息。
然后打开JTessBoxEditor对图片进行合并:
合并后得到一个新的tif图片
然后基于tesseract打上box信息
tesseract tg.font.exp0.tif tg.font.exp0 -l chi_sim batch.nochop makebox
随后再打开jTessBoxEditor,点击Box Editor,加载tif文件
针对生成的结果进行文字的重新编辑和调整。然后在图片目录下创建一个font_properties的字体文件,里面的内容为:
>cat font_properties
font 0 0 0 0 0
echo "训练"
tesseract tg.font.exp0.tif tg.font.exp0 nobatch box.train
echo "生成字符集"
unicharset_extractor tg.font.exp0.box
mftraining -F font_properties -U unicharset -O tg.unicharset tg.font.exp0.tr
echo "聚类"
cntraining tg.font.exp0.tr
echo "重命名"
cp normproto tg.normproto
cp inttemp tg.inttemp
cp pffmtable tg.pffmtable
cp shapetable tg.shapetable
cp unicharset tg.unicharset
echo "创建tessdata"
combine_tessdata tg.
echo "拷贝traineddata"
cp tg.traineddata /usr/local/Cellar/tesseract/3.05.02/share/tessdata/tg.traineddata
然后重新进行文字识别,可以看到刚才识别错误的 “辑”字正确了:
本地搭建好tesseract,可以使用一些第三方的工具包来调用,还是很方便的。