ALOCRC Ver. 1.0〜Ver. 3.0 リファレンスマニュアル

目次
  1. DOCRResult構造体
  2. 文字種フラグ
  3. テキストブロック抽出パラメータ
  4. エラーコード
  5. 各論
    1. 画像の読み込み
    2. 画像情報の取得
    3. 画像の保存
    4. 画像処理
    5. テキストブロック抽出パラメータ設定
    6. テキストブロック抽出
    7. 認識エンジン初期化と解放
    8. 認識
    9. ユーザー辞書登録
    10. ユーザー参照と削除
    11. グレイスケール表示サポート(機能制限あり)
  6. バージョン2.0追加API
    1. 画像→透明テキスト付きPDF変換
    2. 画像→テキストファイル変換
    3. 画像→CSV/XML/Unicodeファイル変換
  7. バージョン3.0改良・追加API
    1. 手動テキストブロック指定
    2. テキストブロック編集
    3. アンドゥ・リドゥサポート


マニュアルホームページ


目次

1.DOCRResult構造体

認識結果は以下のような構造体で管理されています。
// パターンの外接矩形
typedef struct _DOCRRect {
    int        x1;            // パターンの左上x座標(段落内正規化座標)
    int        y1;            // パターンの左上y座標(段落内正規化座標)
    int        x2;            // パターンの右下x座標(段落内正規化座標)
    int        y2;            // パターンの右下y座標(段落内正規化座標)
} DOCRRect;
// 認識候補
typedef struct _DCandidate {
    char*           code;       // パターン文字列へのポインタ
    unsigned char   score;      // 確信度(0〜100)
    unsigned char   filler[3];  // padding
} DCandidate;
//////////////////
// OCRの結果構造体
// 120バイト固定
typedef struct _DOCRResult {
    DCandidate      cand[MAX_CAND]; // 候補データMAX_CAND == 10 80 bytes
    DOCRRect        area;           // OCRした領域              16 bytes
    unsigned long   chartype;       // 文字認識結果の文字種     4  bytes
    unsigned long   space;          // 文字の後に続く半角スペースの数
                                                                4  bytes
    char            newcand[KEYSIZE_MAX];                        16 bytes
} DOCRResult;

認識結果が

DOCRResult ocrresult;

とすると、ocrresult.cand[0]〜ocrresult.cand[9]が認識結果の候補となり、ocrresult.cand[0].codeを第1候補の指す文字列、すなわちパターンの認識結果とみなすことができます。

DOCRResultのもっとも重要なメンバーは、認識結果の文字列を示す。DCandidate配列です。ALOCRCライブラリでは、最大10の候補がDOCRResultに含まれています。
DCandidate構造体のcodeメンバーが、認識結果の文字列を指しています。大部分のケースでは、codeは1文字の漢字文字列を指しています。このcodeの先は、辞書からロードした(あるいはユーザ辞書に登録した)文字列を指しています。したがって、辞書クラスをdeleteした場合は、ポインタの先は保証されないので注意してください。
候補の数が10に満たない場合は、codeの先は、NULLではなく""を指しています。さらにscoreが0であることで、候補が無いことが分かります。

DCandidate構造体のscoreメンバーは、候補文字の確信度を示しています。確信度の値は、0から100の範囲にあります。0の場合は、候補が無いことを示しています。候補がある場合の確信度は1〜100の範囲にあり、100に近いほど認識結果として確からしい事を示しています。
10の候補は必ずしも確信度順には並んでいません。確信度はあくまで画像的な特徴に基づくもので、文字認識では、さらに言語的な特徴も考慮されます。言語的な処理によって確信度の低い候補がより上位に来ることもあります。
通常、第1候補の確信度は60以上で、それ以下の場合は、認識がうまくいっていない可能性が高くなります。

DOCRResultのメンバーで、areaメンバーは、認識したパターン(文字)の外接矩形を示してます。画像の左上が原点で、右方向がx座標の正方向、下方向がy座標の正方向となります。
座標は、テキストブロック内の座標系で、縦書き/横書きとベースラインの向きによって以下のようになっています。

cordinates system
typedef struct _DOCRRect {
    int        x1;            // パターンの左上x座標(段落内正規化座標)
    int        y1;            // パターンの左上y座標(段落内正規化座標)
    int        x2;            // パターンの右下x座標(段落内正規化座標)
    int        y2;            // パターンの右下y座標(段落内正規化座標)
} DOCRRect;

DOCRResultの他のメンバーは、chartypeがcand[0].codeが指している文字列の文字種。spaceは1行認識における、文字と文字との間隔(漢字1文字をスペース2と換算したときのスペース数)を示しています。


目次

2.文字種フラグ

