MODI中的OCR模块

作者:马健
邮箱:[email protected]发布:2012.07.02
更新:
2012.07.09
补充非简体中文版内容

自从基于MODI的DjVuToy、FreePic2Pdf、Pdg2Pic发布后,很多人就在问同一个问题:能不能在不装Office
2003/2007或SharePoint Designer 2007的情况下,让基于MODI的软件正常OCR?毕竟对于简体中文来说,就算只装SharePoint
Designer 2007中的MODI,也要近650 MB,装Office 2007的MODI则更夸张,要近1 GB。

想解决这个问题,需要从MODI中OCR模块的来历说起。在《用MODI OCR 21种语言》一文中已经说过,MODI其实只是封装了ScanSoft
API,而google(注意我说的是google,不是baidu)一下关键词“ScanSoft API”,可以发现两个网页:
http://www.corrupteddatarecovery.com/Products/ScanSoft-API.asp
http://www.corrupteddatarecovery.com/Products/Asian-OCR-for-ScanSoft-API.asp

从这两个帖子及其他一些相关信息推断,ScanSoft API封装了清华文通以支持亚洲语言,而MODI又在ScanSoft
API上封装出MODI接口,并在此基础上提供MODI应用(MSPVIEW.EXE),整个层次结构应该如下图所示:

——————           MSPVIEW.EXE
应用层                ┃
——————           
MODI接口
接口层                ┃
                 ScanSoft
API
             ┏━━━━━┻━━━━━┓
             ┃     ScanSoft
API亚洲语言支持(清华文通)
——————       ┃             

数据层      西欧11国、东欧3国、     亚洲语言文件
         俄、希、土语言文件    (简、繁、日、朝)

从上图看,如果只想调用MODI接口,不需要应用层的支持,可以有以下选择:

  1. 直接调用ScanSoft API。这个比较有难度,至少我到目前为止还找不到相关文档。
  2. 还是调用MODI接口,至少这个的文档是公开的。

所以上面的问题就转换成了:能否抽取出支持MODI接口的最小集合,实现OCR接口功能?

身为资深技术人员,对于这种问题的回答当然不能胡言乱语,而应该以实验为基础:

1、搞一个干净的XP SP3虚拟机,再复制一份,姑且命名为“虚拟机A”、“虚拟机B”。
2、在虚拟机A中安装InstallRite
2.5,用它监视安装SharePoint Designer
2007中的MODI。
3、安装完成后,用InstallRite导出安装后新的注册表,命名为aaa.reg。
4、将虚拟机A中的两个文件夹
C:\Program
Files\Common Files\Microsoft Shared\MODI
C:\Program Files\Common
Files\Microsoft
Shared\OFFICE12
复制到虚拟机B,并将aaa.reg导入虚拟机B。毕竟MODI接口是COM接口,与注册表无关的COM接口是不存在的。
5、运行DjVuToy、FreePic2Pdf或Pdg2Pic,可以验证在虚拟机B中能够用第三方软件正常OCR,只不过每OCR一页都要自动安装一次文件,似乎注册表中掺入了垃圾。

以上可行性实验清楚表明:
1、在不安装Office或SharePoint
Designer的情况下,可以通过复制相关文件和注册表项,为第三方软件提供OCR支持。
2、对于简体中文来说,单独安装Office
2007中的MODI需要约1 GB硬盘空间,单独安装SharePoint Designer 2007中的MODI则需约650
MB,而上面两个文件夹加起来也只有约76 MB,何况中间还有水分可挤,空间的节省还是很可观的,所以这笔买卖做得过。

无聊但又必不可少的理论扯完了,下面开始进入实战:哪些文件和注册表项才是必不可少的?

先说文件。上面两个URL中的内容,其实已经说明了接口层中ScanSoft API所需的文件,剩下需要解决的就是MODI接口部分的文件。

在第三方软件中调用MODI接口的初始化代码为:
IDocument
doc;
doc.CreateDispatch(_T("MODI.Document"));

