zoukankan      html  css  js  c++  java
  • 程序员调用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等也进行了相应的升级,并更新各自的使用说明文件,对此进行说明。

    (完)

  • 相关阅读:
    使用EF进行简单的增删改查
    观察者模式(委托事件的小应用)
    lambda表达式和表达式树
    socket知识总结
    xml读写Demo
    winfrom DataGridView Demo
    6月26号.NET面试题(程序题部分)只要做懂这3道题肯定能脱离菜鸟称号!
    多线程与异步编程知识简单总结
    15年6月14号面试中没有回答出来的问题
    2020.5.15记一次阿里电话面试经历
  • 原文地址:https://www.cnblogs.com/stronghorse/p/12302662.html
Copyright © 2011-2022 走看看