文字種は、文字種フラグの論理和で指定します。文字種フラグは、ヘッダファイル"ocrdef.h"に定義されています。ライブラリのユーザが指定できるのは、以下のフラグです。
gd_execocrの第1引数と第2引数の2つで文字種を指定します。第2引数ではアスキー記号、ファイル名記号といった意味的な制約を指定します。

gd_execocrの第1引数として指定可能なフラグ

通常記号SYMBOL_ETC!:”’‘?^_ ̄&#@´ `‘“
数値記号SYMBOL_NUMBER=+*<>/¥$%±×÷≠≦≧
中黒SYMBOL_NAKAGURO
マイナスSYMBOL_MINUS
カンマSYMBOL_COMMA
ピリオドSYMBOL_PERIOD
丸括弧SYMBOL_PAREN()
括弧SYMBOL_BRACE{}[]--〔〕「」『』【】
句読点SYMBOL_KUTOTEN、。
SYMBOL_MARU
伸ばす棒SYMBOL_NOBASBO
アラビア数字CHAR_NUMBER0〜9
アルファベット大文字CHAR_ALPHABET_CAPITALA−Z
アルファベット小文字CHAR_ALPHABET_SMALLa−z
カタカナ大文字CHAR_KATAKANA_CAPITALア−ン
カタカナ小文字CHAR_KATAKANA_SMALLァ−ヶ
ひらがな大文字CHAR_HIRAGANA_CAPITALあ−ん
ひらがな小文字CHAR_HIRAGANA_SMALLぁ−ょ
漢数字CHAR_KANJI_NUMBER一二三四五六七八九十百千万億兆
漢字CHAR_KANJI

目次


gd_execocrの第2引数として指定可能なフラグ

アスキー記号ASCII_CHARSET
ファイル名FILE_CHARSET

第2引数は、第1引数で指定した文字種をさらに絞り込むために指定されます。例えば数値記号(=+*<>/¥$%±×÷≠≦≧)のうちASCII記号(=+*<>/¥$%)だけを利用するときは、

mrecognize(SYMBOL_NUMBER,ASCII_CHARSET);

と指定します。またアルファベットやアラビア数字を指定すると"WA"や"12"のような2桁の英字、数字も認識対象となります。2桁の英数字は、漢字かなと混在する英数字の認識率を上げる効果がありますが、認識対象が英数字であると分かっているときは、逆効果となります。その場合は、

gd_execocr1(0,CHAR_NUMBER | CHAR_ALPHABET_CAPITAL | CHAR_ALPHABET_SMALL,ASCII_CHARSET,0,0,...);

のように指定します。
また、文字種フラグには以下のようなマクロも定義されています。

マクロ定数内容定義内容
CHAR_SET_SYMBOL記号(SYMBOL_ETC | SYMBOL_NUMBER | SYMBOL_NAKAGURO | SYMBOL_MINUS | SYMBOL_MARU | SYMBOL_NOBASBO)
CHAR_SET_KAKKO括弧類(SYMBOL_PAREN | SYMBOL_BRACE)
CHAR_SET_TERMINAL句読点(SYMBOL_PERIOD | SYMBOL_COMMA | SYMBOL_KUTOTEN)
CHAR_SET_ALPHABETアルファベット全て(CHAR_ALPHABET_SMALL | CHAR_ALPHABET_CAPITAL)
CHAR_SET_HIRAGANAひらがな(CHAR_HIRAGANA_CAPITAL | CHAR_HIRAGANA_SMALL)
CHAR_SET_KATAKANAカタカナ(CHAR_KATAKANA_CAPITAL | CHAR_KATAKANA_SMALL)
CHAR_SET_KANJI漢字全て(CHAR_KANJI | CHAR_KANJI_NUMBER)
CHAR_SET_ALL全文字種(CHAR_SET_SYMBOL | CHAR_SET_KAKKO | CHAR_SET_TERMINAL | CHAR_NUMBER | CHAR_SET_ALPHABET | CHAR_SET_HIRAGANA | CHAR_SET_KATAKANA | CHAR_SET_KANJI)

これらのマクロの論理和で、認識文字種を指定するようにします。


目次

3.テキストブロック抽出パラメータ

目次
テキストブロック抽出のためのパラメータの定義は以下のようになっています。通常は、パラメータ作成ツールを用いて、実際に対話的にパラメータ変更の効果を確認しながらパラメータを作ることができます。
また、ほどほどの精度で良い場合は、以下のような文書向けのパラメータセットがあらかじめ定義されているので、それをそのまま使ったり、多少変更して使うこともできます。
パラメータファイルは、テキスト形式なので、エディタ等でそのまま編集することができます。