在注册表中搜索字符串“MODI.Document”,可以知道此COM对象对应的DLL是MODI安装文件夹下的MDIVWCTL.DLL。再看一眼VC++的Debug窗口,可以知道在调用此DLL后,还接着调用了同文件夹下的MSPGIMME.DLL、MSPCORE.DLL,及OFFICE12文件夹下的MSO.DLL等。从文件属性看,这些文件都是微软鼓捣出来的,因此可以认为是接口层中MODI接口部分的东西。

从VC++的Debug窗口输出信息看,除了上述DLL文件外,OCR过程中还加载了MODI安装文件夹下的XOCR3.PSP、THOCR.PSP、XFILE.PSP。这3个文件虽然扩展名是PSP,但其实是DLL文件,从文件属性看属于ScanSoft
API的范畴,可以看作是对上面两个URL中内容的补充。

另外VC++的Debug窗口中还记录到OCR过程调用了OFFICE12文件夹下的OGL.DLL、MSORES.DLL、2052\MSOINTL.DLL,但在后来的回归性测试中证明,在对注册表项进行简化后,这几个文件没有也没关系。

结合上面分析,及《用MODI OCR 21种语言》中的相关信息,可知要OCR简体中文、英语,至少需要的文件如下表所示,加一起也就约30
MB。其中“说明”部分的英文是从DLL文件的文件属性中复制过来的,中文是我自己加的;数据层的数据文件是用文件监视器抓取的。

层次 文件名 说明
接口层 MODI MDIVWCTL.DLL Microsoft Office Document Imaging Viewer Control
MSPCORE.DLL Microsoft® Office Document Imaging Object Library
MSPGIMME.DLL Microsoft® Gimme library
OFFICE12\MSO.DLL 2007 Microsoft Office component
ScanSpft
API
BINDER.DLL XDoc Binder module for the ScanSoft SDK
PSOM.DLL Component Management Module for PefectScan API
XIMAGE3B.DLL Image Processing Module for the ScanSoft SDK
XPAGE3C.DLL Page Management Module for ScanSoft SDK
XOCR3.PSP OCR Module for ScanSoft SDK
XFILE.PSP Asian OCR Module for ScanSoft SDK
THOCR.PSP Asian OCR Module for ScanSoft SDK
ScanSoft
API亚洲
语言
FORM.DLL Table Recognition for Asian OCR
REVERSE.DLL Reverse Video Detection for Asian OCR
THOCRAPI.DLL Asian OCR API
TWCUTCHR.DLL Character Segmentation for Asian OCR
TWCUTLIN.DLL Line Segmentation for Asian OCR
TWLAY32.DLL Layout Analysis for Asian OCR
TWORIENT.DLL Orientataion Detection for Asian OCR
TWRECC.DLL Chinese Recognition for Asian OCR
TWRECE.DLL English Recognition for Asian OCR
TWRECS.DLL Punctuation Recognition for Asian OCR
TWSTRUCT.DLL Document Structure Processing for Asian OCR
数据层 英文 LATIN1.SHP 西欧11国(含英文)通用特征库
CharSetTable.chr 字符编码转换表,文本文件
ENGLISH.LNG 英文语言文件
简体中文 ENGDIC.DAT 清华文通的英文字典文件,貌似它也支持中、英文
ENGIDX.DAT 清华文通的英文索引
JFONT.DAT  
LOOKUP.DAT  
OCRHC.DAT  
OCRVC.DAT  
TWGB32.DLL Simplified Chinese code Conversion
SCCODE.UNI  
SCPRINT.DAT  
SCPRINT2.DAT  
SCSERHT.DAT  
SCTREE.DAT  
TW_GU.DAT  
TW_UG.DAT  

如果还想增加对其他语言的OCR能力,可以参阅《用MODI OCR 21种语言》,增加相关语言对应的文件。

另外在上表中,在PSOM.DLL文件描述中出现了一个新的名字:PefectScan API。google了一下,找到其官网http://perfectscan.com/,从介绍上看是做图像处理的:
PerfectScan is an
image processing program that automatically analyzes an image, then makes
adjustments to that image rendering a black and white image that contains all
viewable data as if it were a gray scale scan, only at 15% of the size of a gray
scale image.
看来MODI还真是一个大杂烩。不过PefectScan官网上的一句话,感觉道尽了程序员的悲凉:
We built the
software after 10 years of hard work, now all we have to do is build the
website...OOPS!!

