忍者ブログ
プログラミングとか日常とかの覚書っぽいなにか
[33] [32] [31] [30] [29] [28] [27] [26] [25] [24] [23]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

いろいろと手当たり次第に試しているような気もする今日この頃。

OCR(光学文字認識)の機能を実現できないものかと思い立ち、フリーのOCRライブラリがないか探してみたところ、『Tesseract OCR』(テッサラクトOCR)なるものがあることを知ったので、これを試してみることにしました。

どうやらTesseract OCRのライブラリ自体はC++で書かれているようなのですが、ライブラリのビルド方法や自作アプリからの使用方法、各クラスや関数の説明などが少なく、分からないことが山積みで、Google先生の力を借りて検索してても日本語ドキュメントどころか英語の範囲でもなかなか見つからずに試行錯誤する羽目になりました。

今回のテストプログラムを作成するまでの過程を以下にまとめておきます。


Tesseractライブラリのビルド

まずはTesseract OCRのプロジェクトページからライブラリのソースなどをダウンロードします。Google Project Hostingで管理されており、以下のページからダウンロードできます。
    
tesseract-ocr - Google Project Hosting
http://code.google.com/p/tesseract-ocr/

ダウンロードリスト
http://code.google.com/p/tesseract-ocr/downloads/list


現時点の最新リリースバージョンはVer.3.01なので、*-3.01.* という名前のファイルが必要になります。今回は、以下の3つが必要となるので、ダウンロードしてきます。
  • tesseract-3.01.tar.gz
        ソースファイル
  • tesseract-3.01-win_vs.zip
        Visual C++ 用のプロジェクトファイル(2008, 2010用)
  • tesseract-ocr-3.01.eng.tar.gz
        Tesseract用の言語データ(英語)

上記3つのうち2つはアーカイブの形式が ~.tar.gz なので、対応する圧縮・解凍ソフトを使って展開してください。

ソースファイルには、ライブラリをビルドするためのVisual C++のプロジェクトファイルは含まれていないので、別にダウンロードする必要があります。これらの2つはどちらも「tesseract-3.01」フォルダを起点として、その下にファイルやサブフォルダがあるので、1つにまとめておきます。
86af4749.png

ソースには言語データファイルが含まれていないので、これもまた別にダウンロードする必要があります。今回は英語のものを使います。こちらは「tesseract-ocr」フォルダの下に「tessdata」サブフォルダがあって、その中に各種データファイル(eng.*** という名前)がありますので、これらのファイルをソースの「tessdata」フォルダの中にコピーしておきます。
(今回はライブラリのみビルドするのでこの位置に置かなくても大丈夫なのですが、ソリューション全体をビルドする場合にはこの位置にないとビルド時にエラーが発生してしまうみたいです。)


Visual C++のソリューションファイル・プロジェクトファイルはVisual C++ 2008 用のものとVisual C++ 2010 用のものがあり、それぞれ「vs2008」と「vs2010」フォルダに格納されています。使っている開発ツールに合った方を使うようにします。私の環境はVisual Studio 2010がインストールされているので、Visual C++ 2010用の方を使っていきます。(ただし、Visual Studio 2010を使う場合でも、一部のファイル(.libなど)はvs2008フォルダの中のものが使用されます。)

ソースファイルには、Tesseractライブラリ内で使用されている各種ライブラリ群、コマンドライン版Tesseract OCRアプリケーションや、関連するツールなどのソースが含まれているので、ソリューションファイル内にも数多くのプロジェクトが存在します。今回はOCRライブラリのみを必要としているので、「libtesseract」プロジェクトのみビルドするようにします。

このソリューションファイルにはビルドの構成として以下の4つの構成があります。
  • Release
  • Release.dll
  • Debug
  • Debug.dll

ただ、少なくともVisual C++ 2010の環境では、「Debug」「Debug.dll」の構成は使用できなさそうです。というのも、Tesseractライブラリでは内部でLeptonicaと呼ばれる画像処理ライブラリを使用しているのですが、これのデバッグビルド版ライブラリがVisual C++ 2008のデバッグ版ランタイムを必要としているのです。このデバッグ版C/C++ランタイムはVisual C++ 2008がインストールされた開発環境にしか存在しないはずのものなので、Visual C++ 2010の開発環境では使えないわけです。