日本語一般文書tateyoko.prm
日本語横書き一般文書yokogaki.prm
日本語縦書き一般文書tategaki.prm
英文一般文書english.prm
数表number.prm
英文図面edraft.prm
日本語図面jdraft.prm
配線図・回路図circuit.prm
公図(数字+英大文字)公図.prm
路線価図(数字+カンマ+英大文字)路線価.prm
住宅地図住宅地図.prm
// クラスタ抽出コントロール
#define    ABSTRACT_RATE            0x00000001        // 高さ/幅情報を使うかどうか
#define    ABSTRACT_PIXEL           0x00000002        // 面積情報を使うかどうか
#define    ABSTRACT_LENGTH          0x00000004        // 周囲長情報を使うかどうか
#define    ABSTRACT_CLUSTERWIDTH    0x00000008        // 周囲長情報を使うかどうか
#define    ABSTRACT_CLUSTERHEIGHT   0x00000010        // 周囲長情報を使うかどうか
#define    ABSTRACT_NUM             0x00000020        // 周囲長情報を使うかどうか
#define    ABSTRACT_LOC             0x00000040        // 位置情報を使うかどうか
#define    ABSTRACT_SEPARATOR       0x00000080        // セパレータによってクラスタを区切るかどうか

#define    ABSTRACT_DIST            0x00000100        // ユークリッド距離を使う
#define    ABSTRACT_DISTXY          0x00000200        // 市街地距離を使う
#define    ABSTRACT_LONG            0x00000400        // 1のように長いプリミティブは無条件で通す
#define    ABSTRACT_FLAT            0x00000800        // ーのように平たいプリミティブは無条件で通す
#define    ABSTRACT_SMALL           0x00001000        // 、のように小さいプリミティブは無条件で通す
#define    ABSTRACT_1PRIM1CHAR1LINE 0x00002000        // 英大文字+数字など1文字=1プリミティブ
                                                      // 1行(公図、路線価図、数表)
#define    ABSTRACT_1PRIM1CHAR1COLUMN 0x00004000      // 英大文字+数字など1文字=1プリミティブ
                                                      // 1列(図面の90度回転文字列)
#define    ABSTRACT_NOISE1                0x00008000          // 破線やノイズのように、小さなプリミティブだけで構成されるクラスタを除外
#define    ABSTRACT_NOISE2                0x00010000          // 写真等、ベタグラフィック内部のクラスタを除外

typedef struct _ABSTRACTPARAMETER {
    int        mdpi;              // パラメータサンプリングdpi
    int        mcontrol;          // コントロールフラグ
// プリミティブ必須
    int        minprimwidth;      // プリミティブ最小幅(必須)
    int        maxprimwidth;      // プリミティブ最大幅(必須)
    int        minprimheight;     // プリミティブ最小高(必須)
    int        maxprimheight;     // プリミティブ最大高(必須)
// プリミティブ任意
    double    minrate;            // プリミティブ高さ/幅の最小値(任意)
    double    maxrate;            // プリミティブ高さ/幅の最大値(任意)
    int        minpixel;          // プリミティブ面積の最小値(任意)
    int        maxpixel;          // プリミティブ面積の最大値(任意)
    int        minlength;         // プリミティブ周囲長の最小値(任意)
    int        maxlength;         // プリミティブ周囲長の最大値(任意)
// プリミティブ間距離
    // ユークリッド距離あるいは市街地距離のどちらか
    double    mindist;            // プリミティブ間ユークリッド距離の最小値
    double    maxdist;            // プリミティブ間ユークリッド距離の最大値
    int        mindistx;          // 市街地X座標距離最小値
    int        maxdistx;          // 市街地X座標距離最大値
    int        mindisty;          // 市街地Y座標距離最小値
    int        maxdisty;          // 市街地Y座標距離最大値
// クラスタ任意
    int        minclusterwidth;   // クラスタ最小幅(任意)
    int        maxclusterwidth;   // クラスタ最大幅(任意)
    int        minclusterheight;  // クラスタ最小高(任意)
    int        maxclusterheight;  // クラスタ最大高(任意)
    int        minnum;            // クラスタ内プリミティブ数(任意)最小値
    int        maxnum;            // クラスタ内プリミティブ数(任意)最大値
// クラスタの存在するエリア(任意)
    int        mleft;             // 左上X
    int        mtop;              // 左上Y
    int        mright;            // 右下X
    int        mbottom;           // 右下Y
} ABSTRACTPARAMETER;
mdpiは、テキストブロック抽出パラメータのあてはまる画像の解像度を示しています。パラメータの単位がピクセル単位となっており実際の長さではないため、パラメータの値を解像度調整するために必要となります。
100dpiで長さが10ピクセルで面積が100ピクセル^2であれば、300dpiでは長さが30ピクセル、面積は900ピクセルとなります。

