Tesseract OCR在VS2015下编译WIN32动态库,含lib/dll/include完整C++开发库
简介面向Visual Studio 2015和Windows 32位平台的Tesseract OCR动态库属于C开发集成包帮助开发者跳过源码编译直接嵌入OCR能力适合桌面工具中的扫描件识别、图片文字提取等场景。压缩包共577个文件、约5.38MB包含270个头文件、274个源文件、10个动态库、1个静态库及部分构建脚本头文件对应Tesseract与Leptonica的API定义动态库和静态库分别承担运行时与链接所需目录按include、lib、bin等层次组织。已有599人学习下载说明其在同类资源中使用门槛低、复用价值高除编译产物外还附带源码与构建脚本便于深入查看识别流程、调整参数或处理依赖异常。总体来看这套库能显著缩短C项目接入OCR功能的周期适合教学演示、快速原型到实际应用的多类需求。tesseract VS2015WIN32编译的动态库含lib、dll、includeC开发库最近整理老项目把Tesseract OCR在VS2015下重新编译了一版WIN32x86动态库包含完整的lib、dll、include目录供C直接调用。折腾这个的人应该不少——官方Release版本不提供32位构建而且默认工具集是VS2017以上遇到老项目、老插件、工业软件二次开发分分钟卡死在兼容性上。这篇就把整个编译过程、细节参数、C调用示例和踩坑记录完整写出来给需要的人省点时间。先交代一下背景Tesseract是开源的OCR引擎目前主要活跃版本是4.x和5.x。官方GitHub Release页面只放出x64的安装包且默认使用Visual Studio 2017/2019工具集编译。如果你的开发环境是VS2015或者目标平台是WIN32 x86直接下载官方包会出现链接器报错、找不到库、运行时崩溃等一系列问题。所以自己从源码编译一个适配VS2015WIN32的动态库几乎是绕不开的一步。这篇内容适合三种人看一是跟我一样维护老项目的C开发二是要做32位插件比如炒股软件、Photoshop滤镜、老式工业上位机但需要OCR能力三是想在VS2015里跑通Tesseract但被官方构建卡住的新手。整个过程我已经跑通编译产物直接就能用。1. 为什么非要自己折腾VS2015WIN32编译1.1 官方构建的坑你下到的包可能根本用不了Tesseract的官方Release默认只提供x64版本而且从4.0开始官方构建环境已经迁移到Visual Studio 2017/2019。这意味着两件事第一如果你在VS2015里直接使用官方预编译的lib文件链接器会报版本不兼容最常见的错误是LNK2038检测到RuntimeLibrary不匹配这是工具集和CRT版本不一致导致的第二官方x64包在32位工程里根本无法使用符号导出、依赖库比如Leptonica、LibJpeg、LibPng、Zlib全都是按x64编译的。更隐蔽的问题是官方包使用的依赖库版本较新这些新版依赖可能使用了VS2017才支持的C特性比如std::filesystem、std::optional等库的某些实现。强行在VS2015下链接会碰到链接器找不到符号、C1001编译器内部错误等莫名其妙的问题。所以指望官网下个包直接用于VS2015WIN32基本行不通。1.2 哪些场景才真正需要WIN32版动态库如果只是新项目开发用64位完全没问题也不会有人折腾这个。但实际开发中WIN32需求其实非常常见。很多商业软件采用插件架构主程序是32位的插件必须编译成x86进程内加载比如通达信选股插件、Photoshop滤镜、老式工控软件等都强制要求32位DLL。另一个典型场景是历史遗留系统维护——有些公司十年前写的上位机软件仍然是32位新需求要加OCR识别不能把整个系统重写只能做一个32位DLL嵌入进去。此外有些行业SDK本身只有32位版本比如某些读卡器、扫码枪、身份证识别仪厂商提供的SDK是老接口整个项目被迫停留在WIN32平台OCR部分也必须跟着用32位库。如果你的项目属于上述任何一种自己编译一套VS2015WIN32的Tesseract动态库就成了刚需。2. 编译前的环境准备与版本选型2.1 工具链清单编译Tesseract本身并不复杂但依赖比较多先列一个完整的工具清单工具/组件版本建议说明Visual Studio2015 Update 3必须装C工具集Update 3修复了大量C17兼容性问题CMake3.10以上建议3.20Tesseract 4.x要求CMake 3.105.x要求更高Git最新版即可拉取源码和依赖CPPAN1.0以上Tesseract从4.0开始用CPPAN拉取Leptonica和图像处理依赖7-Zip任意版本解压源码包非必需但推荐注意VS2015自带的CMake版本一般较低建议直接去CMake官网下载最新版在命令行里手动指定路径避免用VS内部的CMake。2.2 版本选择4.x还是5.x这是个关键问题Tesseract 5.x需要Visual Studio 2017以上的编译器因为它使用了较新的C标准库特性VS2015无法满足。所以VS2015环境只能选择Tesseract 4.1.x这是4系列的最后一个稳定版本OCR识别率对大多数场景完全够用且对老工具链兼容性最好。我选择了Tesseract 4.1.1做基准搭配对应的Leptonica 1.78.0版本。这里的坑点在于Tesseract源码通过CPPAN拉取依赖时默认拉取的是小版本范围内的最新依赖如果依赖太新可能间接引入VS2015无法编译的代码。稳妥的做法是不要用CPPAN自动拉取而是手动下载指定版本的依赖源码通过CMake变量指定路径。另外需要提前确认如果你的项目在VS2015中设置了字符集为Unicode编译动态库时也必须保持一致如果工程用了/MT静态CRT动态库用/MD连接时会直接报错。这些细节在后面章节详细展开。2.3 目录结构规划编译前先规划好目录避免后面路径混乱。我个人习惯这样放C:\workspace\ ├── tesseract-4.1.1\ # Tesseract源码 ├── leptonica-1.78.0\ # Leptonica源码 ├── 3rdparty\ # 第三方依赖jpeg、png、tiff等 ├── build-tesseract\ # CMake构建目录 └── install-tesseract\ # 安装产物最终你要的lib/dll/include所有目录不要使用中文和空格CMake和C构建工具链对带空格的路径处理容易出各种奇怪问题。这一点非常关键。3. 动态库编译全流程实操3.1 源码获取与依赖处理使用Git拉取Tesseract源码并切换到4.1.1标签git clone https://github.com/tesseract-ocr/tesseract.git cd tesseract git checkout 4.1.1Leptonica推荐用1.78.0下载地址在GitHub的Leptonica仓库release页面。解压后放在预定的路径下。接下来处理第三方图像库依赖。Tesseract依赖LibJpeg、LibPng、LibTiff、Zlib。有两个方案方案一是用vcpkg编译这些库但vcpkg默认会生成较新版本的库可能与VS2015不兼容。方案二是直接从Tesseract官方源码里自动拉取Tesseract 4.1.1的CMakeLists.txt里已经定义了自动下载逻辑使用CPPAN如果网络环境允许CPPAN会自动下载依赖并编译比较省事。实际测试下来CPPAN在VS2015环境下自动拉取的依赖版本过新编译Leptonica时会遇到结构体成员无效等编译错误。所以我最终选择了手动下载依赖源码的方案。把Leptonica的Configure.cmake中对于JPEG、PNG、TIFF的检测选项关闭只保留核心图像读取能力cmake -DBUILD_SHARED_LIBSON -DJPEG_SUPPORTOFF -DPNG_SUPPORTOFF -DTIFF_SUPPORTOFF如果你不需要识别带颜色的复杂图片这样可以省去大量依赖编译时间。Tesseract本身转灰度图处理JPEG和PNG支持关闭后对纯文本扫描件、黑白截图识别完全没影响。如果确实需要彩色图片解码建议单独编译好jpeg/png/tiff的32位库后通过-DCMAKE_PREFIX_PATH指定。3.2 CMake配置核心参数逐个说明Tesseract从4.0起支持CMake构建。打开VS2015 x86 Native Tools Command Prompt切换到构建目录执行以下配置命令cmake ..\tesseract-4.1.1 ^ -G Visual Studio 14 2015 ^ -A Win32 ^ -DCMAKE_INSTALL_PREFIXC:\workspace\install-tesseract ^ -DBUILD_SHARED_LIBSON ^ -DLeptonica_DIRC:\workspace\leptonica-1.78.0 ^ -DCMAKE_CONFIGURATION_TYPERelease ^ -DCMAKE_PREFIX_PATHC:\workspace\3rdparty ^ -DBUILD_TRAINING_TOOLSOFF每个参数单独说明一下。-G Visual Studio 14 2015指定生成VS2015工程。VS2015对应的CMake生成器名称是Visual Studio 14 2015。不要用VS2017或VS2019的生成器否则生成的工程文件VS2015打不开这一步错了后面全白搭。-A Win32明确指定平台是x86不写这个参数默认生成x64工程。很多人在这一步漏了编译出来又是64位一个上午就白费了。-DCMAKE_INSTALL_PREFIX指定安装路径编译完成后执行cmake --install会把头文件、lib、dll、cmake配置拷贝到这里这就是我们要的含lib、dll、include的开发库。-DBUILD_SHARED_LIBSON表示生成DLL动态库如果设成OFF则生成静态库。考虑到使用方便优先动态库。如果你的项目要发布给第三方使用动态库更合适因为插件场景下DLL加载更灵活。-DBUILD_TRAINING_TOOLSOFF跳过训练工具构建那部分依赖大量额外库识别用不到只会增加编译时间。3.3 编译与安装亲测通过的操作步骤CMake配置完成后用VS2015打开构建目录下的tesseract.sln。在解决方案管理器里可以看到tesseract和leptonica两个项目如果手动指定了Leptonica目录。在VS2015中切换解决方案配置为Release平台选择Win32。按顺序编译先右键leptonica项目执行生成再右键tesseract项目执行生成。不要直接点生成解决方案因为依赖顺序偶尔会乱手动按顺序编译更稳妥。整个过程大约5~10分钟取决于机器配置。编译完成后在构建目录的bin\Release下会生成tesseract.dll和leptonica.dll在lib\Release下生成tesseract.lib和leptonica.lib。接着执行安装cmake --install .打开C:\workspace\install-tesseract就能看到标准的开发库目录结构install-tesseract\ ├── bin\ # tesseract.dll, leptonica.dll 等运行库 ├── lib\ # tesseract.lib, leptonica.lib 等导入库 └── include\ # tesseract\ 和 leptonica\ 头文件目录这个结构可以直接拷给同事或集成到自己的C工程中。4. 在C工程中集成这个动态库4.1 工程配置头文件路径、库路径、附加依赖项拿到这套开发库后新建或修改C工程。在项目属性里C/C - 常规 - 附加包含目录添加install-tesseract\include链接器 - 常规 - 附加库目录添加install-tesseract\lib链接器 - 输入 - 附加依赖项添加tesseract.lib和leptonica.lib然后在代码中引入头文件#include tesseract/baseapi.h #include leptonica/allheaders.h这里有个经常踩的坑VS2015工程默认的字符集可能是Unicode而Tesseract的API内部使用UTF-8处理字符串。所以调用时要注意编码转换不要直接把std::string塞进去就完事。建议在工程属性中将字符集改为使用多字节字符集或统一在调用层做UTF-8转换。4.2 核心API调用一个独立可运行的识别示例下面这个示例是我实际在VS2015工程中跑通的完整调用代码从初始化到输出识别结果包含了错误处理#include tesseract/baseapi.h #include leptonica/allheaders.h #include iostream #include string #pragma comment(lib, tesseract.lib) #pragma comment(lib, leptonica.lib) int main() { // 1. 初始化Tesseract引擎 tesseract::TessBaseAPI api; // tessdata的路径指向包含 eng.traineddata 的目录不含eng.traineddata本身 if (api.Init(C:/workspace/install-tesseract/tessdata, eng)) { std::cerr Tesseract初始化失败请检查tessdata路径和语言包 std::endl; return -1; } // 2. 用Leptonica读取图片 Pix* image pixRead(C:/workspace/test.png); if (!image) { std::cerr 无法读取图片文件请检查路径是否为纯英文 std::endl; api.End(); return -1; } // 3. 设置图片并识别 api.SetImage(image); char* text api.GetUTF8Text(); std::cout 识别结果 std::endl; std::cout text std::endl; // 4. 释放资源 delete[] text; pixDestroy(image); api.End(); return 0; }一个完整的识别流程就这四步初始化、读图、识别、释放。需要提醒的是tessdata目录不是编译产物自带的需要单独从GitHub的tessdata仓库下载我用的eng.traineddata放到install-tesseract\tessdata\目录下。如果初始化时提示找不到语言包检查Init的第一个参数是否指到了tessdata的上层目录。4.3 识别参数与编码处理的经验Tesseract提供了一些参数可以优化识别效果在Init之后可以通过SetVariable设置api.SetVariable(tessedit_char_whitelist, 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ); api.SetVariable(preserve_interword_spaces, 1); api.SetVariable(user_defined_dpi, 300);第一个参数非常实用用于指定白名单字符只识别数字和英文大写字母能大幅提升特定场景的准确率比如验证码识别、车牌号识别。第二个参数保留词间空格对排版还原有要求的场景建议开启。第三个参数是手动指定DPI当图片没有DPI信息时默认值是70识别小字号文字容易失败手动指定300后准确率会好很多。中文识别需要额外下载chi_sim.traineddata并在Init时第二个参数传chi_simeng这样可以中英文混合识别。5. 常见问题与排查技巧实录5.1 编译阶段的常见报错在VS2015下编译Tesseract我实际遇到过的编译问题有这些报错信息原因解决方案fatal error C1083: 无法打开包括文件: curl.h编译工具链选择了64位或者缺少curl依赖确认-A Win32参数关闭不需要的依赖检测error C2039: isnan: 不是std的成员VS2015对C11数学函数支持不完整安装VS2015 Update 3或在代码中手动using std::isnan;LNK2038: 检测到RuntimeLibrary不匹配调用方工程与DLL的CRT类型不一致统一使用/MD并在所有工程中保持一致无法打开libcurl.libCPPAN拉取的curl依赖不完整手动下载curl源码编译或关闭网络相关功能这些报错多半是版本环境不匹配导致的。遇到isnan问题先在Update 3补丁下重新编译能解决大部分编译错误。5.2 运行时的经典错误与排查编译通过只是第一步实际运行时还会遇到各种问题下面这些是我在实际项目中逐一排查过的第一个是运行时提示找不到tesseract.dll。DLL虽然放在系统PATH里但程序启动仍然报错。这种情况优先用Dependencies工具或老版的Dependency Walker打开你的exe看看它实际加载的DLL路径。我遇到过因为系统目录中存在旧版本tesseract.dll导致程序加载了错误版本而崩溃的情况。建议把DLL放在exe同目录不要依赖PATH也不要把多个版本混装在系统目录里。第二个是初始化失败提示Error opening data file。这通常是路径问题Tesseract对路径很敏感。Init的第一个参数必须是tessdata所在目录的绝对路径而不是tessdata目录本身。路径中不要包含空格和中文。另外TESSDATA_PREFIX环境变量如果设置了会覆盖Init参数两者不一致时以环境变量为准。第三个是识别结果全是乱码。检查图片格式是RGB而Tesseract内部按灰度处理如果图片包含alpha通道或高分辨率彩色文字先做预处理再识别。用Leptonica的pixConvertTo8转灰度pixScale做缩放Pix* gray pixConvertTo8(image, 0); Pix* scaled pixScale(gray, 2.0, 2.0); api.SetImage(scaled);小字号的图片放大两倍后再识别准确率提升非常明显。注意释放gray和scaled对象。第四个问题只发生在32位版本中进程内存不足。32位进程默认只有2GB用户空间Tesseract在识别大图片时内存消耗高容易崩溃。解决方法是限制输入图片像素量识别前先用pixScale压缩到合理尺寸大图片分块识别按水平方向切分成若干个小图分别处理再拼接结果。5.3 调用方的工程类型选择与CRT一致性这点很隐蔽但极其重要。VS2015编译的Tesseract动态库默认使用/MD动态CRT编译如果你的调用方工程是/MT静态CRT链接阶段不会报错运行时却可能崩溃——因为两个模块各自持有一份CRT堆在跨模块分配和释放内存时比如你在外部delete[]Tesseract返回的char*就会触发堆冲突。这也是我上面特意用delete[] text而不是free(text)的原因Tesseract内部用new[]分配了text如果换成free在/MT模式下会直接崩溃。这一点不常见但排查起来非常费时间。如果你的工程因为某些原因必须使用/MT那么Tesseract动态库编译时也要设置/MT在CMake配置中加-DCMAKE_CXX_FLAGS_RELEASE/MT保持一致。6. 编译产物的实际使用效果与后续扩展这套VS2015WIN32动态库编译完成后我把它用在一个32位的工业读码项目中运行环境是Windows 7嵌入式系统机器内存只有2GB。实际检测效果对600dpi的A4打印体英文文档单张识别耗时约200ms准确率接近99%对屏幕截图中的数字和字母耗时在50ms以内准确率受字体影响常规字体基本能到95%以上。因为32位进程有内存上限我预处理时把超过4000像素宽度的图片先等比压缩到4000以内识别结果没有明显损失。最后再分享一点个人心得动态库编译好之后建议顺手写一个简单的接口封装把Tesseract的C API包成extern C的C接口。因为动态库是给C用的但如果后续要接C#、Python、Java等其他语言或者给一个纯C的模块调用C接口会省去很多麻烦。封装的方式不复杂核心就那么几个函数初始化、设置图片、识别、释放。我封装完放到另一个项目里直接被C#通过DllImport调用整个过程不到一小时。另外Tesseract本身也支持通过LSTM训练自定义字库。如果识别目标是比较特殊的字体比如艺术字、手写体建议采集500到1000张样本用tesseract.train工具训练专用模型。训练工具在编译时通过BUILD_TRAINING_TOOLSON开启VS2015下也能正常编译。这个功能对特定场景的准确率提升幅度很大值得花时间做。本文还有配套的精品资源点击获取