1. 程式人生 > >Tess4J Linux 實踐[解決:Tess4J - Native library (linux-x86-64/libtesseract.so) not found in resource path]

Tess4J Linux 實踐[解決:Tess4J - Native library (linux-x86-64/libtesseract.so) not found in resource path]

進行 新版 指令 tom form res lower 活躍 txt

【本文編寫於2018年7月5日】

Tess4J是Tesseract的Java JNA wrapper。本文介紹了在CentOS 7 操作系統中使用Tess4J的步驟及註意事項。在正式開始之前,先花一點篇幅,對相關的技術作一簡要介紹。

一點點背景

Tesseract

Tesseract 是一個著名的開源OCR引擎,支持100多種語言,可以開箱即用。還可以通過訓練方式支持更多語言。Tesseract誕生於1984年,來自HP公司,2005年開源。自2006年起,由谷歌接手開發。截止目前,最新的穩定版本是2017年6月1日發布的3.05.01。還有一只比較活躍的基於LSTM(長短期記憶網絡,是一種時間遞歸神經網絡)的4.0版本,還在研發中,最新釋放的是2018年6月26日的4.0.0-beta.3。Tesseract由C++開發。

站點:

https://github.com/tesseract-ocr/tesseract

Leptonica

Tesseract作為OCR引擎,避免不了使用圖像處理。Tesseract使用的圖像處理主要由leptonica提供。Leptonica 包含眾多圖像處理和圖像分析相關的功能。

站點:

http://www.leptonica.com/

Java JNA Wrapper

JNA 是 Java Native Access的縮寫,顧名思義,是一個實現Java調用操作系統Native應用的庫。提起Java本地調用,大家自然聯想的JNI,但JNI使用過程十分復雜,會讓人望而生畏。JNA則采取更加自然的方式,為Java應用提供調用本地應用的支持。

站點:

https://github.com/java-native-access/jna

Tess4J

Tess4J通過Java JNA Wrapper,提供了Java的Tesseract API,同時還提供了Windows 32bit和64bit的Tesseract的DLL以及一些樣例圖像。通過Tess4J,可以在Windows下非常便利的通過Java使用Tesseract。對於Linux、MAC等其他操作系統,則需要自行構建Tesseract才可以使用Tess4J。

也就是說,原生的Tess4J並不是跨平臺的,僅僅是對Windows開箱即用的。

這也是本文寫作的初衷,記錄在Linux環境中,使用Tess4J的步驟及淌過的坑。

本文使用的技術版本

為什麽要單獨強調版本?長期混跡開源坑的同誌們一定了解一個事實:大部分的開源項目其質量(功能可用性,文檔正確性、更新及時性)相對一般,在圈子裏混,必須具備在眾多繁雜的信息中去偽存真的能力,在社區裏大聲疾呼求關註的技巧,極強的動手能力以及百折不撓的精神。。。

對於某些技術問題,谷歌出來的結果中,很大一部分是無效的,會浪費大量的時間,甚至走入歧途。但同眾多作者交流後發現,絕大部分這類情況是有文章介紹方案不完整,或者不夠嚴謹導致的。

因此,我認為,作為分享的每一個實踐,需要具備可重復操作的基本要求。所以,我會盡量精確的重復我實踐過程使用的軟件及環境的版本,希望對大家有所幫助。

Tess4J:4.0.2

Tesseract:4.0.0-beta.1

Leptonica:1.76.0

JDK:1.8 Update 102 64bit

運行環境:CentOS 7 (內核:3.10.0-862.3.3.el7.x86_64)64bit

GCC:4.8.5

Clang:3.4

開發環境:Windows 10 64bit

為何這樣選?

這裏的坑是,不能根據自己的喜好,使用新版本。我使用過Tesseract 4.0.0-beta.3,但運行JVM會報出Fatal Error最後自行退出,看報出的錯誤來判斷,大概是Tesseract中某些函數簽名變化,Tess4J中簽名與之不匹配所致。