プリミティブ必須パラメータで、プリミティブの幅と高さの最小値と最大値を指定します。プリミティブとは、画像のピクセルが連結している領域のことを指しています。以下の図ではプリミティブの幅は7、高さは5となります。数字や英語の大文字は、1文字=1プリミティブとなりますが、漢字や「i」「j」「=」のように1文字が複数のプリミティブから成る文字もあります。

primitive
プリミティブ任意パラメータで、プリミティブの高さ/幅の比や面積に関する制限を指定できます。上の図の場合、比は0.714285、プリミティブの面積は14となります。

プリミティブ間距離は必須パラメータで、2つのプリミティブの外接矩形間のユークリッド距離あるいは、外接矩形間の市街地距離で指定します。下の図の場合、ユークリッド距離はsqrt(3^2 + 4^2)の5で、市街地距離だとX軸方向は4でY軸方向は3となります。

primitive2
漢字など複数のプリミティブからなる文字では、プリミティブ間の距離が0となるため、距離の最小値は必ず0にします。

primitive3
クラスタ任意パラメータでは、クラスタの幅と高さの最小値と最大値を指定します。クラスタとは、プリミティブパラメータとプリミティブ間距離パラメータに合ったプリミティブの集合のことです。プリミティブが文字とすると、クラスタはテキスト段落ということになります。
以下の図の場合、プリミティブ間ユークリッド距離の最大値を2とすると、左上と右下のプリミティブ群は別々のクラスタということになり、画像内には2つのクラスタが存在することになります。プリミティブ間ユークリッド距離の最大値を5とすると、左上と右下のプリミティブ群は同じクラスタに属し、画像内には1津のクラスタが存在することになります。

cluster
クラスタの幅と高さのパラメータは、必ずプリミティブの幅と高さのパラメータよりも大きくなります。上の図が2つのクラスタとなる場合、各クラスタの高さは2で、左上のクラスタの幅は7、右下のクラスタの幅は5となります。

クラスタ内プリミティブ数は、段落内の文字数+αに該当します。+αは漢字のように1文字が複数のプリミティブから成るためで、認識対象に漢字等が含まれる場合は、プリミティブ数の最大値は大きめに設定するといいでしょう。
上の図の場合、左上のクラスタのプリミティブ数は4で、右下のクラスタのプリミティブ数は3となります。

良く分からない場合、クラスタ任意パラメータのチェックは外して無視しても構いません。

クラスタの存在するエリアは任意パラメータで、帳票のように固定した場所に文字がある場合に、その場所を囲む長方形の座標を指定します。

mcontrolはクラスタ抽出コントロールで、最初の7つ(ABSTRACT_RATE、ABSTRACT_PIXEL、ABSTRACT_LENGTH、ABSTRACT_CLUSTERWIDTH、ABSTRACT_CLUSTERHEIGHT、ABSTRACT_NUM、ABSTRACT_LOC)は任意パラメータを無視するかどうかに該当します。
ABSTRACT_SEPARATORは、2つのプリミティブ間に別のプリミティブ(セパレータ)が存在する場合に、それぞれ別のクラスタに属すると判断するときに立てるフラグです。
ABSTRACT_SEPARATORが指定されている場合、プリミティブ間ユークリッド距離が5であるとしても、左上と右下のクラスタは別の物として扱われます。
separator
次の2つ(ABSTRACT_DIST、ABSTRACT_DISTXY)は、プリミティブ間距離の判定にユークリッド距離を使うか、市街地距離を使うかを指定します。すなわちどちらかがオンとなります。
ABSTRACT_LONGフラグは1やアルファベットのIのように長いプリミティブは無条件でパラメータに合致するものと判断します。ABSTRACT_FLATやABSTRACT_SMALLも同様です。長い文字、平たい文字、小さい文字は、パラメータが例外的な値をとるために、処理も例外的に行うことによって、他のパラメータで例外的な文字のことを考慮せずにすみます。

longprimitive
上記の文字の場合、高さは2で幅は8で高さ/幅は0.25ですが、他の文字と比較すると極端な値になっています。こうした文字は、最初からハイフンであると考えてパラメータでの判断からは外すようにします。慣れるまでは、これらのフラグはオフにして、代わりにプリミティブの最小値を小さめに設定しておきます。
ABSTRACT_1PRIM1CHAR1LINEやABSTRACT_1PRIM1CHAR1COLUMNは、特殊文書向けのフラグで、対象文字種が英大文字+数字など1文字=1プリミティブで、段落が1行あるいは、1列の場合にオンにすることで、抽出精度が向上します。
このような特殊文書の例としては、公図、路線価図、数表、図面(カナや漢字が含まれないもの)が挙げられます。