言归正传。搞定文件后,还需要搞定注册表项才行。与MODI相关的注册表项包括两个部分:COM相关与Office相关。

COM相关就是与MODI的COM组件相关的注册表项,这个直接用regsvr32导入即可:启动命令行,进入MODI安装文件夹,执行下面的命令:
regsvr32
MDIVWCTL.DLL
regsvr32 MSPCORE.DLL
即可完成MODI COM组件的注册。

但与Office相关的注册表项就没那么好搞定了。我曾经试过用注册表监视器对OCR过程进行监视,结果发现真相淹没在了细节的海洋里。最终不得不采用了一个笨办法:专门写了一套测试软件,在前面的可行性实验中搭建的虚拟机B里猛跑,逐一尝试删除从aaa.reg中导入的注册表项,每删除一项就检查一下对OCR会不会造成影响。最终试出来约20个注册表项是必不可少的,其中近一半与前面用regsvr32注册COM组件时自动插入的注册表项重复。

最终经过手工调整后,确认在上面表格所列文件及COM注册基础上,再增加下列注册表项即可正常用第三方软件在简体中文环境下OCR简体中文、英文:

[HKEY_CLASSES_ROOT\Installer\Components\61BA386016BD0C340BBEAC273D84FD5F]
"2052"=hex(7):76,00,55,00,70,00,41,00,56,00,53,00,2e,00,7d,00,58,00,25,00,21,\
00,21,00,21,00,21,00,21,00,4d,00,4b,00,4b,00,53,00,6b,00,4f,00,43,00,52,00,\
5f,00,32,00,30,00,35,00,32,00,3c,00,00,00,00,00

[HKEY_CLASSES_ROOT\Installer\Features\00002109F10040800000000000F01FEC]
"OCR_2052"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\00002109F10040800000000000F01FEC\Features]
"OCR_2052"="%mEMae,7q9*[email protected]="

[HKEY_CLASSES_ROOT\Installer\Products\00002109710000000000000000F01FEC]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\3F745FF6A76FF2F4797DB74FC7B3FD8B]
"00002109710000000000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\MODI\\12.0\\XPAGE3C.DLL"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\4080B9FA1A0BBF34FB7813E87159FC64]
"00002109F10040800000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\MODI\\12.0\\SCCODE.UNI"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\48AD0082D02B3D24C9A56FA50728CCAB]
"00002109710000000000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\MODI\\12.0\\MSPCORE.DLL"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\D94C8360B8BB1DC41B1950E0F8237563]
"00002109710000000000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\OFFICE12\\MSO.DLL"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\00002109710000000000000000F01FEC\InstallProperties]
"WindowsInstaller"=dword:00000001

前三项的语言编码2052对应简体中文,但只要文件不缺,OCR中文、英文或其他语言都没有问题。不过在面对其他国家的用户时,解释采用简体中文的语言编码还是有点费劲,所以仍然需要继续尝试其他语言编码。

把两个虚拟机复原,重复上面可行性实验步骤:在虚拟机A中监视安装英文版SharePoint Designer
2007(安装后支持英、法、西班牙语),导出安装后的注册表和文件到虚拟机B,用同一套测试软件进行检查,出来的是不是与英文语言编码1033相关的注册表项呢?错,大错特错,跑出来不能删的是与法语(语言编码1036)相关的注册表项:

[HKEY_CLASSES_ROOT\Installer\Components\61BA386016BD0C340BBEAC273D84FD5F]
"1036"=hex(7):76,00,55,00,70,00,41,00,56,00,57,00,3f,00,57,00,41,00,24,00,21,\
00,21,00,21,00,21,00,21,00,4d,00,4b,00,4b,00,53,00,6b,00,4f,00,43,00,52,00,\
5f,00,31,00,30,00,33,00,36,00,3c,00,00,00,00,00

[HKEY_CLASSES_ROOT\Installer\Features\00002109F100C0400000000000F01FEC]
"OCR_1036"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\00002109F100C0400000000000F01FEC\Features]
"OCR_1036"=")aEMae,7q9*[email protected]="