この問題は、すでにビルドされた状態のLeptonicaライブラリを使用しているために起こる問題で、Leptonicaライブラリも含めてソースからビルドしなおせばこの問題は発生しないわけですが…。

一方、リリースビルドの方であれば、実行環境にVisual C++ 2008ランタイムライブラリがインストールされていれば問題なく実行できます。ここでは、ツールバーにあるビルド構成で「Release」を選択してビルドを行います。
e6147325.png

ソリューションエクスプローラ上の「libtesseract」を右クリックして表示されるメニューでビルドを選択し、Tesseractライブラリをビルドします。(プロジェクトの依存関係が適切に設定されているので、必要となる他のプロジェクトについても自動的にビルドされます。)
21672120.png

ビルド後に「tesseract-3.01\vs2010\Release」フォルダに「libtesseract.lib」が格納されていれば成功です。


お試しプログラムの作成

次に、Tesseractライブラリを使ったお試しプログラムを作っていきます。

Web上ではTesseractを使ったソースのサンプルがほとんど見当たりませんでした…。
そのため、「api\baseapi.h」に書かれているコメントや、一緒に含まれているコマンドラインツールのソース「api\tesseractmain.cpp」を読み解いて書いていくことになると思います。(Doxygenで作られたドキュメントはダウンロード可能なんですけど…うーん…)

その結果出来上がったお試しプログラムは以下の通り。「tesseractmain.cpp」を簡略化したものになっています。ビットマップファイル input.bmp を読み込み、文字列をコンソールに出力するようにしています。


#include <iostream>
#include "baseapi.h"
#include "strngs.h"

int main(int argc, char* argv[])
{
    tesseract::TessBaseAPI tessBaseApi;
    tessBaseApi.Init(
        argv[0],            // データパス (tessdata の親ディレクトリ名) 
        "eng");             // 言語 "eng", "jpn" など

    STRING output;
    bool success = tessBaseApi.ProcessPages(
        "input.bmp",        // 入力ファイル名
        NULL,               // リトライconfigファイル名
        0,                  // タイムアウト値(msec) (0 は指定なし)
        &output);           // 出力文字列

    if (!success) {
        std::cout << "Error occurred.\n";
    } else {
        std::cout << "result: [" << output.string() << "]\n";
    }

    return success ? 0 : 1;
}


TessBaseAPIクラスがTessseractライブラリの基本的なAPIを提供するクラスのようです。クラスや定数名などはtesseract名前空間に含まれている模様。また、文字列を表す STRING 型が存在するらしい…。

Tessseract::Init() の第1引数は、言語データファイル(今回は eng.traineddata)を含むtestdataフォルダの親フォルダのパスを指定する必要があります。この引数は最後の文字がファイルパスのデリミタ(スラッシュ「/」とかバックスラッシュ「\」)であると想定されていますが、もし最後の文字がデリミタでない場合は、最後のデリミタより後ろが切り捨てられるようです。
main() の引数 argv[0] は通常exeファイルのフルパスが指定されているので、これをそのまま指定することでexeファイルがあるフォルダを指定したことになります。したがって、実行時にはexeのあるフォルダに「testdata」フォルダを作成し、その下に言語データファイル eng.traineddata を格納しておく必要があります。

tessBaseApi.Init() にはもっと多くの引数をとるオーバーロードが存在するようですが、それを調べる時間がなかったので、それについては後日に後回し。


お試しプログラムのビルドを行うのですが、今回はVisual C++のIDEでなく、makefile を作成してMAKEツールでビルドする方法を取りました。なんとなくそちらの方がラクかなーと思ったので…。(makefileの雛型がすでに手元にあったというのもありますが。)