目次

4.エラーコード

目次

エラー定義ヘッダファイルerrcode.hに用いられているエラーコードのうち、ライブラリに関連するものを解説します。

#define        MEMORY_SHORTAGE     -1000        // メモリ不足
#define        ILLEGAL_ARGUMENT    -1001        // 引数エラー
#define        BUFFER_OVERFLOW     -1002        // バッファオーバーフロー
#define        INITIALIZE_ERROR    -1004        // 初期化エラー
#define        FILE_OPEN_ERROR     -2000        // ファイルオープンエラー
#define        FILE_READ_ERROR     -2002        // ファイルリードエラー
#define        FILE_SEEK_ERROR     -2003        // ファイルシークエラー
#define        FILE_WRITE_ERROR    -2004        // ファイルライトエラー
#define        ILLEGAL_HEADER      -3002        // ファイルヘッダエラー
#define        ILLEGAL_VERSION     -3003        // バージョンエラー
#define        ILLEGAL_GRAPHIC     -3004        // グラフィックエラー
#define        FATAL_ERROR         -9999        // 致命的エラー
目次

3.各論


3.1 画像の読み込み

目次

2値モノクロあるいは256階調グレイスケールのTIFFファイル、BMPファイルから画像を読み込んで、2値モノクロ画像として格納します。TIFFファイルは、packed pixel、LZW、G3 MH、G3 FAX、G4圧縮画像に対応しています。
画像ファイルに解像度情報が含まれていない場合、フラグによって解像度情報をデフォルト値に設定するか、ユーザーに入力させるかを設定することができます。
//////////////////////////
// 画像のロード
// モノクロ2値、256階調グレイスケールのTIFF、BMP画像を読み込む
// 内部での画像はboudaryで指定されたモノクロ2値画像となっている
// 入力
//    char*         filename;       ファイル名(拡張子でファイル種別)
//    int           boundary;       1...1バイト境界
//                                  2...2バイト境界
//                                  4...4バイト境界
//    int           bottomupflag;   0...トップダウンイメージ
//                                  1...ボトムアップイメージ
//    int           uifflag;        0...解像度不明の場合defaultdpiを用いる
//                                  1...解像度不明の場合、ダイアログを表示して解像度を入力
//  int             defaultdpi;     解像度不明の場合のデフォルト解像度
// 返り値
//  0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_LOADIMAGE)(char* filename,int boundary,int bottomupflag,int uifflag,int defaultdpi);
extern GD_LOADIMAGE gd_loadimage;
ファイル名の拡張子が"TIF"あるいは"TIFF"の場合にTIFFファイル、"BMP"の場合にBMPファイルと判断します。大文字小文字は無視されます。
バイト境界では、格納した2値画像のバイト境界を指定します。例えばNピクセル幅の画像をロードした場合。

boudary1行のバイト数
N / 8 + (N % 8 > 0)
(N / 16 + (N % 16 > 0)) * 2
(N / 32 + (N % 32 > 0)) * 4


となります。
bottomupflagが0の場合トップダウンイメージでY軸正方向が下向きとなります。bottomupflagが1の場合ボトムアップイメージでY軸正方向が上向きとなります。 bottomupflagが0の場合トップダウンイメージでY軸正方向が下向きとなります。bottomupflagが1の場合ボトムアップイメージでY軸正方向が上向きとなります。 ヘッダファイル"alocrcb.h"をインクルードすれば、通常のint値を返すC言語関数としてコールすることができます。
uifflagが1の場合で、なおかつ画像の解像度が不明の場合に、ダイアログを表示してユーザーに解像度を入力させます。ダイアログの初期値はdefaultdpiとなります。
uifflagが0の場合で、なおかつ画像の解像度が不明の場合に、解像度はdefaultdpiとなります。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。

サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE    gd_dllinstance;
GD_LOADIMAGE gd_loadimage;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
if(gd_dllinstance != NULL) {
    int        i1;
    // DLL関数アドレスの取得
    gd_loadimage = (GD_LOADIMAGE)GetProcAddress(gd_dllinstance,"gd_loadimage");
    if(gd_loadimage != NULL) {
        // foo.tifというtifファイルを読み込んで、
        // 4バイトバウンダリトップダウン2値画像として格納する。
        // 解像度情報が不明の場合、ダイアログを表示して解像度を入力させる
        // ダイアログの解像度の初期値は300dpi
        i1 = gd_loadimage("foo.tif",4,0,1,300);
    }
    // DLLの解放
    FreeLibrary(gd_dllinstance);
}

目次

3.2 画像情報の取得

