程序员调用MODI的正确姿势

程序员调用MODI的正确姿势

作者:马健
邮箱:stronghorse_mj@hotmail.com
主页:http://www.comicer.com/stronghorse
发布:2020.02.13

Q:MODI是什么?
A:MODI全称Microsoft Office Document Imaging,是微软Office 2003/2007所带的光学字符识别(OCR)组件,支持对21种语言进行OCR。其中对于中日韩(CJK)的支持基于清华文通,对其他语言的支持基于ScanSoft。

Q:为什么要使用MODI?
A:因为这是目前世上唯一的一款能够在本地免费调用的商业级OCR引擎。只有实际使用过后,你才会明白那些业余的OCR引擎是多么的不靠谱,而商业版的Abbyy之流都是要真金白银的。单独安装MODI的方法有两种:

  1. 采用微软官方提供的方法:http://support.microsoft.com/kb/982760/
  2. 采用我山寨的独立安装包,只含引擎部分,不含其他,所以比微软方案占用的空间小得多。安装包可以从我网盘的OCR文件夹下载,解压后按照其中的安装说明操作即可。我的网盘地址在下面这个博客的置顶贴里提供:
    http://www.cnblogs.com/stronghorse/

Q:为什么说MODI是一个OCR引擎?
A:引擎的意思,就是说它只含有最核心的OCR功能,但不提供前处理和后处理,这些都要调用者自己解决:

  • 前处理:包括灰度/彩色图像转纯黑白(二值化)、去斑点等,目标是把需要喂给MODI进行识别的图像处理得干干净净,以提高识别成功率和准确率。ScanSoft还好说,清华的中文OCR部分比玻璃纸都脆弱,一言不合就崩溃给你看,尤其是在碰到图表的时候。即使是同一张灰度图,我都见过用Otsu二值化后用MODI识别没事,用八叉树二值化就造成MODI崩溃。当然结果完全反过来的我也不是没有见过。
  • 后处理:MODI结果是一个个word(中文是字),如果想得到有意义的结果,需要调用者自己根据word的坐标把word组成line,line组成paragraph。仅仅是判断word与word之间要不要加空格,估计就让不少人挠头皮了,何况中文还有横排、竖排。

所以说即使大家都调用MODI,但软件或者说软件开发者的前、后处理能力不同,出来的结果也会有所不同。比如说MODI识别中文时会有一些习惯性错误,如果软件内部的后处理部分能对这些错误进行修正,那么同一张图片的识别结果,就可能比别的没有进行修正的软件结果更好。而前处理部分的图像处理能力,甚至仅仅是采用不同的二值化算法,都会导致OCR结果和软件的稳定性不同。

Q:调用MODI有那些限制?
A:我用手上近40万页简体中文扫描图像进行了近两个月的反复测试(电费都花了好几百),其中大部分是扫描版技术书籍,图文混排的比例很高。测试后发现主要有以下限制:

  1. MODI是32位组件,嵌入32位EXE甚至32位DLL都没有问题,但嵌入64位EXE就不要想了。
  2. 如前所述,MODI在OCR含图表的中文图像时极其脆弱,崩溃是家常便饭。很多错误根本捕获不到就退出了,有一些则可以通过异常捕获抓到,但有时候的递归错误直接把堆栈耗尽了,这个时候什么样的错误捕获机制都不好使。另外即使捕获到了异常,但MODI是用C++开发的,没有自动垃圾回收机制,异常会造成内存漏洞,累积到一定程度除了杀进程之外也没有别的办法。
  3. 一次识别出来的中文字数如果不超过8个字,会直接报告说识别结果为空。

Q:这些限制要如何解决?
A:8个字的限制比较好办,把图像重复拼接,造成需要识别的字数超过限制即可。其他两个限制,尤其是错误处理方面,我在经过长期各种努力奋斗后,终于明白了前辈们总结的一个真理:线程是不安全的,但进程很安全。

具体来说,就是开发一个桥接器,在桥接器进程中嵌入、执行MODI调用。真正需要调用MODI进行OCR的软件自己不要嵌入MODI,而是与桥接器之间通过IPC(interprocess communications,进程间通信)进行交互——向桥接器发送OCR命令,桥接器接受后调用MODI进行OCR,再把OCR结果返回给调用者。

这样做的好处是:

  1. 如果OCR过程出错造成崩溃,崩溃的也只是桥接器进程,主进程P事没有,重启一个桥接器就可以进行下一页的OCR。
  2. IPC可以在32位进程与64位进程之间通信,所以桥接器没有办法只能是32位,但与桥接器通信的主进程可以是64位。IPC的具体说明见MSDN,有若干种技术可供选择,我选择的是最简单同时也是最麻烦的WM_COPYDATA。说它简单,是因为这项技术只是基于常规消息处理,不需要上多线程,而且数据一次就是完整的一批过去,不存在发送或接收不完整的问题。说它难,是因为如果对消息分发和处理机制理解不够,想纯靠消息就实现两个进程的同步,会很不容易。

所以从v4.00开始,FreePic2Pdf_Lib不再直接调用MODI,而是通过新增的桥接器MODI_Engine.exe进行调用。使用FreePic2Pdf_Lib+MODI生成双层PDF、双层DJVu的软件,包括DjVuToy、FreePic2Pdf、Pdg2Pic、UnicornViewer等也进行了相应的升级,并更新各自的使用说明文件,对此进行说明。

(完)

原文地址:https://www.cnblogs.com/stronghorse/p/12302662.html