最近在做一个项目时,需要用到OCR识别技术,而且要求识别世界上大多数的常用语言,也要考虑一些小语种的识别。之前对这个领域比较默生,经过一番研究,发现目前比较成熟的能够识别多语言的OCR主要是有道和百度在线的API调用方案,识别中文、英文等还是可以的,但是不能识别一些纵向的排版,另外对于一些小语种的识别不提供支持。
业界有一个叫做tesseract的OCR开源产品,最早是由惠普开发,后来开源之后由谷歌在持续维护,号称可识别100多种语言,对于印刷体的识别效果比较好,虽然对于中文等其他东亚语言的识别交易不是很理想,但是这个开源框架除了提供基本的识别功能外,最重要的是也提供一套优化训练的方案,可通过训练提升识别的效果。而且它最新的4.0版本也支持比较新的机器学习算法,它采用的是LSTM算法,训练的框架也都已经搭好,自己不用做特别多的工作,对于OCR和深度学习零知识,也可按照所提供的步骤开始起来。
Tesseract框架本身是C++开发的,但是项目通过Java语言调用时,一般还要用到另外个开源项目tess4j,这个项目已经把对tesseract API的调用做了完善的封装,可快速实现java语言的OCR方案。然而,真正跑起来这个tess4j将两个项目配合起来,还是折腾了好几天,里面有个大坑,主要是在macOS上面运行时,在windows和linux上面好像没有什么问题。按照两个项目上的wiki文档运行起来,发现只能跑英文等其他字母语言的识别,中文、日文等其他东亚语言,都跑不起来,报如下错误,程序直接崩溃,
Failed loading language 'jpn'
Tesseract couldn't load any languages!
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00000001259222d7, pid=83872, tid=0x0000000000001903
#
# JRE version: Java(TM) SE Runtime Environment (8.0_172-b11) (build 1.8.0_172-b11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.172-b11 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C [libtesseract.dylib+0x202d7] tesseract::Tesseract::recog_all_words(PAGE_RES*, ETEXT_DESC*, TBOX const*, char const*, int)+0x607
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Volumes/Data/workspace/huifng/ocr/hs_err_pid83872.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
经过长时间的baidu, overstack和查看两个项目中的issue,发现有人很早之前也遇到这个问题,也是中macOS上出现问题。有个找到根本原因是由于mac系统上面locale的问题,有的对代码比较熟悉的人直接修改代码解决;有个workaround是针对python语言调用tesseract的,是调用Sys.setLocale方法,参照这个思路,在idea环境中,在运行项目时,增加环境变量LC_CTYPE=C,最终解决问题。再使用任何语言时都不会再报错了。