目次

gd_getimagefileinfo 画像ファイルの情報を取得します。
gd_getimageinfo 画像の情報を取得します。

//////////////////////////
// 画像ファイル情報の取得
// bmp/tiffファイルから読み込んだ生画像の情報
// 出力
//    int*            pwidth;         画像の幅(ピクセル)
//    int*            pheight;        画像の高さ(ピクセル)
//    int*            pscanlinesize;  画像1行のバイト数(バイト)
//    int*            pdpi;           画像の解像度(dpi)
//    int*            pdepth;         1...2値画像
//                                    8...256階調グレイスケール画像
//    int*            ptype;          0...bmpファイル
//                                    1...tiffファイル
// 返り値
//  0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GETIMAGEFILEINFO)(int* pwidth,int* pheight,int* pscanlinesize,int* pdpi,int* pdepth,int* ptype);
extern GD_GETIMAGEFILEINFO gd_getimagefileinfo;
画像の幅と高さはピクセル単位で返します。
画像1行のバイト数はTIFFファイルの場合はスキャンラインサイズ情報、BMPファイルの場合は4バイトバウンダリのバイト数が返ります。
解像度情報はファイルに書かれている解像度が返ります。解像度不明の場合は0が返ります。
モノクロ2値画像の場合pdepthは1、グレイスケール256階調画像の場合pdepthは8となります。
ptypeが0の場合はBMPファイル、1の場合はTIFFファイルとなります。
//////////////////////////
// 画像情報の取得
//    バッファに格納された2値画像の情報
//    1行のバイト数はgloadimageで指定したバウンダリに基づく
//    必ず2値画像
// 出力
//    void**          ppdata;         画像バッファ
//    int*            pwidth;         画像の幅(ピクセル)
//    int*            pheight;        画像の高さ(ピクセル)
//    int*            pscanlinesize;  画像1行のバイト数(バイト)
//    int*            pdpi;           画像の解像度(dpi)
//    int*            pbackground;    0...bit0が背景
// 返り値
//  0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_GETIMAGEINFO)(void** ppdata,int* pwidth,int* pheight,int* pscanlinesize,int* pdpi,int* pbackground);
extern GD_GETIMAGEINFO gd_getimageinfo;
*ppdataは画像が格納されているバッファのアドレスとなります。画像は必ずモノクロ2値となっています。
画像の幅と高さはピクセル単位で返します。
画像1行のバイト数はgd_loadimageで指定したバイトバウンダリと画像の幅から計算されます。33ピクセル幅の画像は1バイトバウンダリでは1行5バイト、2バイトバウンダリでは1行6バイト、4バイトバウンダリでは1行8バイトとなります。
解像度情報はファイルに書かれている解像度が返ります。解像度不明の場合はユーザー入力あるいはデフォルトの解像度が返ります。gd_loadimage参照
*pbackgroundは画像の背景がbit0かbit1かを示しています。
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。

サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE    gd_dllinstance;
GD_GETIMAGEFILEINFO gd_getimagefileinfo;
GD_GETIMAGEINFO gd_getimageinfo;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
    int            i1;
    int            width;
    int            height;
    int            scanlinesize;
    int            dpi;
    int            depth;
    int            imagetype;
    void*        pdata;
    int            background;
    // DLL関数アドレスの取得
    gd_getimagefileinfo = (GD_GETIMAGEFILEINFO)GetProcAddress(gd_dllinstance,"gd_getimagefileinfo");    if(gd_getimagefileinfo != NULL) {
        // 画像ファイル情報の取得
        i1 = gd_getimagefileinfo(&width,&height,&scanlinesize,&dpi,&depth,&imagetype);
        if(i1 < 0) return(-4);
    }
    gd_getimageinfo = (GD_GETIMAGEINFO)GetProcAddress(gd_dllinstance,"gd_getimageinfo");
    if(gd_getimageinfo != NULL) {
        // 画像情報の取得
        i1 = gd_getimageinfo(&pdata,&width,&height,&scanlinesize,&dpi,&background);
        if(i1 < 0) return(-4);
    }
    // DLLの解放
    FreeLibrary(gd_dllinstance);
}

目次

3.1 画像の保存

目次

gd_saveimage 画像を保存します。
gd_savelayer レイヤ0あるいはレイヤ1の画像を保存します。
格納されているモノクロ2値画像を、TIFF G4圧縮ファイルとして保存します。
レイヤについてはテキストブロック抽出で解説しています。