[HKEY_CLASSES_ROOT\Installer\Products\00002109710000000000000000F01FEC]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\3F745FF6A76FF2F4797DB74FC7B3FD8B]
"00002109710000000000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\MODI\\12.0\\XPAGE3C.DLL"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\48AD0082D02B3D24C9A56FA50728CCAB]
"00002109710000000000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\MODI\\12.0\\MSPCORE.DLL"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\C040B9FA1A0BBF34FB7813E87159FC64]
"00002109F100C0400000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\MODI\\12.0\\FRENCH.LNG"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\D94C8360B8BB1DC41B1950E0F8237563]
"00002109710000000000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft
Shared\\OFFICE12\\MSO.DLL"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\00002109710000000000000000F01FEC\InstallProperties]
"WindowsInstaller"=dword:00000001

对比两个结果,可以看出:

  1. 与语言相关的注册表项共4项,其他注册表项都是相同的。
  2. 与语言相关的注册表项前3项直接用语言编码标识,第4项用语言文件标识,简体中文的文件是SCCODE.UNI,法语是FRENCH.LNG。
  3. 与语言相关的注册表项键值不是随便乱起的,是在产品基本键值(SharePoint
    Designer的基本键值是00002109710000000000000000F01FEC)的基础上,叠加相关语言编码(简体中文语言编码2052,十六进制0804,Intel表示为0408;法语语言编码1036,Intel表示为0C04)。敢这么玩GUID的我就见过这么一个,别人似乎都没这胆子。
  4. 不管采用什么语言,都可以只有一种语言,但这种语言不能是英语(语言编码1033)。

为了验证第4点,我从虚拟机A中手工导出英语相关注册表项,在虚拟机B中把与法语相关的注册表项全部换成英语的,结果OCR失败。与英语相关的4个注册表项为:

[HKEY_CLASSES_ROOT\Installer\Components\61BA386016BD0C340BBEAC273D84FD5F]
"1033"=hex(7):76,00,55,00,70,00,41,00,56,00,54,00,28,00,38,00,41,00,24,00,21,\
00,21,00,21,00,21,00,21,00,4d,00,4b,00,4b,00,53,00,6b,00,4f,00,43,00,52,00,\
5f,00,31,00,30,00,33,00,33,00,3e,00,26,00,61,00,45,00,4d,00,61,00,65,00,2c,\
00,37,00,71,00,39,00,2a,00,44,00,58,00,64,00,55,00,40,00,45,00,50,00,69,00,\
3d,00,00,00,00,00

[HKEY_CLASSES_ROOT\Installer\Features\00002109F10090400000000000F01FEC]
"OCR_1033"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\00002109F10090400000000000F01FEC\Features]
"OCR_1033"="&aEMae,7q9*[email protected]=OFu[`t.WO9zoh+x^{BHE"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\9040B9FA1A0BBF34FB7813E87159FC64]
"00002109F10090400000000000F01FEC"="C:\\Program
Files\\Common Files\\Microsoft Shared\\MODI\\12.0\\ENGLISH.LNG"

因此对于国内的用户,直接上简体中文的注册表项就好;对于国外的用户,如果对简体中文解释起来比较麻烦,就上法语或其他语言的注册表项吧
。但注意一次只能上一种语言,而且不能是英语。如果在上了一种语言的注册表项的基础上,再画蛇添足上英语的注册表项,会有问题:由于前面对文件和注册表项进行了精简,在OCR时MODI组件如果发现有英文的注册表项,
就会尝试恢复被精简的文件,造成OCR速度缓慢。

当然不论是哪一种语言,在导入x64 Windows时,都要注意x64下32位软件对应的Program Files文件夹多了一个后缀,改叫Program
Files (x86)了。另外在理论上Program
Files文件夹也是可以不在C盘上的,所以最保险的方法是通过环境变量CommonProgramFiles、CommonProgramFiles(x86),或SHGetFolderPath等SDK函数获取实际文件夹名称。

另外一个容易被问到的问题是:貌似导入的注册表项中包含了文件路径,那么能不能通过改注册表项的方法,改变MODI的安装路径,不装到CommonProgramFiles文件夹下?答案是:不行。事实上,InstallRite
2.5导出的aaa.reg文件中的原始注册表项里,路径名中是含有非法字符(问号)的,但并不影响使用,所以我怀疑文件夹是被写死在MODI代码里的。