還記得官方文檔(https://github.com/tesseract-ocr/tesseract/wiki)嗎?

技術分享圖片

官方Wiki提到,Linux的so庫,可以通過安裝預先編譯的包,如果按照Wiki操作,便會自動安裝最新版本。我也曾經嘗試通過yum列表舊版本安裝,發現即使所謂的舊版本,也會導致Tess4J運行時報錯。(通過yum下載並自動安裝的rpm包如下所示)

技術分享圖片

這裏必須根據Tess4J適配的版本來選擇。

Tess4J的versionchanges.txt中描述了最近幾個版本的變化:

Version 4.0.0 (28 April 2018)
- Upgrade to Tesseract 4.0.0-beta.1 (45bb942)
- Update Lept4J to 1.9.3 (Leptonica 1.75.3)

Version 4.0.1 (2 May 2018)
- Fix a path issue when extracting resources from JAR to temp directory on Windows server

Version 4.0.2 (3 May 2018)
- Replace JNA string constant Platform.RESOURCE_PREFIX
- Update jai-imageio url
- Update Lept4J to 1.9.4

可見,最新版的Tess4J,僅對Tesseract 4.0.0-beta.1進行過適配,因此產生了上面描述的版本組合。鑒於無法確定預先構建的包哪個是從Tesseract 4.0.0-beta.1構建而來,因此只能通過源碼自行構建。

構建Tesseract

1 修改yum的Repo

可能是我所在的環境網絡非常差,yum默認會使用mirror,但絕大部分mirror連接不上,會導致下載過程在大量無效的mirror嘗試中進行,非常浪費時間。

因此,我關閉了yum的fast mirror插件(/etc/yum/pluginconf.d),另外修改了CentOS-Base.repo。

技術分享圖片

2 安裝必備包

yum -y update 
yum -y install libstdc++ autoconf automake libtool autoconf-archive pkg-config gcc gcc-c++ make libjpeg-devel libpng-devel libtiff-devel zlib-devel
yum group install -y "Development Tools"

註意:autoconf-archive 是官方說明中都沒有提到的必備組件。

3 下載源碼

Leptonica

http://www.leptonica.com/source/leptonica-1.76.0.tar.gz

Tesseract

https://codeload.github.com/tesseract-ocr/tesseract/tar.gz/4.0.0-beta.1

下載完畢效果:

技術分享圖片

4 安裝Leptonica

tar -zxvf leptonica-1.76.0.tar.gz
cd leptonica-1.76.0
./autobuild
./configure
make -j
make install

5 安裝Tesseract

tar -zxvf 4.0.0-beta.1.tar.gz
cd tesseract-4.0.0-beta.1/
./autogen.sh
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig LIBLEPT_HEADERSDIR=/usr/local/include ./configure --with-extra-includes=/usr/local/include --with-extra-libraries=/usr/local/lib
LDFLAGS="-L/usr/local/lib" CFLAGS="-I/usr/local/include" make -j
make install
ldconfig

6 確認安裝

經過漫長的編譯過程,Tesseract已經安裝完畢。

執行如下指令:

tesseract -v

  顯示內容如下:

技術分享圖片

即為安裝完畢。

獲取so庫

在/usr/local/lib中,可以找到Tess4J需要的依賴庫libtesseract.so。可見libtesseract.so實際指向libtesseract.so.4.0.0。liblept.so是leptonica的庫,Tesseract也需要調用。

技術分享圖片

為Tess4J設置庫(so)文件位置

Tess4J的JAR包中,包含windows的DLL庫,其位置如下:

技術分享圖片

在Tess4J運行時,會將操作系統依賴的庫從JAR包中解壓出來使用,對於Linux系統的so文件,也是如此。Tess4J約定的Linux庫文件存儲路徑為classpath根路徑下的linux-x86-64。

既然已經拿到了so文件,顯而易見的有兩種方法:

1 修改tess4j-4.0.2.jar,將so文件按照約定路徑存儲,這樣Tess4J在運行時就會自動解壓使用。

技術分享圖片

但這種方式修改了Tess4J公開發布的JAR包,日後升級會有麻煩,因此,不建議這樣操作。

2 將linux-x86-64放到Java工程的classpath根目錄。這樣在運行時,Tess4J就可以找到庫了。我的Java工程采用的Gradle構建,因此將這些文件放到了src/main/resources下。

技術分享圖片

linux-x86-64目錄中包含的文件,是從Linux系統中/usr/local/lib拷貝而來,去掉了一些鏈接文件,具體如下:

技術分享圖片

至此,已經完成了Tess4J在庫文件方面的準備。

在Tess4J設置Tesseract數據目錄tessdata

Tesseract運行時是需要加載語言的訓練數據的,按照約定,這些訓練數據需要放在tessdata下。但Tess4J 4.0.2對Windows和Linux兩類操作系統目錄處理方式是不一致的。

初始化Tesseract的代碼,setDatapath就是用來設置tessdata目錄的。

ITesseract instance = new Tesseract();
//設置tessdata目錄
instance.setDatapath("/path/to/tessdata");

Tesseract的訓練數據以“語言名.traineddata”命名。

經過實測,在Windows中,需要直接指定到.traineddata所在目錄,在Linux中,則需要指定到一個目錄,其中包含一個叫做tessdata的文件夾,tessdata內部是.traineddata文件。

舉例說明:

技術分享圖片

在Windows中,instance.setDatapath("lngData/tessdata");

在Linux中,instance.setDatapath("lngData");

顯然這是一個BUG,不過開源項目有BUG已經是家常便飯了。

為此,我在實踐時根據操作系統做了一個小小的適配。

                ITesseract instance = new Tesseract();
		File tessTrainedDataLoc = null; 
		if(SystemDetector.isWindows())
		{
			//Windows Data目錄直接指定到*.traineddata所在目錄
			tessTrainedDataLoc = new File(System.getProperty("user.dir"),"lngData\\tessdata");
		}
		else
		{
			// 在Linux(如CentOS 7)中,Data目錄指定到tessdata上一級
			tessTrainedDataLoc = new File(System.getProperty("user.dir"),"lngData");
		}
		instance.setDatapath(tessTrainedDataLoc.getAbsolutePath());

以上用到的SystemDetector代碼:

import java.util.Properties;

public class SystemDetector {

	private static boolean isWindows = false;
	private static boolean isLinux = false;
	
	static {
		Properties props = System.getProperties();
		String systemName = props.getProperty("os.name");
		if (systemName.toLowerCase().indexOf("windows") != -1) {
			isWindows = true;
		}
		if (systemName.toLowerCase().indexOf("linux") != -1) {
			isLinux = true;
		}
	}
	
	public static boolean isWindows()
	{
		return isWindows;
	}
	
	public static boolean isLinux()
	{
		return isLinux;
	}
}

  至此,全部完成。在Windows上開發的項目使用Tess4J,已經可以在Linux中正常運行。

關於Tesseract的訓練數據

Tesseract最大優勢就是可以開箱即用,擁有大量語言的訓練數據,實際使用時,可以根據需要進行OCR識別的內容類型添加。

但是不要貪多,識別範圍越廣,速度也就越慢,甚至還會影響精確度。建議在使用時盡量指定要識別內容的語言,類型,以便在準確度及效率之間取一個恰當的平衡。

Tesseract訓練數據可以從下面獲取:

https://github.com/tesseract-ocr/tessdata

Tesseract 4使用了LSTM,因此還有一個叫做tessdata_best的Repo,其內容是使用LSTM模型訓練的各種語言識別率最高的訓練數據。(推薦使用)

https://github.com/tesseract-ocr/tessdata_best

如果對Tesseract效果不滿意,還可以自行準備數據進行訓練。Tesseract所有項目均在Github上,鏈接地址為:

https://github.com/tesseract-ocr

【全文完】

歡迎轉載,請註明出處。

Tess4J Linux 實踐[解決:Tess4J - Native library (linux-x86-64/libtesseract.so) not found in resource path]