/////////////
// 画像の保存
//    バッファに格納された2値画像を指定されたファイル名で保存
//    ファイルはG4フォーマットのTIFFファイルとして保存
// 入力
//    char*         filename;       ファイル名
// 返り値
//  0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SAVEIMAGE)(char* filename);
extern GD_SAVEIMAGE gd_saveimage;
///////////////////
// レイヤ画像の保存
//    文字領域画像/文字領域画像以外の画像を保存
//    ファイルはG4フォーマットのTIFFファイルとして保存
// 入力
//    int           layer;           0...文字領域以外の画像
//                                   1...文字領域画像
//    char*         filename;       ファイル名
// 返り値
//  0...正常終了
// 負...エラー(エラーコード定義参照)
typedef int (__cdecl* GD_SAVELAYER)(int layer,char* filename);
extern GD_SAVELAYER gd_savelayer;
関数の動的リンクに関しては、サンプルプログラムを参考にインプリメントすると良いでしょう。通常の動的リンクと同様に、LoadLibrary/GetProcAddress/FreeLibraryの3つのAPIによってDLLにアクセスします。

サンプルコード
// DLL関数の定義
#include "alocrcb.h"
HINSTANCE    gd_dllinstance;
GD_SAVEIMAGE gd_saveimage;
GD_SAVELAYER gd_savelayer;
// DLLのロード
gd_dllinstance = LoadLibrary("alocrc.dll");
......
if(gd_dllinstance != NULL) {
    int        i1;
    // DLL関数アドレスの取得
    gd_saveimage = (GD_SAVEIMAGE)GetProcAddress(gd_dllinstance,"gd_saveimage");
    if(gd_saveimage != NULL) {
        // 全てのラスタを"b.tif"というG4圧縮TIFFファイルとして保存
        i1 = gd_saveimage("b.tif");
    }
    gd_savelayer = (GD_SAVELAYER)GetProcAddress(gd_dllinstance,"gd_savelayer");
    if(gd_savelayer != NULL) {
        // 文字画像レイヤを"c.tif"というG4圧縮TIFFファイルとして保存
        i1 = gd_savelayer(1,"c.tif");
    }
    // DLLの解放
    FreeLibrary(gd_dllinstance);
}

目次

3.4 画像処理

目次

gd_negate画像を白黒反転
画像のサイズ、バッファアドレスは変化しない。gd_getimageinfoの背景は1と0が反転。
gd_deletenoize画像のノイズ除去
画像のサイズ、バッファアドレスは変化しない。
gd_rotate180画像180度回転
画像のサイズ、バッファアドレスは変化しない。
gd_rotate90画像90度回転
画像のサイズ、バッファアドレスが変化するのでgd_getimageinfoでアドレスを取得しなおす。
gd_rotate270画像270度回転
画像のサイズ、バッファアドレスが変化するのでgd_getimageinfoでアドレスを取得しなおす。
gd_4to8プリミティブを8連結で抽出
全ての画像処理の後、テキスト抽出の前に行う。プリミティブを8連結で抽出する。
通常はプリミティブは4連結で抽出されるが、かすれた画像や解像度の低い画像の場合、8連結で抽出した方が精度が高くなる場合がある。
逆に4連結では分離していると処理されるものが8連結では結合されていると処理されるため、却って精度が低くなる場合もある。

8連結と4連結


/////////////////
// 画像を白黒反転
// 抽出したテキストブロック情報はクリア
// 返り値
//  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ピクセルまでの面積のプリミティブがノイズとして除去されます。

noise reduction
上記の図では、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では、認識用の辞書のあるディレクトリとユーザー辞書名を指定します。
認識用のシステム辞書は名前固定で以下のようになっています。
基本辞書
辞書名レコードファイル名キーファイル名内容
systemsystem.dbssystem.key必須
systemfatsystemfat.dbssystemfat.key必須
オプション辞書(差分辞書)
diff0diff0.dbfdiff0.kef楷書体
diff1diff1.dbfdiff1.kef低品質かすれ文字
diff2diff2.dbfdiff2.kef低品質つぶれ文字
diff3diff3.dbfdiff3.kef数字
diff4diff4.dbfdiff4.kef英字
diff5diff5.dbfdiff5.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となります。下図参照

baseline
insideflagが0だと、テキストブロック矩形の内部をそのまま認識します。1の場合は、テキストブロック矩形の枠に接触するプリミティブを除いて認識します。テキストブロック矩形内に図形の一部が侵入している場合などに指定します。

insideflag
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バイトの画像のみサポートしています。
  1. gd_grayscalefastinit
  2. gd_grayscalefastrect
  3. gd_grayscalefineinit
  4. 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のように、
  1. 初期化
  2. 画像読み込み
  3. パラメータの設定
  4. 認識結果の取得
  5. 出力
と複数の手順を踏まなければ成らない処理が、Version 2.0では、
  1. 画像読み込み+認識+出力
