作者:马健
邮箱:stronghorse_mj@hotmail.com发布: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*DXdU@EPi="

[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*DXdU@EPi="

[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*DXdU@EPi=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的情况下的不得已方法,如果已经装了,不仅节省不了多少空间,而且可能会出现文件或注册表项的冲突。

(完)

MODI中的OCR模块的更多相关文章

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

    作者:马健邮箱:stronghorse_mj@hotmail.com发布:2012.07.02更新:2012.07.09补充非简体中文版内容 自从基于MODI的DjVuToy.FreePic2Pdf. ...

  2. 如何在Meteor中使用npm模块?

    首先,请在AtmosphereJs上搜索有无相关的封装包.尽量采用已有的封装包,而不是自己封装. 有两种方法在项目中使用来自npm的模块. 封装为Meteor包并在项目中添加包.使用meteor cr ...

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

    Python中的random模块用于生成随机数.下面介绍一下random模块中最常用的几个函数. random.random random.random()用于生成一个0到1的随机符点数: 0 < ...

  4. Python中的logging模块

    http://python.jobbole.com/86887/ 最近修改了项目里的logging相关功能,用到了python标准库里的logging模块,在此做一些记录.主要是从官方文档和stack ...

  5. Chrome中的Device模块调式响应性设计

    Chrome中的Device模块调式响应性设计 阅读目录 启用Device模块 Device模块设置介绍 自定义预设介绍 查看media queries 触发触摸事件 回到顶部 启用Device模块 ...

  6. Python中的random模块

    Python中的random模块用于生成随机数.下面介绍一下random模块中最常用的几个函数. random.random random.random()用于生成一个0到1的随机符点数: 0 < ...

  7. 游戏中VIP会员模块的简单实现

    哈哈  今天周末有时间,再整理一篇博文上来,虽然已经不做游戏老长时间了,但还是要把以前做过的东西总结一下,借此可以回顾以前的东西,也可以分享给大家. 今天说一下游戏中VIP会员模块的实现思路.每款游戏 ...

  8. 浅析Python中的struct模块

    最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概了解了,在这里做一下简单的总结. 了解c语言 ...

  9. python中的StringIO模块

    python中的StringIO模块 标签:python StringIO 此模块主要用于在内存缓冲区中读写数据.模块是用类编写的,只有一个StringIO类,所以它的可用方法都在类中.此类中的大部分 ...

随机推荐

  1. Java代码使用正则验证和常用工具方法

    1.正则验证邮箱 public static boolean checkEmail(String email){ boolean flag = false; try{ String check = & ...

  2. 超时 CS-8610 中性笔

    超时 CS-8610 中性笔 最初觉得这款笔很简单,而且还认为有点丑,因为笔头比较短. 比较特别提这款中性笔比一般的中性笔要粗一点. 使用后才发现比其它的中性笔好用,因为笔杆粗,手感好,笔杆上并没有特 ...

  3. 自己写的highcharts级联(点击事件)

    $.fn.extend({ Zhu: function (option) { var id = $(this).attr("id"); $('#' + id).highcharts ...

  4. 机器学习:数据归一化(Scaler)

    数据归一化(Feature Scaling) 一.为什么要进行数据归一化 原则:样本的所有特征,在特征空间中,对样本的距离产生的影响是同级的: 问题:特征数字化后,由于取值大小不同,造成特征空间中样本 ...

  5. PAT L3-008. 喊山(BFS)C4 初赛30分

    喊山(30 分) 喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤.呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的. ...

  6. Oracle 高可用作业测试

    1.RAC 是一种: A 分布式数据库B 内存共享多节点数据库C 能够保护数据安全的架构 2.RAC 和CRS 的区别是: A 前者表示一种架构,后者是一套软件B 前者表示一套软件,后者是一种架构 C ...

  7. 单片机RS485通信接口、控制线、原理图及程序实例

    RS232 标准是诞生于 RS485 之前的,但是 RS232 有几处不足的地方: 接口的信号电平值较高,达到十几 V,使用不当容易损坏接口芯片,电平标准也与TTL 电平不兼容. 传输速率有局限,不可 ...

  8. java selenium webdriver第二讲 页面元素定位

    自动化测试实施过程中,测试程序中常用的页面操作有三个步骤 1.定位网页上的页面元素,并存储到一个变量中 2.对变量中存储的页面元素进行操作,单击,下拉或者输入文字等 3.设定页面元素的操作值,比如,选 ...

  9. 获取Linux权限后安装rootkit

    1.首先获得远程服务器的root权限,当然这是基本的也是最难的. 2.然后下载rootkit程序,本文用到的是mafix. 3.开始安装 wget http://godpock.googlecode. ...

  10. 【Android 多媒体应用】使用 VideoView 播放视频

    1.MainActivity.java import android.os.Bundle; import android.support.v7.app.AppCompatActivity; impor ...