此文章為 漢學@博客園 原創作品,轉載請保留版權信息
原文鏈接:https://www.cnblogs.com/c2soft/articles/13194981.html
一、總體思路
各庫之間的依賴關系及使用的工具如下:
之前在 win7 64位 + VS2017 + VCPKG 的環境下很順利地編譯了 tesseract 4.1.1,可是當我想對 tesseract 的源碼做下改動時,發現編譯過程完全被 VCPKG 所接管,沒法重新編譯 tesseract 庫(C語言門外漢,慚愧),於是產生了自己手工編譯 tesseract 的想法。
按照網上的教程,直接使用 cppan 、 cmake 編譯 tesseract 時,總出現找不到 endianness.h 的問題,經多次嘗試,總結出使用 cppan、cmake 生成 leptonica 解決方案,然后使用 cmake-gui 手動生成 tesseract 解決方案的編譯方式。
二、環境准備
編譯環境:Win7 32位,VS2015
將cmake-3.17.3-win32-x86 解壓到 C 盤,cppan.exe 放到 cmake 的 bin 文件夾中,將C:\cmake-3.17.3-win32-x86\bin 添加到 Path 變量中。
三、編譯leptonica
1、 在 c 盤創建storage 文件夾,leptonica的所有依賴庫都將下載到此文件夾中。編輯C:\Users\用戶名\.cppan\cppan.yml,修改storage_dir,使其指向 c:\storage
2、 執行 cppan –V 初始化,將在c:\storage 中創建所需的文件夾結構。
3、 下載leptonica-1.78.0.tar (有網友建議使用1.76版本,說 1.79 版本編譯時只生成 dll,沒有lib。經驗證,1.76, 1.78版本都可以正常編譯。根據leptonica官網上的文檔,偶數版本為穩定版本,因此直接下載1.78,1.79是否有問題未去嘗試),將leptonica-1.78.0 文件夾解壓到 C 盤根目錄下。
4、 在C:\leptonica-1.78.0 下創建 build 文件夾,CMD窗口中執行:
cd C:\leptonica-1.78.0 cppan cd build cmake .. (在build 文件夾中執行 cmake,別少了兩個點點)
C:\leptonica-1.78.0\build 下順利生成 leptonica.sln 解決方案,使用 VS2015 打開它,VS2015->生成->配置管理器->release,先編譯生成cppan-d-b-d,將在C:\storage\bin\020a56a6\Release 下生成pvt.cppan.demo.jpeg-9.2.0.dll 等7個leptonica所需的DLL文件。
5、 再編譯生成 leptonica,結果生成:
C:/leptonica-1.78.0/build/src/Release/leptonica-1.78.0.lib
C:/leptonica-1.78.0/build/src/Release/leptonica-1.78.0.exp
C:\leptonica-1.78.0\build\bin\Release\leptonica-1.78.0.dll
6、 如果想生成兼容XP的文件,需要分別對 cppan-d-b-d 和leptonica 項目設置:常規->平台工具集:v140xp,有鏈接器選項的,還要設置:鏈接器->系統->所需最低版本:5.01
7、 此時C:\leptonica-1.78.0\build\src 下已經生成endianness.h 文件(網上很多編譯的方法都缺少此文件)。
四、編譯tesseract
1、 下載 tesseract ,注意選擇 4.1.1 穩定分支,不要下載 master 版本,master 代碼更新后可能出現其它編譯問題。將tesseract-4.1.1文件夾解壓到C盤根目錄,在tesseract-4.1.1下創建build文件夾。
2、 運行cmake-gui,指定source文件夾到C:\tesseract-4.1.1(必須指定到CMakeLists.txt所在的文件夾),指定 build 文件夾到C:\tesseract-4.1.1\build,點“configure”,將顯示紅色的錯誤信息,需要指定leptonica 文件夾。
3、 根據上面的提示,leptonica 文件夾需要定位到包含 LeptonicaConfig.cmake 或 leptonica-config.cmake 的文件夾,在 leptonica 的文件夾中搜索這兩個文件,找到C:\leptonica-1.78.0\build\LeptonicaConfig.cmake,因此將Leptonica_DIR 指向C:\leptonica-1.78.0\build\,再次 configure 。
4、 又出現新的錯誤,根據提示,是因為下載下來的icu32.zip 的 hash 值與預期的不同,打開C:\tesseract-4.1.1\src\training\CMakeLists.txt,第39行中可以發現下載的網址,到該網站手工下載icu4c-56_1-Win32-msvc10.zip,計算它的MD5值,與期待的一致。
在tesseract文件夾中搜索 icu32.zip(就是MD5值錯誤的文件),將下載的 icu4c-56_1-Win32-msvc10.zip 更名為 icu32.zip 替換剛才搜索到的 icu32.zip,再次configure。
5、 點configure后,結果提示“Configuring incomplete, errors occurred!”,查看提示信息,前后有兩處紅色的錯誤,先解決前面的。
cmake 試圖在 C:/leptonica-1.78.0/build/ 查找 cppan.cmake 文件,可是沒有找到。到 C:/leptonica-1.78.0 中搜索一下 cppan.cmake,在C:\leptonica-1.78.0\build\exports 下發現了這個文件,將其復制到C:/leptonica-1.78.0/build/,再次 configure。
Configuring done!剛才后面還有一處錯誤,現在沒有了。點 generate,Generating done!
C:\tesseract-4.1.1\build下已經生成了tesseract.sln。
6、 用 VS2015 打開tesseract.sln,設置好編譯選項后先生成 libtesseract,出現以下錯誤信息:
查找 allheaders.h,位於C:\leptonica-1.78.0\src下,將C:\leptonica-1.78.0\src加入項目的包含目錄即可。
7、 再次生成,提示“錯誤C1083 無法打開包括文件: endianness.h”,經查找,endianness.h保存在C:\leptonica-1.78.0\build\src 下,該文件夾下面只有config_auto.h、endianness.h兩個頭文件,因為剛才已經把C:\leptonica-1.78.0\src加入了包含目錄,這次不再另添加包含目錄了,將兩個頭文件直接復制到C:\leptonica-1.78.0\src下。
8、 再次生成,提示“錯誤 LNK1181 無法打開輸入文件 pvt.cppan.demo.gif.lib”,因為前面編譯leptonica時生成的lib文件名為C:\storage\lib\020a56a6\Release\pvt.cppan.demo.gif-5.1.4.lib,所以導致這里無法打開輸入文件,在VS中點擊項目的 VC++目錄->庫目錄->編輯,將C:\storage\lib\020a56a6\Release\加入到庫搜索目錄中:
9、 點項目的 鏈接->輸入->依賴附加項->編輯,將pvt.cppan.demo.gif.lib、pvt.cppan.demo.jpeg.lib、pvt.cppan.demo.png.lib、pvt.cppan.demo.tiff.lib、pvt.cppan.demo.webmproject.webp.lib、pvt.cppan.demo.openjpeg.openjp2.lib幾個項目逐一加入leptonica編譯結果的版本號:
再次生成,順利生成
C:/tesseract-4.1.1/build/Release/tesseract41.lib
C:/tesseract-4.1.1/build/Release/tesseract41.exp
C:\tesseract-4.1.1\build\bin\Release\tesseract41.dll
10、編譯生成tesseract,會遇到以上步驟7、8、9的問題,照上面的方法即可解決。也可以跳過第8步,在第9步中加入庫文件的全路徑也可以。
五、改進與提高
1、編譯完 tesseract.exe 后,突然心血來潮,想把全部的 TrainTools 編譯出來,編譯時又遇到了上面步驟 8、9 的問題,需要手工對附加依賴項加入版本號,每編譯一個 traintool 都要修改 6 處,一共 10 多個工具呢!有沒有一勞永逸的方法呢?猜測是因為在編譯 leptonica 時生成的lib文件名為C:\storage\lib\020a56a6\Release\pvt.cppan.demo.gif-5.1.4.lib,而在 tesseract 項目中需要導入的庫為 pvt.cppan.demo.gif.lib,導致二者不一致,那么只要在編譯 leptonica 時生成的 pvt.cppan.demo.gif-5.1.4.lib 不帶版本號,就可以與 tesseract 無縫結合了。
在 leptonica 的文件夾中搜索包含 “pvt.cppan.demo.gif” 的文件,在 C:\leptonica-1.78.0\.cppan\CMakeLists.txt 中找到了線索:
if (CPPAN_USE_CACHE) # pvt.cppan.demo.webmproject.webp-1.0.0 cppan_include("C:/storage/obj/33/8b/7ef3/generate.cmake") # pvt.cppan.demo.jpeg-9.2.0 cppan_include("C:/storage/obj/97/2a/155a/generate.cmake") # pvt.cppan.demo.gif-5.1.4 cppan_include("C:/storage/obj/d6/de/c13d/generate.cmake") # pvt.cppan.demo.tiff-4.0.9 cppan_include("C:/storage/obj/1f/16/f783/generate.cmake") # pvt.cppan.demo.png-1.6.35 cppan_include("C:/storage/obj/44/f1/4690/generate.cmake") # pvt.cppan.demo.openjpeg.openjp2-2.3.0 cppan_include("C:/storage/obj/71/a6/8bbe/generate.cmake") else() # pvt.cppan.demo.webmproject.webp-1.0.0 cppan_include("C:/storage/src/33/8b/7ef3/include.cmake") # pvt.cppan.demo.jpeg-9.2.0 cppan_include("C:/storage/src/97/2a/155a/include.cmake") # pvt.cppan.demo.gif-5.1.4 cppan_include("C:/storage/src/d6/de/c13d/include.cmake") # pvt.cppan.demo.tiff-4.0.9 cppan_include("C:/storage/src/1f/16/f783/include.cmake") # pvt.cppan.demo.png-1.6.35 cppan_include("C:/storage/src/44/f1/4690/include.cmake") # pvt.cppan.demo.openjpeg.openjp2-2.3.0 cppan_include("C:/storage/src/71/a6/8bbe/include.cmake") endif()
原來 gif、png 這些 leptonica 的依賴庫的配置在 c:\storage\src 下,到 c:\storage\src 中搜索包含 “pvt.cppan.demo.gif” 的文件,找到了 C:\storage\src\d6\de\c13d\CMakeLists.txt,其中包含以下代碼:
if (CPPAN_SHORT_LOCAL_NAMES) set_target_properties(${this} PROPERTIES OUTPUT_NAME gif-5.1.4) else() set_target_properties(${this} PROPERTIES OUTPUT_NAME pvt.cppan.demo.gif-5.1.4) // 去掉“-5.1.4”后,只生成 pvt.cppan.demo.gif.lib endif()
試了一下,只要將 OUTPUT_NAME 中的版本號去掉,編譯時生成的 lib 就是沒有版本號了。
在編譯 leptonica 時, 在執行完 cppan 命令,下載好全部依賴庫的源代碼后,先不要執行 cmake,到c:\storage\src 下搜索 “CMakeLists.txt”,一共找到 10 個,在每個文件中查找 “OUTPUT_NAME”,將 OUTPUT_NAME 后面的版本號去掉,然后再執行 cmake,這樣生成的解決方案編譯后就會得到不帶版本號的 lib 文件了,編譯 tesseract 時的步驟 8、9 就可以免去了。
2、在編譯 TrainTools 時還遇到一個問題:就是每編譯一個項目,就要設置包含目錄和庫目錄,能否設置成全局屬性,不再一一設置呢?后來找到了方法:在 VS 中打開 視圖->其他窗口->屬性管理器,在任一項目下找到 Microsoft.Cpp.Win32.user 打開,
對其設置包含目錄和庫目錄后,就是全局性質的設置了,其它項目就不用再逐一設置了。
六、小結
以上記錄的是解決問題的過程,實際在編譯時可以把步驟再優化一些,簡要記錄如下:
- cppan 下載 leptonica 依賴庫的源代碼
- 在 c:\storage\src 下搜索 CMakeLists.txt(一共10個),將其中 OUTPUT_NAME 后面的版本號去掉
- cmake 生成 leptonica 解決方案,VS 編譯之
- 將 C:\leptonica-1.78.0\build\src 中的 config_auto.h、endianness.h 復制到 C:\leptonica-1.78.0\src 中,將 C:\leptonica-1.78.0\build\exports\cppan.cmake 復制到 C:\leptonica-1.78.0\build
- 在 cmake-gui 中設置 leptonica 路徑為 C:\leptonica-1.78.0\build\ ,替換 icu32.zip,生成 tesseract 解決方案
- VS 打開 tesseract 解決方案,全局包含目錄添加 C:\leptonica-1.78.0\src ,全局庫目錄添加 C:\storage\lib\020a56a6\Release,然后就可以逐一編譯了
七、后記
這種編譯方式的優點在於,tesseract 所依賴的其它庫使用 cppan 和 cmake 自動下載源代碼,生成解決方案,全程自動化;而 tesseract 使用手工編譯,如果需要改動其源代碼,可以隨時重新編譯它,比較靈活。將自己編譯的全過程記錄下來,希望對大家有所幫助。
下載 traineddata 的頁面是 https://tesseract-ocr.github.io/tessdoc/Data-Files,不知道為什么下載不下來。
BTW:
我使用 tesseract 對下面的驗證碼圖片
進行識別時遇到了很詭異的問題,本以為這個圖片很清晰,而且沒有做變形處理,tesseract 應該可以輕松識別。可是 tesseract 將其識別為 ZING。開始我以為是 tesseract 使用詞庫對識別結果做了糾正,可是在源代碼中禁用詞庫后,結果仍然是 ZING。
將原圖放大之后觀察,4個字母之間的間隔是1個像素,在 PhotoShop 中將字符間距拉至2像素,tesseract 識別為 Z2NG;將字符間距拉到3像素,又識別為 ZING;當間距拉大到4像素以上時,就完全可以正確識別了。
使用 Tesseract 的multilang_debug_level 參數分別對間距為2像素、3像素的圖片測試,結果如下:
猜想與字符間距有關,可是在參數表里沒找到哪個參數可用,如果哪位網友有辦法解決,歡迎在下方留言指教或者給我發郵件 731805810@qq.com 。