makefileは以下の通り。テストプログラムのソースを test.cpp として保存し、それと同じフォルダにファイル名「makefile」を作成し、以下の内容で保存します。ただし、Tesseractライブラリのパス(「TESS_BASE = XXX」の部分)については、上記のライブラリビルド時のフォルダに直してください。また、Visual C++ 2010でなくVisual C++ 2008を使っている場合は、「vs2010」の部分を「vs2008」に直す必要があるので注意。


TARGET = test.exe
OBJECTS = test.obj

TESS_BASE = D:\dev\tesseract-3.01
OTHER_LIB_DIR = $(TESS_BASE)\vs2008\lib

## [Debug build] (Debug版はうまくいかないのでコメントアウト)
#TESS_LIB_DIR = "$(TESS_BASE)\vs2010\Debug"
#LIBS = user32.lib libtesseract-debug.lib liblept-static-mtdll-debug.lib
#CPPFLAGS_PP = /D__MSW32__ /D_DEBUG
#CPPFLAGS_CRT = /MDd

# [Release build]
TESS_LIB_DIR = "$(TESS_BASE)\vs2010\Release"
LIBS = user32.lib libtesseract.lib liblept-static-mtdll.lib
CPPFLAGS_PP = /D__MSW32__
CPPFLAGS_CRT = /MD

## [Release build (DLL)] (DLL版を使うならこちらを有効に)
#TESS_LIB_DIR = "$(TESS_BASE)\vs2010\Release.dll"
#LIBS = user32.lib libtesseract.lib
#CPPFLAGS_PP = /D__MSW32__
#CPPFLAGS_CRT = /MD


CPPFLAGS = /nologo /Zi /EHsc /c $(CPPFLAGS_CRT) $(CPPFLAGS_PP) \
 /I"$(TESS_BASE)\api" \
 /I"$(TESS_BASE)\ccstruct" \
 /I"$(TESS_BASE)\ccutil" \
 /I"$(TESS_BASE)\ccmain"

LINKFLAGS = /nologo /DEBUG /out:$(TARGET)\
 /LIBPATH:$(TESS_LIB_DIR) /LIBPATH:$(OTHER_LIB_DIR)

CC = cl.exe
LK = link.exe
RM = del

all : $(TARGET)

$(TARGET): $(OBJECTS)
	$(LK) $(LINKFLAGS) $(OBJECTS) $(LIBS)

.cpp.obj:
	$(CC) $(CPPFLAGS) $<

clean:
	$(RM) *.obj *.pdb $(TARGET).pdb $(TARGET).exe

rebuild: clean all


Visual C++のコマンドプロンプトを実行し、cdコマンドでソースおよびmakefileのあるフォルダに移動します。以下のように nmake (Visual C++のMAKEツール)を実行すると、お試しプログラムのビルドを行います。


D:\dev\tesseracttest> nmake rebuild


うまくビルドが完了すれば、test.exe が出来上がっているはずです。
ビルドができたら、同じフォルダ配下に「testdata」フォルダを作成して言語データ eng.traineddata をコピーします。

さて、ビットマップファイルとして、以下のような画像を「input.bmp」という名前で同じフォルダに置いて実行してみました。(これはTesseract OCRのプロジェクトページの一部をキャプチャし、切り出してきてビットマップファイルとして保存したものです。)

tesseract-input.png

そして、コマンドプロンプトから test.exe を実行して出てきた出力は以下の通り。

result: [A||OCRE||gnel7|atwasdevel0pedatHPLahsl>e\weev|l986a|dl995 mammasmge

]

あ、あれ…?
ところどころ合ってるように見えなくもないけど…。もしかしたら文字が小さすぎたのかも? ブラウザの表示で文字を大きめにして再度キャプチャし、以下の画像で再挑戦。

tesseract-input2.png


実行して出てきたのは以下の通り。

result: [An OCR Engine that was developed al HP Labs belween 1985 and 1995 and now at Google

]

まだ一部おかしいところは残っているものの(「at」が「al」になっているなど)、それなりにちゃんと読めているようです。

時間があれば、もうちょっと調べていきたいところです。


IDEでビルドする場合の注意

