Rust から Tesseract OCR(のライブラリ)を呼び出そうと色々やっていました。
ひとまず動くようになったので備忘録としてあげておきます。
vcpkg でインストールした DLL を Rust で使う、という場合にも使えると思います。
vcpkg をインストールする
GitHubの説明に則ってインストールします。
https://github.com/microsoft/vcpkg
Tesseract OCRライブラリをインストールする
以下コマンドでインストールします。
アニメ一本分くらいは時間かかります。
./vcpkg install tesseract:x64-windows
依存関係のあるパッケージも一緒にインストールしてくれますが、足りない場合は以下を実行してみてください。
./vcpkg install leptonica:x64-windows
Rust プロジェクトで読み込む
tesseract クレートを利用しました。
https://crates.io/crates/tesseract
Cargo.toml に以下を追記してビルドします。
tesseract = "0.12.0"
main.rs は最低限の記述にします。
let text = tesseract::ocr("test.png", "jpn").unwrap();
println!("Tesseract: {}", text);
lib をプロジェクトのルートに設置する
vcpkg でインストールした .lib ファイルを Rust プロジェクトのルートフォルダに配置します。
lib ファイルは vcpkg\installed\x64-windows\lib 以下にあります。
tesseract のビルドに必要なファイルは以下のようです。
- leptonica-1.82.0.lib
- libcrypto.lib
- libcurl.lib
- tesseract52.lib
設置したらビルドしてみます。
> cargo build
エラーが出なければひとまずOKです。
ただし、ビルドは通っても cargo run すると DLL が足らないと怒られます。
error: process didn't exit successfully:
target\debug\tesseract_rust.exe (exit code: 0xc0000135, STATUS_DLL_NOT_FOUND)
実行に必要な DLL を設置する
DLL はプロジェクトのルートではなく、exe と同じパスに設置する必要があります。
target\debug\ 以下に DLL を設置します。
lib ファイルとは違い、関連する DLL が全て必要です。
vcpkg\installed\x64-windows\tools\tesseract\ 以下にある DLL を全て target\debug\ 以下にコピーします。
動かしてみます。
> cargo run
言語ファイルが無いと言われます。
GitHub から jpn.traineddata を DL してプロジェクトのルートフォルダに設置します。
https://github.com/tesseract-ocr/tessdata
これで動作するようになりました。
build.rs でビルドを自動化する
ビルドや実行の度に関連ファイルを設置するのは面倒なので、build.rs を書いて自動化してみました。
fn main() {
let project_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
println!("cargo:rustc-link-search=native={}\\lib", project_dir);
let target_path = std::path::Path::new(&project_dir).join("target");
if target_path.exists() {
let debug_path = target_path.join("debug");
let release_path = target_path.join("release");
let dll_files = std::fs::read_dir(std::path::Path::new(&(project_dir + "\\dll"))).unwrap()
.map(|res| res.map(|e| e.path()))
.collect::<Result<Vec<_>, std::io::Error>>().unwrap();
for path in dll_files {
if debug_path.exists() {
std::fs::copy(&path, debug_path.join(&path.file_name().unwrap())).unwrap();
}
if release_path.exists() {
std::fs::copy(&path, release_path.join(&path.file_name().unwrap())).unwrap();
}
}
}
}
今回は cargo:rustc-link-search=native= を指定して、プロジェクトルート以下の lib フォルダを参照するように設定しています。
vcpkg\installed\x64-windows\lib をフルパスで指定しても問題ないと思います。
更に、targetフォルダがある場合に dll フォルダ以下の DLL ファイルを全て debug、release フォルダにコピーするように設定しています。
こちらも、DLLフォルダはフルパスで vcpkd 以下を指定してもいいと思います。
GitHub にプロジェクトがありますので、必要な方はどうぞ。
https://github.com/sou1ka/tesseract_rust
Rustのビルド時にC++のソースも一緒にビルドしてFFIする方法もできるとは思いますが、Tesseract の構成が中々重たいので今回はvcpkg経由で試してみました。
参考