のひとつの手順(API)で処理することができます。
Version 1.0では、新聞のような複雑な段組の文書には対応できませんでした。
Ver. 2.0では、一般文書(新聞のような複雑な段組の文書も含む)に限定して認識パラメ ータの設定が不要なAPIを提供しました。APIひとつだけで画像の読み込みから 透明テキスト付きのPDFファイルへの出力までを実行できるようにしました。
目次

4.1 画像→透明テキスト付きPDF変換

目次

Version 2.0 対応画像フォーマット
  1. BMP(モノクロ2値、256階調グレイスケール)
  2. TIFF(モノクロ2値、256階調グレイスケール)
Version 3.0 対応画像フォーマット
  1. BMP(モノクロ2値、256階調グレイスケール、24ビットカラー)
  2. TIFF(モノクロ2値、256階調グレイスケール、24ビットカラー)
  3. PDF(モノクロ2値(JBIG圧縮は未対応)、256階調グレイスケール、24ビットカラー)
  4. JPEG(256階調グレイスケール、24ビットカラー)
  5. PNG(モノクロ2値、256階調グレイスケール、24ビットカラー)
  6. GIF(モノクロ2値、256階調グレイスケール)
  7. 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ファイルは
  1. [General]セクション、guiflagキー
    0の時は、エラーがあってもダイアログを出さない、1のときはダイアログを出す。
  2. [General]セクション、rotatespecキー
    1. 0の時は、読み込み画像を回転しない
    2. 1の時は、読み込み画像を左90度回転
    3. 2の時は、読み込み画像を180度回転
    4. 3の時は、読み込み画像を左270度回転
    5. 4の時は、読み込み画像の向きを自動判別回転
  3. [General]セクション、jpegrateキー
    24ビット画像、8ビットグレイスケール画像をPDF画像として出力するときの画質(30〜100、大きいほど画質が良いがサイズが大きくなる)
  4. [General]セクション、zen2hanflagキー
    0の時は、英数字を2バイトコードで出力、1の時は英数字を1バイトコードで出力
  5. [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を提供している。
      カスタマイズの例は
      1. 画像→PDF/CSVファイル変換。CSVファイルには文字単位で位置とサイズの情報を出力(カスタマイズ料:8万円)
      2. 画像→XMLファイル変換。文字コードはUnicode/指定フォーマットのXMLファイル出力(カスタマイズ料:16万円)
      3. 奇数ページPDFファイル+偶数ページPDFファイル→透明テキスト付きPDFファイル変換(カスタマイズ料:20万円)
        ブックスキャナで奇数ページのみ、偶数ページのみで取り込んだ2つのPDFファイルを1つのPDFファイルに統合変換
      4. 帳票定義ファイル+PDF帳票ファイル→透明テキスト付きPDFファイル、TSVファイル変換(カスタマイズ料:80万円)
        独自仕様の帳票定義ファイルとPDFの帳票画像を読み込んで透明テキスト付きPDF+TSV(タブ区切りファイル)形式の 属性:属性値ファイルを出力
      目次

      5 バージョン3.0改良・追加API

      バージョン3.0では、画像入力およびバッチ処理コマンドにおいてカラー画像対応等を行なった。
      Version 2.0 対応画像フォーマット
      1. BMP(モノクロ2値、256階調グレイスケール)
      2. TIFF(モノクロ2値、256階調グレイスケール)
      Version 3.0 対応画像フォーマット
      1. BMP(モノクロ2値、256階調グレイスケール、24ビットカラー)
      2. TIFF(モノクロ2値、256階調グレイスケール、24ビットカラー)
      3. PDF(モノクロ2値(JBIG圧縮は未対応)、256階調グレイスケール、24ビットカラー)
      4. JPEG(256階調グレイスケール、24ビットカラー)
      5. PNG(モノクロ2値、256階調グレイスケール、24ビットカラー)
      6. GIF(モノクロ2値、256階調グレイスケール)
      7. JPEG2000(256階調グレイスケール、24ビットカラー)
      また、Version 2.0とは逆にGUIを使って対話的に認識処理を進めるためのAPIを追加した。
      1. テキストブロック(いわゆる段落に相当)をマウス操作で作成する機能
      2. 認識結果をエディタ上で編集する機能
      3. 候補文字リストから候補文字を選択する機能
      4. 誤認識文字を簡潔な操作でユーザー辞書登録する機能
      5. 以上の操作を取り消したり、やり直したりするアンドゥ・リドゥ機能
      目次

      5.1 手動テキストブロック指定

      目次
      目次

      5.2 テキストブロック編集

      目次
      目次

      5.3 アンドゥ・リドゥサポート

      目次
      目次

      マニュアルホームページ