プリミティブを8連結で抽出
全ての画像処理の後、テキスト抽出の前に行う。プリミティブを8連結で抽出する。
通常はプリミティブは4連結で抽出されるが、かすれた画像や解像度の低い画像の場合、8連結で抽出した方が精度が高くなる場合がある。
逆に4連結では分離していると処理されるものが8連結では結合されていると処理されるため、却って精度が低くなる場合もある。
/////////////////
// 画像を白黒反転
// 抽出したテキストブロック情報はクリア
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_NEGATE)();
extern GD_NEGATE gd_negate;
/////////////////////
// 画像のノイズを除去
// 抽出したテキストブロック情報はクリア
// 入力
// int noisesize; ノイズのサイズ(1〜noisesizeまでの面積の画素連続領域が除去)
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_DELETENOISE)(int noisesize);
extern GD_DELETENOISE gd_deletenoise;
///////////////////
// 画像を左90度回転
// 抽出したテキストブロック情報はクリア
// 注:画像バッファアドレス、1行のバイト数等が変わるためgd_getimageinfoを再コール
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_ROTATE90)();
extern GD_ROTATE90 gd_rotate90;
///////////////////
// 画像を180度回転
// 抽出したテキストブロック情報はクリア
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_ROTATE180)();
extern GD_ROTATE180 gd_rotate180;
///////////////////
// 画像を右90度回転
// 抽出したテキストブロック情報はクリア
// 注:画像バッファアドレス、1行のバイト数等が変わるためgd_getimageinfoを再コール
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_ROTATE270)();
extern GD_ROTATE270 gd_rotate270;
ノイズ除去におけるnoisesizeは、ノイズとしてみなすプリミティブの最大面積です。1ピクセル〜noisesizeピクセルまでの面積のプリミティブがノイズとして除去されます。
上記の図では、noisesizeを2とした場合にノイズが除去される様子を示しています。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_NEGATE gd_negate;
GD_DELETENOISE gd_deletenoise;
GD_ROTATE90 gd_rotate90;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
int i1;
// DLL関数アドレスの取得
gd_negate = (GD_NEGATE)GetProcAddress(gd_dllinstance,"gd_negate");
if(gd_negate != NULL) {
// 画像の白黒を反転する
i1 = gd_negate();
}
gd_deletenoise = (GD_DELETENOISE)GetProcAddress(gd_dllinstance,"gd_deletenoise");
if(gd_deletenoise != NULL) {
// 7ピクセル以下のプリミティブをノイズとして削除する
i1 = gd_deletenoize(7);
}
gd_rotate90 = (GD_ROTATE90)GetProcAddress(gd_dllinstance,"gd_rotate90");
if(gd_rotate90 != NULL) {
i1 = gd_rotate90();
if(i1 < 0) エラー;
// 画像情報の取得
i1 = gd_getimageinfo(&pdata,&width,&height,&scanlinesize,&dpi,&background);
if(i1 < 0) エラー;
}
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
3.5 テキストブロック抽出パラメータ設定
目次
テキスト抽出パラメータをパラメータ構造体あるいはパラメータファイルで指定します。
gd_setparameter パラメータを構造体で指定
gd_setparameterfile パラメータをファイルで指定
パラメータファイルは、テキストエディタで編集できるテキスト形式ファイルですが、画像見て試しながらパラメータファイルを作成するツールが提供されます。
パラメータの制限を緩くすると、広範なタイプの文書画像に対応できます。ただし、広く適用できる分、精度が低くなります。主要な文書タイプ別のパラメータファイルは標準で提供されます。
高い精度を求める場合は、制限の厳しいパラメータを使って精度の高い抽出を行うことができます。
///////////////////////////////
// テキスト抽出パラメータの設定
// 入力
// ABSTRACTPARAMETER* parameter; パラメータ
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SETPARAMETER)(ABSTRACTPARAMETER* parameter);
extern GD_SETPARAMETER gd_setparameter;
///////////////////////////////////////
// テキスト抽出パラメータファイルの設定
// 入力
// char* filename; ファイル名
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SETPARAMETERFILE)(char* filename);
extern GD_SETPARAMETERFILE gd_setparameterfile;
パラメータの内容にはテキストブロック抽出パラメータを参照してください。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_SETPARAMETER gd_setparameter;
GD_SETPARAMETERFILE gd_setparameterfile;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
int i1;
// DLL関数アドレスの取得
gd_setparameter = (GD_SETPARAMETER)GetProcAddress(gd_dllinstance,"gd_setparameter");
if(gd_setparameter != NULL) {
ABSSTRACTPARAMETER parameter;
parameter.mdpi = 300;
parameter.mcontrol = ABSTRACT_SEPARATOR | ANSTRACT_DISTXY;
parameter.minpixelwidth = 15;
.......
// 構造体を直接指定してパラメータ設定
i1 = gd_setparameterfile(¶meter);
}
gd_setparameterfile = (GD_SETPARAMETERFILE)GetProcAddress(gd_dllinstance,"gd_setparameterfile");
if(gd_setparameterfile != NULL) {
// default.prmというパラメータファイルでパラメータ設定
i1 = gd_setparameterfile("default.prm");
}
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
3.6 テキストブロック抽出
目次
gd_abstract テキストブロック抽出
gd_cleartextblock テキストブロッククリア
gd_getarea テキストブロック取得
指定したパラメータを使って、テキストブロックを抽出します。抽出はレイヤモデルに基づいて行われます。最初全ての画像はレイヤ0にあって、抽出したテキストはレイヤ1に移動します。
複数のパラメータを用いて複数パスでテキストブロック抽出を実行することができます。
例えばパス1で横書きのテキストブロックを抽出します。
横書きのテキストブロックがレイヤ1に移動します。
例えばパス2で縦書きのテキストブロックを抽出します。この場合、レイヤ0に残った画像が抽出の対象となります。
テキストブロッククリア関数を呼び出すことで、全てのテキストブロック情報をクリアして、画像を全てレイヤ0に戻します。パラメータを変更してあたらに抽出をやり直すときなどに、この関数を呼び出します。
画像を新たに読み込んだとき、ノイズを除去した時、画像を反転た時には、自動的にテキストブロック情報は削除されるために、特にこの関数を呼ぶ必要はありません。
テキストブロック取得関数は、レイヤ1にあるテキストブロック全てを返す仕様になっています。テキストブロック抽出関数が、レイヤ1に移動したテキストブロックを返すので、複数パスに分けるときは、その合計がレイヤ1のテキストブロック数となります。
///////////////////////
// テキストブロック抽出
// 返り値
// 0以上...正常終了(抽出したテキストブロックの数)
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_ABSTRACT)();
extern GD_ABSTRACT gd_abstract;
/////////////////////////
// テキストブロッククリア
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_CLEARTEXTBLOCK)();
extern GD_CLEARTEXTBLOCK gd_cleartextblock;
///////////////////////
// テキストブロック取得
// 入力
// int index; インデックス(0〜テキストブロック数-1)
// 出力
// RECT* prect; 矩形座標
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GETAREA)(int index,RECT* prect);
extern GD_GETAREA gd_getarea;
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_ABSTRACT gd_abstract;
GD_CLEARTEXTBLOCK gd_cleartextblock;
GD_GETAREA gd_getarea;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
int i1;
int textblocknum;
// DLL関数アドレスの取得
gd_abstract = (GD_ABSTRACT)GetProcAddress(gd_dllinstance,"gd_abstract");
if(gd_abstract != NULL) {
// textblocknumに抽出したテキストブロック数が入る
textblocknum = gd_abstract();
}
gd_cleartextblock = (GD_CLEARTEXTBLOCK)GetProcAddress(gd_dllinstance,"gd_cleartextblock");
if(gd_cleartextblock != NULL) {
// 抽出したテキストブロック情報を全て削除
i1 = gd_cleartextblock();
}
gd_getarea = (GD_GETAREA)GetProcAddress(gd_dllinstance,"gd_getarea");
if(gd_getarea != NULL) {
for(int i = 0 ; i < textblocknum ; i++) {
RECT rect;
i1 = gd_getarea(i,&rect);
if(i1 == 0) {
// 何らかの形でテキストブロックと登録
}
}
}
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
3.7 認識エンジンの初期化と解放
目次
gd_initocr OCR初期化
gd_freeocr OCR解放
認識用の辞書のパスを指定して文字認識エンジンを初期化します。
初期化関数を重複して呼び出しても、2回目以降は無視されます。
辞書の組み合わせを変えるには、OCR解放関数を呼び出してから再度OCR初期化関数を呼び出します。
ライブラリ終了時に、あえてOCR解放を呼び出す必要はありません。
///////////////
// OCR初期化
// 再初期化するにはgfreeocrをコールした後にもう一度コール
// 入力
// char* dicpath; // システム辞書のあるディレクトリ
// // 最後はディレクトリ区切り文字(ex. d:\ocr\dic\)
// char* userdictname; // ユーザー辞書名
// // 拡張子なし(ex. user)
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_INITOCR)(char* dicpath,char* userdictname);
extern GD_INITOCR gd_initocr;
/////////////
// 通常は呼ぶ必要はない
// 再初期化する直前にコールする
// OCR解放
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_FREEOCR)();
extern GD_FREEOCR gd_freeocr;
gd_initocrでは、認識用の辞書のあるディレクトリとユーザー辞書名を指定します。
認識用のシステム辞書は名前固定で以下のようになっています。
基本辞書 |
辞書名 | レコードファイル名 | キーファイル名 | 内容 |
---|
system | system.dbs | system.key | 必須 |
systemfat | systemfat.dbs | systemfat.key | 必須 |
オプション辞書(差分辞書) |
diff0 | diff0.dbf | diff0.kef | 楷書体 |
diff1 | diff1.dbf | diff1.kef | 低品質かすれ文字 |
diff2 | diff2.dbf | diff2.kef | 低品質つぶれ文字 |
diff3 | diff3.dbf | diff3.kef | 数字 |
diff4 | diff4.dbf | diff4.kef | 英字 |
diff5 | diff5.dbf | diff5.kef | かな |
ユーザー辞書名は、ユーザー辞書のファイル名の拡張子を抜いたのもです。
名前は自由ですが、システム辞書と同じディレクトリに存在しなければなりません。
認識エンジンは、API関数FreeLibrary呼び出し時に自動的に解放されるので、終了時にgd_freeocrを呼ぶ必要はありません(別に呼び出しても構いません)。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_INITOCR gd_initocr;
GD_FREEOCR gd_freeocr;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
int i1;
// DLL関数アドレスの取得
gd_initocr = (GD_INITOCR)GetProcAddress(gd_dllinstance,"gd_initocr");
// システム辞書はd:\dic\に格納されている。
// ユーザー辞書はd:\dic\user.*(一つのユーザー辞書にファイルは4つある)を用いる
i1 = gd_initocr("d:\\dic\\","user");
gd_freeocr = (GD_FREEOCR)GetProcAddress(gd_dllinstance,"gd_freeocr");
// 一旦解放して再初期化
i1 = gd_freeocr();
i1 = gd_initocr("d:\\dic\\","user1");
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
3.8 認識
目次
テキストブロックのインデックスあるいはテキストブロックの位置を指定して文字認識を実行します。
テキストプロック抽出で自動抽出したものはgd_execocr1で、ユーザーがテキストブロックの外接矩形を指定したものはgd_execocr2で文字認識を実行します。
gd_execocr1 インデックス指定OCR
gd_execocr2 位置指定OCR
/////////////////////////
// インデックス指定OCR
// 入力
// int index; // テキストブロックインデックス
// // 0〜テキストブロック数-1
// unsigned long chartype1; // 文字種フラグ1
// unsigned long chartype2; // 文字種フラグ2
// int tateyoko; // 0...横書き/1...縦書き
// int baseline; // 0...通常/1...90度左回転/2...180度回転/3...90度右回転
// 横書き 0 1 2 3
// +-------+ +-------+ +=======+ +-------+
// | ABCDE | | || | | || |
// | | | || | | || |
// +=======+ +-------+ +-------+ +-------+
// 縦書き 0 1 2 3
// +-------+ +=======+ +-------+ +-------+
// | あ || | | || | | |
// | い || | | || | | |
// +-------+ +-------+ +-------+ +=======+
// int insideflag; // 0...テキストブロック矩形をそのまま認識
// // 1...テキストブロック矩形の枠に接触するプリミティブを除く
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_EXECOCR1)(int index,unsigned long chartype1,unsigned long chartype2,int tateyoko,int baseline,int insideflag,int resultbuffersize,int* presultnum,DOCRResult* pocrresult);
extern GD_EXECOCR1 gd_execocr1;
/////////////////
// 位置指定OCR
// 入力
// RECT rect; // テキストブロック外接長方形
// unsigned long chartype1; // 文字種フラグ1
// unsigned long chartype2; // 文字種フラグ2
// int tateyoko; // 0...横書き/1...縦書き
// int baseline; // 0...通常/1...90度左回転/2...180度回転/3...90度右回転
// 横書き 0 1 2 3
// +-------+ +-------+ +=======+ +-------+
// | ABCDE | | || | | || |
// | | | || | | || |
// +=======+ +-------+ +-------+ +-------+
// 縦書き 0 1 2 3
// +-------+ +=======+ +-------+ +-------+
// | あ || | | || | | |
// | い || | | || | | |
// +-------+ +-------+ +-------+ +=======+
// int insideflag; // 0...テキストブロック矩形をそのまま認識
// // 1...テキストブロック矩形の枠に接触するプリミティブを除く
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_EXECOCR2)(RECT rect,unsigned long chartype1,unsigned long chartype2,int tateyoko,int baseline,int insideflag,int resultbuffersize,int* presultnum,DOCRResult* pocrresult);
extern GD_EXECOCR2 gd_execocr2;
テキストブロックのインデックスは、0〜テキストブロック数-1までの範囲のインデックスを指定して文字認識を実行します。
文字種フラグに関しては、文字種フラグを参照してください。
tateyokoは横書きが0、縦書きが1となります。
baselineは横書き、縦書きに応じて以下のようになります。回転の無い横書き、縦書きのテキストブロックのベースラインは0となります。下図参照
insideflagが0だと、テキストブロック矩形の内部をそのまま認識します。1の場合は、テキストブロック矩形の枠に接触するプリミティブを除いて認識します。テキストブロック矩形内に図形の一部が侵入している場合などに指定します。
resultbuffersizeはpocrresultバッファの配列数を示し、実際に格納された認識結果の数が*presultnumに返ります。
返り値がBUFFER_OVERFLOWエラーの場合、resultbuffersize以上の認識結果があったことを示しています。
BUFFER_OVERFLOWエラーの場合もresultbuffersizeまでは認識結果が格納されます。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_EXECOCR1 gd_execocr1;
GD_EXECOCR2 gd_execocr2;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
int i1;
DOCRResult pocrresult[256];
RECT rect;
rect.left = 1000;
rect.top = 1000;
rect.right = 1500;
rect.bottom = 1050;
int resultnum;
// DLL関数アドレスの取得
gd_execocr1 = (GD_EXECOCR1)GetProcAddress(gd_dllinstance,"gd_execocr1");
// 最初のテキストブロックをアスキー英数字、横書き、回転無しで認識
i1 = gd_execocr1(0,CHAR_SET_ALPHABET | CHAR_SET_NUMBER,CHAR_SET_ASCII,0,0,256,&resultnum,pocrresult);
// (1000,1000)-(1500,1050)の範囲をアスキー英数字、横書き、回転無しで認識
gd_execocr2 = (GD_EXECOCR2)GetProcAddress(gd_dllinstance,"gd_execocr2");
i1 = gd_execocr2(rect,CHAR_SET_ALPHABET | CHAR_SET_NUMBER,CHAR_SET_ASCII,0,0,256,&resultnum,pocrresult);
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
3.9 ユーザー辞書登録
目次
画像の中の特定のパターンをユーザー辞書に登録します。
///////////////////
// ユーザー辞書登録
// 入力
// RECT rect; // 登録パターンの外接矩形
// 第2引数は常に0(将来の拡張用)
// char* code; // パターンの登録コード(通常1文字)
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_PUT)(RECT rect,int baseline,char* coode);
extern GD_PUT gd_put;
rectで登録パターンの外接矩形を指定します。
第2引数は常に0を指定します。将来の拡張用です
パターンの登録コードは、文字列で指定します。通常は漢字1文字を指定します。登録コードはKEYSIZE_MAX==16バイト以下の文字列で例えば、記号"〒"の画像を"郵便番号"として登録することもできます。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_PUT gd_put;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
int i1;
RECT rect;
rect.left = 1000;
rect.top = 1000;
rect.right = 1050;
rect.bottom = 1050;
// DLL関数アドレスの取得
gd_put = (GD_PUT)GetProcAddress(gd_dllinstance,"gd_put");
if(gd_put != NULL) {
// rectで示される範囲をコード"漢"で登録
i1 = gd_put(rect,0,"漢");
}
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
3.10 ユーザー辞書参照と削除
目次
gd_getvalidrecordnum ユーザー辞書登録数取得
gd_seekhead 先頭レコードにユーザー辞書シーク
gd_seekprev10 10前のレコードにシーク
gd_seekprev1 1前のレコードにシーク
gd_seeknext1 1後のレコードにシーク
gd_seeknext10 10後のレコードにシーク
gd_seektail 末尾のレコードにシーク
gd_getkey 現在のシークポインタのキーを取得
gd_getrecord 現在のシークポインタのレコードを取得
gd_del 現在のシークポインタのキー・レコードを削除
/////////////////////////
// ユーザー辞書登録数取得
// 返り値
// 0以上....正常終了(ユーザー辞書登録数)
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GETVALIDRECORDNUM)();
extern GD_GETVALIDRECORDNUM gd_getvalidrecordnum;
/////////////////////////
// ユーザー辞書シーク(先頭)
// 返り値
// 0...シークポインタ変わらず
// 1...先頭へシーク
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SEEKHEAD)();
extern GD_SEEKHEAD gd_seekhead;
///////////////////////////
// ユーザー辞書シーク(10前)
// 返り値
// 0......シークポインタ変わらず
// 正数...いくつシークしたか
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SEEKPREV10)();
extern GD_SEEKPREV10 gd_seekprev10;
///////////////////////////
// ユーザー辞書シーク(1前)
// 返り値
// 0...シークポインタ変わらず
// 1...1前へシーク
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SEEKPREV1)();
extern GD_SEEKPREV1 gd_seekprev1;
///////////////////////////
// ユーザー辞書シーク(1後)
// 返り値
// 0...シークポインタ変わらず
// 1...1後へシーク
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SEEKNEXT1)();
extern GD_SEEKNEXT1 gd_seeknext1;
///////////////////////////
// ユーザー辞書シーク(10後)
// 返り値
// 0......シークポインタ変わらず
// 正数...いくつシークしたか
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SEEKNEXT10)();
extern GD_SEEKNEXT10 gd_seeknext10;
///////////////////////////
// ユーザー辞書シーク(末尾)
// 返り値
// 0...シークポインタ変わらず
// 1...末尾へシーク
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SEEKTAIL)();
extern GD_SEEKTAIL gd_seektail;
ユーザー辞書のパターンの参照と削除は、シークポインタをターゲットレコードに移動してから実行します。
gd_getvalidrecordnumは、ユーザー辞書に含まれる非削除レコードの数を返します。
現在のレコード数が0の場合、gd_seekhead、gd_seektailは0を返します。
現在のシークポインタが先頭である場合、gd_seekprev10、gd_seekprev1は0を返します。
また、先頭からのレコード数が10未満の場合、gd_seekprev10は、先頭レコードで停止します。
現在のシークポインタが末尾である場合、gd_seeknext1、gd_seeknext10は0を返します。
また、末尾までのレコード数が10未満の場合、gd_seeknext10は、末尾レコードで停止します。
gd_seekprev10、gd_seeknext10は実際にシークしたレコード数(最大10)を返します。
ファイル関連のエラーが生じた場合、いずれの関数も負のエラーコードを返します。
/////////////////////////////
// シークポインタのキーを取得
// 入力
// int keybuffersize; // キーバッファのサイズ(KEYSIZE_MAX以上)
// void* keybuffer; // キーバッファ
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GETKEY)(int keybuffersize,char* keybuffer);
extern GD_GETKEY gd_getkey;
/////////////////////////////////////////
// シークポインタのパターンレコードを取得
// 入力
// int recordbuffersize; // レコードバッファのサイズ(288バイト)
// void* record; // パターンレコード(48×48ピクセル2値モノクロ、288バイト)
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GETRECORD)(int recordbuffersize,void* record);
extern GD_GETRECORD gd_getrecord;
/////////////////////////////
// シークポインタのキーを削除
// 返り値
// 0.......正常終了
// 負.......エラー(エラーコード定義参照)
typedef int (__cdecl* GD_DEL)();
extern GD_DEL gd_del;
キー取得関数は、キー取得バッファとバッファサイズkeybuffersizeを指定してコールします。
キー取得バッファのサイズは、KEYSIZE_MAX("ocrdef.h"で定義)に定義されている値を用います。
パターンレコードの取得は、レコードバッファと、バッファサイズrecordbuffersizeを指定してコールします。
パターンレコードバッファのサイズは288バイト、パターンレコードは48×48ピクセル(288バイト)の2値モノクロ画像データとして返ります。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_GETVALIDRECORDNUM gd_getvalidrecordnum;
GD_SEEKHEAD gd_seekhead;
GD_SEEKPREV10 gd_seekprev10;
GD_SEEKPREV1 gd_seekprev1;
GD_SEEKNEXT1 gd_seeknext1;
GD_SEEKNEXT10 gd_seeknext10;
GD_SEEKTAIL gd_seektail;
GD_GETKEY gd_getkey;
GD_GETRECORD gd_getrecord;
GD_DEL gd_del;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
int i1;
// DLL関数アドレスの取得
gd_getvalidrecordnum = (GD_GETVALIDRECORDNUM)GetProcAddress(gd_dllinstance,"gd_getvalidrecordnum");
if(gd_getvalidrecordnum != NULL) {
// recordnumにユーザー辞書に登録されているパターンの数が返る
int recordnum = gd_getvalidrecordnum();
}
gd_seekhead = (GD_SEEKHEAD)GetProcAddress(gd_dllinstance,"gd_seekhead");
if(gd_seekhead != NULL) {
// 先頭レコードにシーク
i1 = gd_seekhead();
if(i1 == 1) {
// シークした
}
else if(i1 == 0) {
// 先頭レコードが無い=登録レコード数が0
}
else {
// エラー
}
}
gd_seekprev10 = (GD_SEEKPREV10)GetProcAddress(gd_dllinstance,"gd_seekprev10");
if(gd_seekprev10 != NULL) {
// 10前のレコードにシーク(先頭にぶつかった時点で停止)
i1 = gd_seekprev10();
if(i1 > 0) {
// シークした
}
else if(i1 == 0) {
// すでに先頭レコード
}
else {
// エラー
}
}
gd_seekprev1 = (GD_SEEKPREV1)GetProcAddress(gd_dllinstance,"gd_seekprev1");
if(gd_seekprev1 != NULL) {
// 1前のレコードにシーク
i1 = gd_seekprev1();
if(i1 == 1) {
// シークした
}
else if(i1 == 0) {
// すでに先頭レコード
}
else {
// エラー
}
}
gd_seeknext1 = (GD_SEEKNEXT1)GetProcAddress(gd_dllinstance,"gd_seeknext1");
if(gd_seeknext1 != NULL) {
i1 = gd_seeknext1();
if(i1 == 1) {
// シークした
}
else if(i1 == 0) {
// すでに末尾レコード
}
else {
// エラー
}
}
gd_seeknext10 = (GD_SEEKNEXT10)GetProcAddress(gd_dllinstance,"gd_seeknext10");
if(gd_seeknext10 != NULL) {
i1 = gd_seeknext10();
if(i1 > 0) {
// シークした
}
else if(i1 == 0) {
// すでに末尾レコード
}
else {
// エラー
}
}
gd_seektail = (GD_SEEKTAIL)GetProcAddress(gd_dllinstance,"gd_seektail");
if(gd_seektail != NULL) {
i1 = gd_seektail();
if(i1 == 1) {
// シークした
}
else if(i1 == 0) {
// すでに先頭レコード
}
else {
// エラー
}
}
gd_getkey = (GD_GETKEY)GetProcAddress(gd_dllinstance,"gd_getkey");
gd_getrecord = (GD_GETRECORD)GetProcAddress(gd_dllinstance,"gd_getrecord");
unsigned int keysize = KEYSIZE_MAX;
unsigned int recordsize = REG_FONT_SIZE;
char key[KEYSIZE_MAX];
char buffer[REG_FONT_SIZE];
int i1 = gd_getkey(keysize,key);
if(i1 == 1) {
gd_getrecord(recordsize,buffer);
}
gd_del = (GD_DEL)GetProcAddress(gd_dllinstance,"gd_del");
if(gd_del != NULL) {
// 現在のシークポインタのレコードを削除
i1 = gd_del();
}
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
3.11 グレイスケール表示サポート(機能制限あり)
目次
グレイスケール表示をサポートします。表示倍率1.0倍未満のモノクロ画像の縮小表示を高品位グレイスケール画像として取得します。ただし、このdllでは、モノクロ画像のバウンダリは1バイトの場合のみサポートしています。
/////////////////////
// グレイスケール画像初期化
// 画像データのバイトバウンダリが1の場合のみサポート(gd_loadimageの第2引数が1)
// 画像データが更新されたとき、倍率が変わったときにコール
// 入力
// double amag; 表示倍率(等倍=1.0未満)
// 出力
// void** pgray; グレイスケール画像(pgray==NULLの場合はメモリ不足)
// ライブラリ内部でバッファ管理されるためfreeやrealloc等は不可
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GRAYSCALEINIT)(double amag,void** pgray);
extern GD_GRAYSCALEINIT gd_grayscalefastinit;
extern GD_GRAYSCALEINIT gd_grayscalefineinit;
///////////////////////////////
// グレイスケール画像矩形内作成
// 画像データが更新されたとき、倍率が変わったときにコール
// 入力
// double amag; 表示倍率(等倍=1.0未満)
// int x1; (x1,y1)-(x2,y2)の矩形内の画像を作成
// int y1;
// int x2;
// int y2;
// 返り値
// 0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GRAYSCALERECT)(double amag,int x1,int y1,int x2,int y2);
extern GD_GRAYSCALERECT gd_grayscalefastrect;
extern GD_GRAYSCALERECT gd_grayscalefinerect;
amagは1.0未満の表示倍率を指定します。
画像データが新規に読み込まれたとき、画像データが更新されたとき、画像の倍率が変わったときに必ずコール初期化関数をコールします。
実際に表示画像を作成するには、クライアント領域に相当するクライアント座標を引数として画像を作成します。初期化後にグレイスケール画像を作成するクライアント領域が重複しても、計算は重複しないように工夫されているため、スクロール時は、スクロールで新たに表れた部分だけが計算されます。
以下の1と2が、低品質・高速のグレイスケール画像取得です。低品質といっても、モノクロ縮小画像と比較すれば、相当の高品質となります。
以下の3と4が、高品質・低速のグレイスケール画像取得です。低速といっても、Pentium IIIクラスだと、それ程気になるほどではありません。
1と2、3と4はそれぞれ対で使うようになっており、混在して使うことは絶対にできません。
現在は、バイトバウンダリ1バイトの画像のみサポートしています。
- gd_grayscalefastinit
- gd_grayscalefastrect
- gd_grayscalefineinit
- gd_grayscalefinerect
サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE gd_dllinstance;
GD_GRAYSCALEINIT gd_grayscalefastinit;
GD_GRAYSCALERECT gd_grayscalefastrect;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
...
// DLL関数アドレスの取得
gd_grayscalefastinit = (GD_GRAYSCALEINIT)GetProcAddress(gd_dllinstance,"gd_grayscalefastinit");
gd_grayscalefastrect = (GD_GRAYSCALERECT)GetProcAddress(gd_dllinstance,"gd_grayscalefastrect");
if(gd_gd_grayscalefastinit != NULL) {
unsigned char* gray; // グレイスケール画像のアドレス
... // 画像読み込み・表示倍率変更等
// 表示倍率0.61倍の画像を取得する
i1 = gd_grayscalefastinit(0.61,(void**)&gray);
if(i1 < 0) エラー;
}
if(gd_gd_grayscalefastrect != NULL) {
... // スクロール、ウィンドウの表示等で、表示領域更新の必要が生じた
// 更新領域は(100,100)-(500,400)
// 以前の領域と重なっていた場合、再計算は必要最小限の部分に限定
i1 = gd_grayscalefastrect(0.61,100,100,500,400);
if(i1 < 0) エラー;
... 表示等(SetDIBitmapToDevice?)
}
// DLLの解放
FreeLibrary(gd_dllinstance);
}
目次
4 バージョン 2.0追加API
Version 1.0のように、
- 初期化
- 画像読み込み
- パラメータの設定
- 認識結果の取得
- 出力
と複数の手順を踏まなければ成らない処理が、Version 2.0では、
- 画像読み込み+認識+出力
のひとつの手順(API)で処理することができます。
Version 1.0では、新聞のような複雑な段組の文書には対応できませんでした。
Ver. 2.0では、一般文書(新聞のような複雑な段組の文書も含む)に限定して認識パラメ
ータの設定が不要なAPIを提供しました。APIひとつだけで画像の読み込みから
透明テキスト付きのPDFファイルへの出力までを実行できるようにしました。
目次
4.1 画像→透明テキスト付きPDF変換
目次
Version 2.0 対応画像フォーマット
- BMP(モノクロ2値、256階調グレイスケール)
- TIFF(モノクロ2値、256階調グレイスケール)
Version 3.0 対応画像フォーマット
- BMP(モノクロ2値、256階調グレイスケール、24ビットカラー)
- TIFF(モノクロ2値、256階調グレイスケール、24ビットカラー)
- PDF(モノクロ2値(JBIG圧縮は未対応)、256階調グレイスケール、24ビットカラー)
- JPEG(256階調グレイスケール、24ビットカラー)
- PNG(モノクロ2値、256階調グレイスケール、24ビットカラー)
- GIF(モノクロ2値、256階調グレイスケール)
- JPEG2000(256階調グレイスケール、24ビットカラー)
上記の文書画像を入力し、文字認識結果を透明テキストとして元の画像に合成したPDFファイルを出力します。
// 画像ファイル-->透明テキスト付きPDF変換
// 入力
// char* imgfilename; // 入力画像ファイル名
// char* pdffilename; // 出力PDFファイル名
// char* inifilename; // 動作コントロール用のiniファイル
// int flag; // 0....画像の上に、テキストを上書き(テキストの下の元の画像は見えない)
// // 1....画像の上に、透明テキストを上書き(元の画像はそのまま)
// int (__cdecl *feedback)(int percent);
// // 進捗報告フィードバック関数(1〜100%の範囲で進捗程度を返す)
// 戻り値
// 0....正常終了
// 負...エラー
typedef int (__cdecl* GD_IMG2PDF)(char* imgfilename,char* pdffilename,char* inifilename,int flag);
extern GD_IMG2PDF gd_img2pdf;
typedef int (__cdecl* GD_IMG2PDFFB)(char* imgfilename,char* pdffilename,char* inifilename,int flag,int (__cdecl *feedback)(int percent));
extern GD_IMG2PDFFB gd_img2pdffb;
ファイル名の拡張子によって画像フォーマットを判断します。iniファイルは
- [General]セクション、guiflagキー
0の時は、エラーがあってもダイアログを出さない、1のときはダイアログを出す。
- [General]セクション、rotatespecキー
- 0の時は、読み込み画像を回転しない
- 1の時は、読み込み画像を左90度回転
- 2の時は、読み込み画像を180度回転
- 3の時は、読み込み画像を左270度回転
- 4の時は、読み込み画像の向きを自動判別回転
- [General]セクション、jpegrateキー
24ビット画像、8ビットグレイスケール画像をPDF画像として出力するときの画質(30〜100、大きいほど画質が良いがサイズが大きくなる)
- [General]セクション、zen2hanflagキー
0の時は、英数字を2バイトコードで出力、1の時は英数字を1バイトコードで出力
- [General]セクション、defaultdpiキー
解像度情報が無い画像ファイルに設定する解像度
サンプルコード
目次
4.2 画像→テキストファイル変換
目次
仕様としては、画像→透明テキスト付きPDFファイル変換と同様であるが、改行コードと1バイトコードと2バイトコードの
切り替えをAPIの引数で指定することができる。1バイトコードと2バイトコードの切り替えは、関数の引数による指示が
iniファイルでの指示よりも優先される。
//////////////////////////
// BMP/TIF-->TXT変換
// 入力
// char* imgfilename; // 入力画像ファイル名
// char* txtfilename; // 出力txtファイル名
// char* inifilename; // 動作コントロール用のiniファイル
// int crflag; // 1...段落内の行単位に改行コード出力
// int zenhanflag; // 1...1バイトコード
// int (__cdecl *feedback)(int percent);
// // 進捗報告フィードバック関数(1〜100%の範囲で進捗程度を返す)
// 戻り値
// 0....正常終了
// 負...エラー
typedef int (__cdecl* GD_IMG2TXT)(char* imgfilename,char* txtfilename,char* inifilename,int crflag,int zenhanflag);
extern GD_IMG2TXT gd_img2txt;
typedef int (__cdecl* GD_IMG2TXTFB)(char* imgfilename,char* txtfilename,char* inifilename,int crflag,int zenhanflag,int (__cdecl *feedback)(int percent));
extern GD_IMG2TXTFB gd_img2txtfb;
サンプルコード
目次
4.3 画像→CSV/XML/Unicodeファイル変換
バッチ処理コマンドは、実際の運用上は、ユーザーに応じてカスタマイズした仕様で提供されることが多い。内容にもよるが、
10〜80万円程度でカスタマイズAPIを提供している。
カスタマイズの例は
- 画像→PDF/CSVファイル変換。CSVファイルには文字単位で位置とサイズの情報を出力(カスタマイズ料:8万円)
- 画像→XMLファイル変換。文字コードはUnicode/指定フォーマットのXMLファイル出力(カスタマイズ料:16万円)
- 奇数ページPDFファイル+偶数ページPDFファイル→透明テキスト付きPDFファイル変換(カスタマイズ料:20万円)
ブックスキャナで奇数ページのみ、偶数ページのみで取り込んだ2つのPDFファイルを1つのPDFファイルに統合変換
- 帳票定義ファイル+PDF帳票ファイル→透明テキスト付きPDFファイル、TSVファイル変換(カスタマイズ料:80万円)
独自仕様の帳票定義ファイルとPDFの帳票画像を読み込んで透明テキスト付きPDF+TSV(タブ区切りファイル)形式の
属性:属性値ファイルを出力
目次
5 バージョン3.0改良・追加API
バージョン3.0では、画像入力およびバッチ処理コマンドにおいてカラー画像対応等を行なった。
Version 2.0 対応画像フォーマット
- BMP(モノクロ2値、256階調グレイスケール)
- TIFF(モノクロ2値、256階調グレイスケール)
Version 3.0 対応画像フォーマット
- BMP(モノクロ2値、256階調グレイスケール、24ビットカラー)
- TIFF(モノクロ2値、256階調グレイスケール、24ビットカラー)
- PDF(モノクロ2値(JBIG圧縮は未対応)、256階調グレイスケール、24ビットカラー)
- JPEG(256階調グレイスケール、24ビットカラー)
- PNG(モノクロ2値、256階調グレイスケール、24ビットカラー)
- GIF(モノクロ2値、256階調グレイスケール)
- JPEG2000(256階調グレイスケール、24ビットカラー)
また、Version 2.0とは逆にGUIを使って対話的に認識処理を進めるためのAPIを追加した。
- テキストブロック(いわゆる段落に相当)をマウス操作で作成する機能
- 認識結果をエディタ上で編集する機能
- 候補文字リストから候補文字を選択する機能
- 誤認識文字を簡潔な操作でユーザー辞書登録する機能
- 以上の操作を取り消したり、やり直したりするアンドゥ・リドゥ機能
目次
5.1 手動テキストブロック指定
目次
目次
5.2 テキストブロック編集
目次
目次
5.3 アンドゥ・リドゥサポート
目次
目次
マニュアルホームページ