总之,上面说的都是在没有安装Office
2003/2007的情况下的不得已方法,如果已经装了,不仅节省不了多少空间,而且可能会出现文件或注册表项的冲突。

(完)

时间: 2024-10-12 06:45:47

MODI中的OCR模块的相关文章

[转老马的文章]MODI中的OCR模块

作者:马健邮箱:[email protected]发布:2012.07.02更新:2012.07.09补充非简体中文版内容 自从基于MODI的DjVuToy.FreePic2Pdf.Pdg2Pic发布后,很多人就在问同一个问题:能不能在不装Office 2003/2007或SharePoint Designer 2007的情况下,让基于MODI的软件正常OCR?毕竟对于简体中文来说,就算只装SharePoint Designer 2007中的MODI,也要近650 MB,装Office 2007

Python中的random模块,来自于Capricorn的实验室

Python中的random模块用于生成随机数.下面介绍一下random模块中最常用的几个函数. random.random random.random()用于生成一个0到1的随机符点数: 0 <= n < 1.0 random.uniform random.uniform的函数原型为:random.uniform(a, b),用于生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限.如果a > b,则生成的随机数n: a <= n <= b.如果 a <

[转]nodejs中的process模块--child_process.exec

1.process是一个全局进程,你可以直接通过process变量直接访问它. process实现了EventEmitter接口,exit方法会在当进程退出的时候执行.因为进程退出之后将不再执行事件循环,所有只有那些没有回调函数的代码才会被执行. 在下面例子中,setTimeout里面的语句是没有办法执行到的. 1 process.on('exit', function () { 2 setTimeout(function () { 3 console.log('This will not ru

有道词典中的OCR功能:第三方库的变化

之前有点好奇有道词典中的OCR功能,具体来说就是强力取词功能.我知道的最有名的OCR库是tesseract,这个库是惠普在早些年前开源的. 在用python做爬虫处理验证码的时候,就会用到这个库,对应的python封装版本名字叫pytesseract.在github上可以找到tesseract的源码. 不过,此前在有道词典安装之后的文件夹中,我并未找到tesseract库.直到最近,更新了有道词典,换了新版本,才意外在文件下找到一个名叫tessdll.dll的文件. 与此同时,我对照了一下旧版本

NS3之路---在NS3中添加openflow模块

如何在NS3中安装openflow模块 Note:目前NS3中虽然支持openflow(貌似仅为V0.89),但是并不支持外部控制器,仅使用内部封装的一个控制器(ofi::Controller). 模型描述 该模型依赖于建立一个外部的openflow switch库(Openflow software implementation distribution, OFSID),然后编译ns3封装器来调用该openflow库函数.ns3的封装源码位于“src/openflow/model”路径下. 设

学习笔记之卸载远程目标进程中的DLL模块(转)

学习笔记之卸载远程目标进程中的DLL模块 (2007-07-23 23:51:02) 转载▼ 学习笔记之卸载远程目标进程中的DLL模块2007/7/231.首先得把DLL模块中的线程结束使用CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);创建系统线程的快照然后用Thread32First()和Thread32Next()遍历系统中所有线程.将遍历到的线程保存到THREADENTRY32结构,然后判断结构中的th32OwnerProcessID成员是否与

python中查看可用模块

1.这种方式的问题是,只列出当前import进上下文的模块. 进入python命令行.输入以下代码: >>>import sys >>>sys.modules 2.在python命令行下输入: >>>help() help>modulespython中查看可用模块,布布扣,bubuko.com

在Pycharm编辑器中调用getpass模块

兴趣来潮想复习一下python中的getpass模块编辑器使用Pycharm很简单的代码写完执行不到输入部分代码如下 import getpass print("""  --------------------**************----------------- """) #ss=getpass.getpass('please The password:') p = getpass.getpass('input your passwor

python中动态导入模块

如果导入的模块不存在,Python解释器会报 ImportError 错误: >>> import something Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named something 有的时候,两个不同的模块提供了相同的功能,比如 StringIO 和 cStringIO 都提供了Strin