もしVisual C++のIDEでお試しプログラムのプロジェクトを作成してビルドする場合は、上記のmakefileの内容を参考に、追加のincludeディレクトリや追加のライブラリディレクトリ、追加の依存ファイルを指定する必要があります。

また、TesseractライブラリはWindows以外のOSでビルドされることも想定しており、Windowsでビルドする場合にはプリプロセッサマクロ「__MSW32__」を定義しなければならないことに注意してください(上記のmakefileでは「/D__MSW32__」コンパイルオプションが該当)。

ただし、(上記の方法のダウンロードではなく、)Subversionリポジトリから最新のリビジョンのソースを取ってきている場合は __MSW32__ マクロを定義する必要はありません。リビジョン677にて __MSW32__ ではなく _WIN32 (Visual C++コンパイラで自動的に定義されるマクロ) を参照するように修正されている模様です。(Subversionから取ってくる場合はLeptonicaライブラリも別に取ってくる必要があったりして何かと面倒そうではあるのですが。)

現在の最新リリースであるVer.3.01はリビジョン636に相当するので、Ver.3.01では __MSW32__ マクロを定義しておく必要があります。


参考

Tesseract OCRに触ってみた - takminの書きっぱなし備忘録
http://d.hatena.ne.jp/takmin/20110720/1311176261

拍手

PR

コメント
無題
「その結果出来上がったお試しプログラムは以下の通り。「tesseractmain.cpp」を簡略化したものになっています。ビットマップファイル input.bmp を読み込み、文字列をコンソールに出力するようにしています。」
のところとその下のソースをVisual2010C++でどうやって組み込みますか?親フォルダは何のフォルダですか?自分はTessdataに入れましたが。
【2012/06/19 17:47】 NAME[スズキ] WEBLINK[] EDIT[]
Re:無題
ここで作成されたお試しプログラムでは、コマンドプロンプトのパラメータにファイル名を指定します。
test.exe と同じフォルダに input.bmp を置いて、以下のようにパラメータに渡します。

D:\dev\tesseracttest> test.exe input.bmp

または、完全パスでも指定可能です。

D:\dev\tesseracttest> test.exe D:\dev\tesseracttest\input.bmp
【2012/06/19 22:54】
無題
ご返答ありがとうございます。まだ理解不足ですみませんが、以下の質問の返答をお願いします。

#include <iostream>
#include "baseapi.h"
#include "strngs.h"

int main(int argc, char* argv[])
{
tesseract::TessBaseAPI tessBaseApi;
tessBaseApi.Init(
argv[0], // データパス (tessdata の親ディレクトリ名)
"eng"); // 言語 "eng", "jpn" など

STRING output;
bool success = tessBaseApi.ProcessPages(
"input.bmp", // 入力ファイル名
NULL, // リトライconfigファイル名
0, // タイムアウト値(msec) (0 は指定なし)
&output); // 出力文字列

if (!success) {
std::cout << "Error occurred.\n";
} else {
std::cout << "result: [" << output.string() << "]\n";
}

return success ? 0 : 1;
}

上記のソースは。「tesseractmain.cpp」を簡略化と言いますが、つまり「tesseractmain.cpp」の中にある全てのソースを削除し、書き換えるのですか?
【2012/06/20 10:39】 NAME[スズキ] WEBLINK[] EDIT[]
無題
現在そのお試しプログラムはお手元にあったら頂いてもよろしいのでしょうか?
【2012/06/20 10:42】 NAME[スズキ] WEBLINK[] EDIT[]
無題
また、上記のソースを単純にC++ファイルを制作し、ビルドしたらこのような失敗が出ています:
tesseract-3.01\test\test\test.cpp(2): fatal error C1083: include ファイルを開けません。'baseapi.h': No such file or directory

ここで、この"baseapi.h"ファイルが無いということがわかりました。やはり最初の親フォルダはtesseract-3.01フォルダではなく、Apiフォルダに指定するのですか?
【2012/06/20 10:50】 NAME[スズキ] WEBLINK[] EDIT[]
無題
Apiフォルダに指定して、ビルドしたらまたこんなエラーが出ました:

tesseract-3.01\api\apitypes.h(23): fatal error C1083: include ファイルを開けません。'publictypes.h': No such file or directory

いろいろ探しましたが、Publictypes.hファイルを見つかりませんので、どうすればいいんですか?
【2012/06/20 11:00】 NAME[スズキ] WEBLINK[] EDIT[]
Re:無題
すでにライブラリファイル(libtesseract.lib)が vs2010\Release フォルダにできているでしょうか?
できているならば、Tesseractのプロジェクトは閉じてしまって構いません。

このブログ記事のサンプルプログラムは、VC++のコマンドプロンプトコンパイラを使ってビルドしています。
もしもVC++のIDEを使いたいのであれば、以下の手順を実施してください

1.新しいプロジェクト(Win32コンソールアプリケーション)を作成する

2.対象の構成を「Release」に変更する

3.プロジェクトのプロパティを開き、
  構成プロパティ → C/C++ → 全般 → 追加のインクルードディレクトリ
 に以下のフォルダをすべて追加します。
   D:\dev\tesseract-3.01\api
   D:\dev\tesseract-3.01\ccstruct
   D:\dev\tesseract-3.01\ccutil
   D:\dev\tesseract-3.01\ccmain

 もしTesseractを別のフォルダに格納している場合は、それに合わせてパスを変更してください

4.同様に、プロジェクトのプロパティで
  構成プロパティ → C/C++ → プリプロセッサ → プリプロセッサの定義
 に、「__MSW32__」を追加します。

5.プロジェクトのプロパティで
  リンカー → 全般 → 追加のライブラリディレクトリ
 に以下のフォルダを追加します。
   D:\dev\tesseract-3.01\vs2010\Release
   D:\dev\tesseract-3.01\vs2008\lib

 もしTesseractを別のフォルダに格納している場合は、それに合わせてパスを変更してください

6.プロジェクトのプロパティで
  リンカー → 入力 → 追加の依存ファイル
 に以下のファイル名を追加します。
   libtesseract.lib
   liblept-static-mtdll.lib

7.お試しプログラムのソースコードを書いてビルドする。
 (VC++のIDEはデフォルトでプリコンパイル済みヘッダーを使うので、
  最初に stdafx.h をインクルードする必要があります。)
【2012/06/20 22:56】
無題
ご返答ありがとうございました。早速試してみます。もしわからないことがあったらまたよろしくお願いします。
【2012/06/22 12:27】 NAME[スズキ] WEBLINK[] EDIT[]
無題
質問です。
コメント欄で回答してくださっている
VC++のIDEでの手順に沿ってビルドしたのですが、
host.hとserialis.hのヘッダファイルにおいてエラーが出てしまいます。
初心者の質問だと思いますが、何か方法がありましたら教えていただきたいです。。
以下がエラーの内容です。
よろしくお願いします。

構文エラー : ';' が、識別子 'inT64' の前に必要です。
構文エラー : ';' が、識別子 'reverse64' の前に必要です。
構文エラー : ';' が、識別子 'uinT64' の前に必要です。
型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
識別子 "INT64" が定義されていません
識別子 "UINT64" が定義されていません
【2012/11/23 20:06】 NAME[いとう] WEBLINK[] EDIT[]
Re:無題
プリプロセッサの定義に「__MSW32__」を追加する手順が抜けているものと思われます。
確認してみてください。
【2012/11/24 12:32】
無題
素早いお返事ありがとうございます!
とても助かります。

_MSW32_
のアンダーバーは全角のアンダーバーでしょうか??

半角のアンダーバーを用いた定義は出来ています。
もし半角のアンダーバーでしたら、他にエラーの原因はありますでしょうか(>_<)
【2012/11/25 09:20】 NAME[いとう] WEBLINK[] EDIT[]
Re:無題
コピー&ペーストしてみると分かると思いますが、半角のアンダースコア「_」が2個連続で書かれています。
「_」+「_」+「MSW32」+「_」+「_」 という感じです。
【2012/11/25 14:53】
無題
無事エラー解消できました。
本当にありがとうございます!

また違う質問です。何度も申し訳ありません。。
日本語でのOCRをする為にバージョン3.02で動かそうと思ったのですが(バージョン3.01には日本語用がない為)、バージョン3.02にはvs2010用のプロジェクトファイルがなく、vs2008のフォルダにあるlibtesseractをビルドしても、ライブラリファイルが見つけられない状態です。

vs2010上で日本語のOCRを動かすにはどういう手順をふめばよいでしょうか。
バージョン3.02のソースファイルとtesseract用の言語データのダウンロードは出来ています。

よろしくお願いします。
【2012/11/26 16:48】 NAME[いとう] WEBLINK[] EDIT[]
Re:無題
現在の最新リリース(3.02.02)については試していないのでちょっとわからないです。

ただし、3.01でも3.00以上向けの日本語データが使用可能です。
http://code.google.com/p/tesseract-ocr/downloads/detail?name=jpn.traineddata.gz

以前にちょっと試した限りでは、出力がUTF-8で取得されるので、自分でUTF-16なりShift-JISなりに変換する必要があったと記憶しています。
【2012/11/27 22:48】
無題
お礼が遅れてしまい申し訳ありませんでした。
質問にひとつひとつ丁寧に答えてくださり、本当にありがとうございました。
【2012/12/05 23:41】 NAME[いとう] WEBLINK[] EDIT[]
数字に限定したい場合
とても参考になる記事、ありがとうございます。
大変助かっております。

ひとつ質問がございます。

サンプルコードをそのまま実装させておりますが、このサンプルに追加でsetvariableにて数字のみに限定させたいと試みております。

int main(int argc, char* argv[])
{

tesseract::TessBaseAPI tessBaseApi;
tessBaseApi.SetVariable("tessedit_char_whitelist", "0123456789"); // If digit only
tessBaseApi.Init(
argv[0], // データパス (tessdata の親ディレクトリ名)
"eng"); // 言語 "eng", "jpn" など

STRING output;
bool success = tessBaseApi.ProcessPages(
"input.jpg", // 入力ファイル名
NULL, // リトライconfigファイル名
0, // タイムアウト値(msec) (0 は指定なし)
&output); // 出力文字列

if (!success) {
std::cout << "Error occurred.\n";
} else {
std::cout << output.string();
}

return success ? 0 : 1;
}

上記のように
tessBaseApi.SetVariable("tessedit_char_whitelist", "0123456789");
を追加しただけでは数字限定になりませんでした。

可能であればご教授いただけると幸いです。

また以下のサイトに
http://www.pixel-technology.com/freeware/tessnet2/

以下のようなサンプルコードがありました。

Bitmap image = new Bitmap("eurotext.tif");
tessnet2.Tesseract ocr = new tessnet2.Tesseract();
ocr.SetVariable("tessedit_char_whitelist", "0123456789"); // If digit only
ocr.Init(@"c:\temp", "fra", false); // To use correct tessdata
List<tessnet2.Word> result = ocr.DoOCR(image, Rectangle.Empty);
foreach (tessnet2.Word word in result)
Console.WriteLine("{0} : {1}", word.Confidence, word.Text);

上記サンプルにある
tessnet2でないと実現できないのでしょうか。

このような場で大変心苦しいのですが、
よろしくお願いいたします。
【2013/04/26 17:26】 NAME[本田志帆] WEBLINK[] EDIT[]
Re:数字に限定したい場合
SetVariable() は Init() の後で呼び出す必要があるようです。
【2013/05/20 23:33】


コメントフォーム
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード
  Vodafone絵文字 i-mode絵文字 Ezweb絵文字


忍者ブログ [PR]
プロフィール
HN:
はむぱい
職業:
ソフト作ったりしてる人
Twitter
最新CM
[06/09 replica rolex oyster perpetual datejust]
[06/09 bracelets imitation cartier love]
[06/09 replica the oyster perpetual datejust]
[06/09 datejust rolex oyster perpetual]
[06/09 replica gold love bangle]
カレンダー
08 2017/09 10
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
ブログ内検索
あ~いい漢字