// プリミティブ特徴構造体
typedef struct _PRIMFEATURE {
int pixel; // プリミティブ領域の面積
int length; // プリミティブ領域の周囲長
double cx; // 重心x
double cy; // 重心y
// featureexは2001年07月25日追加
// 2001年07月25日時点では常にNULL。構造体の内容も未確定(コンパイルには問題なし)
PRIMFEATUREEX* featureex; // 拡張特徴(将来の拡張用、円形度・線幅等・2次モーメント特徴などが拡張される予定)
} PRIMFEATURE;
typedef struct _PRIMITIVE {
unsigned char layer; // プリミティブのレイヤ番号
unsigned char undo; // プリミティブの元のレイヤ
unsigned char unused; // 使われていない時1
unsigned char flag; // 汎用制御フラグ
int xmin; // プリミティブ領域の左上(Y軸正方向が下の場合)座標
int ymin;
int xmax; // プリミティブ領域の右下(Y軸正方向が下の場合)座標
int ymax;
PRIMFEATURE* feature;
} PRIMITIVE;
typedef struct _CLUSTER {
int num; // prim配列の要素数
int validnum; // prim配列の有効要素数
int max; // prim配列のサイズ
PRIMITIVE** pprim;
unsigned char flag; // 0...通常のクラスタ(fusionする)
// 1...孤立クラスタ(fusionしない)
unsigned char loc; // 0...枠の遠く:隣接セグメントのクラスタと無関係
// 1...上枠の近く:上セグメントのクラスタとfusion
// 2...下枠の近く:下セグメントのクラスタとfusion
// 4...左枠の近く:左セグメントのクラスタとfusion
// 8...右枠の近く:右セグメントのクラスタとfusion
unsigned char unused; // 0...使われている
// 1...使われていない
unsigned char reserved2;
short line; // 表の場合の行
short column; // 表の場合の列
PRIMITIVE* parent; // クラスタの属するプリミティブ(表など)
long pwidthmax; // クラスタ内要素の最大幅
long pheightmax; // クラスタ内要素の最大高さ
long xmin; // クラスタの左上(Y軸正方向が下の場合)の座標
long ymin;
long xmax; // クラスタの右下(Y軸正方向が下の場合)の座標
long ymax;
// angleは2000年10月10日追加
double angle; // クラスタの推定・指定角度(機能追加用)
void* pdata; // 予備
} CLUSTER;
typedef struct _ALTABLE {
int num; // クラスタ数
int max; // クラスタ配列領域のサイズ
CLUSTER** ppcluster; // クラスタ配列
PRIMITIVE* prim; // 表に相当するプリミティブ
long xmin; // 表の左上(Y軸正方向が下の場合)座標
long ymin;
long xmax; // 表の右下(Y軸正方向が下の場合)座標
long ymax;
} ALTABLE;
| クラス名 | CJocrPrimRDまたはCJocrPrimEXまたはCJocrPrim |
| ヘッダファイル | ocrdef.h ocrco.h primitive.h cjocrprim.h absparam.h cjocrprimex.h cjocrprimrd.h errcode.h |
| 必要なLIB | NGKOCR4.LIB |
| 必要なDLL | NGKOCR1.DLL NGKOCR2.DLL NGKOCR4.DLL ALVEC.DLL ALPOLYGON.DLL |
| コンパイル定数 | USENGKDLL4 |
CJocrPrim* prim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
....
delete prim;
あるいは
CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
....
delete prim;
初期化されているかどうかのチェックは以下のようにmchecklimitを使って行う。
ライセンスコードの期限切れやハードウェアロック不良などの理由でライブラ
リが使えない場合は、返り値が1となる。無期限のライセンスファイル等を使っ
ている場合はチェックの必要は無い。
if(mpjocrprim->mchecklimit(3)) {
delete mpjocrrecognize;
mpjocrrecognize = NULL;
}
// int mchecklimit(int level)
// 入力
// int level; // ライブラリユーザーの場合常に3
// 返り値が1の場合初期化ができていない
// ドキュメント画像の設定
void msetdocument(unsigned char* buffer,int background,int width,int height);
// スキャンラインサイズの指定
void msetdocument(unsigned char* buffer,int background,int width,int scanlinesize,int height);
入力
unsigned char* buffer; // 画像の先頭アドレス
int background; // 背景のビット値(0...bit0が背景/1...bit1が背景)
int width; // 画像の幅(ピクセル単位)
int scanlinesize; // 1行のバイト数
int height; // 画像の高さ(ピクセル単位)
// ビットマップ→プリミティブ変換
// ビットマップ全体の変換
int makeprim();
int makeprim8();
// 長方形領域(傾き不可)を指定して、その内部だけ変換
int makeprim(int x1,int y1,int x2,int y2);
int makeprim8(int x1,int y1,int x2,int y2);
入力
int x1,y1; 長方形の左上座標
int x2,y2; 長方形の右下座標
返り値
0................正常終了
MEMORY_SHORTAGE..メモリが不足している
// 任意の凸矩形領域を指定して、その内部だけ変換
// 任意の角度の長方形も可
int makeprim(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4);
int makeprim8(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4);
入力
int x1,y1; 凸矩形の4つの座標(順番は任意でも良い)
int x2,y2;
int x3,y3;
int x4,y4;
返り値
0...............正常終了
MEMORY_SHORTAGE.メモリが不足している
// プリミティブ数の取得
int mgetvalidprimitivenum();
// layer上のプリミティブ数の取得
int mgetvalidprimitivenum(int layer);
返り値
変換した結果のプリミティブの数
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
delete pjocrprim;
...
// dpiの設定
// ポイント単位をピクセル単位に変換するためにdpiを設定します
void msetdpi(int dpi);
入力
int dpi; // 解像度
// 文字サイズの設定
// 最大プリミティブサイズと最小プリミティブサイズを指定
void msetpoint(int maxpoint,int minpoint);
入力
int maxpoint; // 最大プリミティブサイズ(minpointポイント以上(72ポイント=1インチ))
int minpoint; // 最小プリミティブサイズ(1ポイント以上(72ポイント=1インチ))
// 文書タイプの設定
// 斜めの場合のポイント数の解釈が変わる
// 斜めの指定が無いと、角度推定は0度あるいは90度のどちらかに限定される。
void msetvflag(int vflag);
入力
int vflag; // 1...横書きのみ(bit0)
// 2...縦書きのみ(bit1)
// 3...横書き+縦書き(斜めなし)
// 4...斜めあり(bit0,bit1の値は無視)
// 1行文字数、1ブロック行数の設定、文字間、行間
// いわゆるクラスタのサイズと、一つのクラスタにまとめるプリミティブ間の距離の指定に相当する
// charperline×lineperblockが1クラスタの最大プリミティブ数となる
void msetcharline(int charperline,int lineperblock,int charspace,int linespace);
入力
int charperline; // 1行文字数
int lineperblock; // 1段落行数
int chaspace; // 横方向(縦書きでは縦方向)のプリミティブ間の距離
// (ポイント(72ポイント=1インチ))
int linespace; // 縦方向(縦書きでは横方向)のプリミティブ間の距離
// (ポイント(72ポイント=1インチ))
// 1クラスタの文字数の最小値
// 1クラスタに含まれるプリミティブ数に相当する
void msetminnum(int aminnum);
入力
int aminnum; // 最小のプリミティブ数
///////////////////////
// 最小・最大文字サイズの推定
void minferpoint(int& amin,int& amax,int layer);
入力
int layer; // layer内で推定
出力
int& amin; // 最小文字サイズ(ポイント(72ポイント=1インチ))
int& amax; // 最大文字サイズ(ポイント(72ポイント=1インチ))
/////////////////
// クラスタの抽出
// 上記のパラメータに基づいてクラスタを抽出する
int mabstractcluster(int from,int to);
入力
int from; // 移動元レイヤ
int to; // 移動先レイヤ
返り値
0以上.............抽出したクラスタ数
MEMORY_SHORTAGE...メモリが不足している
// 抽出クラスタデータの取得
// 呼ぶ側でのバッファpclusterを確保する
// 内部でクラスタ領域をスタティックに持っているが、そこには計算途中で破棄された無効な
// クラスタも含まれているので、有効クラスタだけ抜き出すという意味で、この関数が提供さ
// れている
void mgetvalidcluster(CLUSTER* pcluster);
入力
CLUSTER* pcluster; クラスタを入れるバッファ
sizeof(CLUSTER) * 抽出したクラスタ数
出力
CLUSTER* pcluster; 抽出したクラスタデータ
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
// クラスタの抽出
int clusternum = pjocrprim->mabstractcluster(0,1);
if(clusternum < 0) {
エラー;
}
CLUSTER* pcluster = (CLUSTER*)malloc(sizeof(CLUSTER) * clusternum);
if(pcluster) {
// クラスタの取得
mgetvalidcluster(pcluster);
}
delete pjocrprim;
...
// クラスタの角度推定計算
void mcalcangle(CLUSTER* pcluster,double& angle);
入力
CLUSTER* pcluster; クラスタ(mgetvalidclusterで取得したクラスタ)
出力
double& angle; 推定角度(ラジアン)
指定された角度から±5度の範囲で角度を推定します。moveprimlinestring関数等で、ユーザーが指定した角度を基準に角度を推定する場合には、こちらの関数を使います。// クラスタの角度推定計算
void mcalcanglespec(CLUSTER* pcluster,double& angle);
入力
CLUSTER* pcluster; クラスタ(mgetvalidclusterで取得したクラスタ)
double& angle; 指定角度(ラジアン)
出力
double& angle; 推定角度(ラジアン)
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
// クラスタの抽出(クラスタに属するプリミティブはレイヤ1へ移動)
int clusternum = pjocrprim->mabstractcluster(0,1);
if(clusternum < 0) {
エラー;
}
CLUSTER* pcluster = (CLUSTER*)malloc(sizeof(CLUSTER) * clusternum);
if(pcluster) {
// クラスタの取得
mgetvalidcluster(pcluster);
for(int i = 0 ; i < clusternum ; i++) {
double angle;
pjocrprim->mcalcangle(pcluster + i,angle); // angleが推定された角度(ラジアン)
// 実際のベースラインの角度はangleかangle+π/2
....
...
}
}
delete pjocrprim;
...
// 座標の順番は、以下の通りになっている。
// [0] | [1]
// +------------+------------+
// | 2 | 1 |
// -+------------+------------+-軸線
// | 3 | 4 |
// +------------+------------+
// [3] | [2]
// mcalcframeによる枠の座標配置
// 0...クラスタ中心に対して、第2象限
// 1...クラスタ中心に対して、第1象限
// 2...クラスタ中心に対して、第4象限
// 3...クラスタ中心に対して、第3象限
// クラスタの外接枠計算
void mcalcframe(CLUSTER* pcl,double angle,double* px,double* py,double& dh,double& dv,double ext = 0.0,int recalcflag);
入力
CLUSTER* pcl; // クラスタ
double angle; // 軸線の角度(ラジアン)
double ext; // 全ての座標をextピクセルだけ外側に広げる
// デフォルト値は0.0
// 2000年10月10日機能追加
int recalcflag // 1にした場合、外接枠がプリミティブに接触するまで縮小する
// 斜めの外接矩形の枠とプリミティブの隙間を縮小する
// デフォルト値は0
出力
double* px; // px[4]...外接枠の座標
double* py; // py[4]...外接枠の座標
// dhの角度がangle(y軸正方向が下の場合時計周りが正)
(y軸正方向が上の場合反時計周りが正)
double& dh; // クラスタの軸線の長さ(必ずしも水平に近いわけではない)
double& dv; // クラスタの軸線と垂直に交差する線の長さ(必ずしも垂直に近いわけではない)
{
// CLUSTER* pcluster;
// pclusterは何らかのAPIによって抽出したクラスタであるとする
double angle;
double dh,dv;
double x[4];
double y[4];
mpjocrprim->mcalcangle(pcluster,angle); // pclusterを元にangleを求める
mpjocrprim->mcalcframe(pcluster,angle,x,y,dh,dv,0.0,1); // pclusterとangleを元にx[4],y[4],dh,dvを求める
// recalcflagは1なので斜めの場合も枠と文字の間に余分な空白が無くなる
// (x[3],y[3])-(x[2],y[2])がテキスト行のベースライン
// 行の高さ(幅)はdv
}
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
// クラスタの抽出
int clusternum = pjocrprim->mabstractcluster(0,1);
if(clusternum < 0) {
エラー;
}
CLUSTER* pcluster = (CLUSTER*)malloc(sizeof(CLUSTER) * clusternum);
if(pcluster) {
// クラスタの取得
mgetvalidcluster(pcluster);
for(int i = 0 ; i < clusternum ; i++) {
double x[4];
double y[4];
double dh
double dv;
pjocrprim->mcalcframe(pcluster + i,0,x,y,dh,dv); // 角度0度として外接矩形を取得
....
...
}
}
delete pjocrprim;
...
///////////////////////
// 表処理オペレーション
// クラスタ抽出(mabstractcluster)の後にコールする
int mabstracttable(int clusterlayer,int from,int to);
入力
int clusterlayer; // クラスタを抽出したレイヤ
int from; // 表を抽出するレイヤ
int to; // 抽出した表の移動先
返り値
0以上.............抽出した表の数
MEMORY_SHORTAGE...メモリ不足
// 抽出した表の数の取得
int mgettablenum();
// 抽出した表の取得
ALTABLE* mgettable(); // 内部のポインタを指しているので、解放、変更は不可
表に属するクラスタのアドレスはALTABLE構造体に格納されている。各クラスタが表の何行目、何列目に属するかは、クラスタ構造体のline、columnメンバに代入されている。行と列のカウントは1行目、1列目から始まる。
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
// クラスタの抽出
ret = pjocrprim->mabstractcluster(0,1);
// 表の抽出
ret = pjocrprim->mabstracttable(1,0,1);
int tablenum = pjocrprim->mgettablenum();
if(tablenum) {
// 表の取得
ALTABLE* ptable = pjocrprim->mgettable();
....
}
delete pjocrprim;
...
// 矩形内にかかるプリミティブをfromからtoへ移動
int moveprimrecthook(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
// 矩形内にかかるプリミティブをfromからtoへ移動+移動したプリミティブをクラスタ化
int moveprimrecthookcluster(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
入力
int x1,y1; // 長方形の座標
int x2,y2;
int from; // 移動元レイヤ
int to; // 移動先レイヤ
int mojiflag; // 1の場合は、msetpointで指示された文字サイズに収まるプリミティブだけを移動する
// オーバーライド(文字の定義)でmojifilter関数をオーバーライドしている場合は、そちらを優先
返り値
0以上..........移動したプリミティブの数
負.............MEMORY_SHORTAGEメモリ不足
// 斜め矩形内にかかるプリミティブをfromからtoへ移動
int moveprimrecthook(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
// 斜め矩形内にかかるプリミティブをfromからtoへ移動をクラスタ化
int moveprimrecthookcluster(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
入力
int x1,y1; // 斜め矩形の座標(座標の順番は任意)
int x2,y2;
int x3,y3;
int x4,y4;
int from; // 移動元レイヤ
int to; // 移動先レイヤ
int mojiflag; // 1の場合は、msetpointで指示された文字サイズに収まるプリミティブだけを移動する
// オーバーライド(文字の定義)でmojifilter関数をオーバーライドしている場合は、そちらを優先
返り値
0以上..........移動したプリミティブの数
負.............MEMORY_SHORTAGEメモリ不足
// 矩形内に完全に含まれるプリミティブをfromからtoへ移動
int moveprimrect(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
// 矩形内に完全に含まれるプリミティブをfromからtoへ移動をクラスタ化
int moveprimrectcluster(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
入力
int x1,y1; // 長方形の座標
int x2,y2;
int from; // 移動元レイヤ
int to; // 移動先レイヤ
int mojiflag; // 1の場合は、msetpointで指示された文字サイズに収まるプリミティブだけを移動する
// オーバーライド(文字の定義)でmojifilter関数をオーバーライドしている場合は、そちらを優先
返り値
0以上..........移動したプリミティブの数
負.............MEMORY_SHORTAGEメモリ不足
// 斜め矩形内完全に含まれるプリミティブをfromからtoへ移動
int moveprimrect(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
// 斜め矩形内完全に含まれるプリミティブをfromからtoへ移動をクラスタ化
int moveprimrectcluster(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
入力
int x1,y1; // 斜め矩形の座標(座標の順番は任意)
int x2,y2;
int x3,y3;
int x4,y4;
int from; // 移動元レイヤ
int to; // 移動先レイヤ
int mojiflag; // 1の場合は、msetpointで指示された文字サイズに収まるプリミティブだけを移動する
// オーバーライド(文字の定義)でmojifilter関数をオーバーライドしている場合は、そちらを優先
返り値
0以上..........移動したプリミティブの数
負.............MEMORY_SHORTAGEメモリ不足
// 直線に接触するプリミティブをfromからtoへ移動
int moveprimline(int x1,int y1,int x2,int y2,int from,int to);
// 直線に接触するプリミティブをfromからtoへ移動をクラスタ化
int moveprimlinecluster(int x1,int y1,int x2,int y2,int from,int to);
入力
int x1,y1; // 直線の始点
int x2,y2; // 直線の終点
int from; // 移動元レイヤ
int to; // 移動先レイヤ
返り値
0以上..........移動したプリミティブの数
負.............MEMORY_SHORTAGEメモリ不足
// 直線に接触するプリミティブ+プリミティブの構成する矩形に含まれるプリミティブをfromからtoへ移動
int moveprimlinestring(int x1,int y1,int x2,int y2,int from,int to,double* px,double* py);
入力
int x1,y1; // 直線の始点
int x2,y2; // 直線の終点
int from; // 移動元レイヤ
int to; // 移動先レイヤ
double* px; // sizeof(double) * 4の配列のアドレス(動作チェック用)
double* py; // sizeof(double) * 4の配列のアドレス(動作チェック用)
返り値
0以上.............移動したプリミティブの数
MEMORY_SHORTAGE...メモリ不足
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
...
// マウス等で(x1,y1)から(x2,y2)までの座標を指定する
...
double x[4];
double y[4];
ret = pjocrprim->moveprimlinestring(x1,y1,x2,y2,from,to,x,y);
if(ret > 0) {
CLUSTER cluster;
pjocrprim->mgetvalidcluster(&cluster);
double angle;
angle = atan2((double)(y2 - y1),(double)(x2 - x1));
// ユーザーが指定した線分の角度から±5度の範囲で角度推定
pjocrprim->mcalcanglespec(&cluster,angle);
double dh,dv;
// 外接枠の計算(プリミティブの外接枠の外接枠を計算)
pjocrprim->mcalcframe(mpcluster,angle,x,y,dh,dv);
...
}
delete pjocrprim;
...
// ノイズをlayerに移動
int movenoise(int xsize,int ysize,int from,int to);
入力
int xsize; // 幅xsizeピクセル以下かつ高さysizeピクセル以下
int ysize; // をノイズとして処理する
int from; // 移動元レイヤ
int to; // 移動先レイヤ
返り値
0以上..........移動したプリミティブの数
負.............MEMORY_SHORTAGEメモリ不足
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
// 雑音の選択
pjocrprim->movenoise(7,7,0,1); // 縦横いずれも7ピクセル以下の4連結bit1領域を雑音とする
// 雑音に相当するプリミティブをレイヤ1へ移動する
// 雑音の除去
pjocrprim->mdeleteprim(1); // レイヤ1のプリミティブを消去する
// 元データにも反映する
delete pjocrprim;
...
// 最外周フレームに接触するプリミティブをlayerへ移動
int movetouchframe(int from,int to);
入力
int from; // 移動元レイヤ
int to; // 移動先レイヤ
返り値
0以上..........移動したプリミティブの数
負.............MEMORY_SHORTAGEメモリ不足
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
// 枠に接触するプリミティブの選択
pjocrprim->movetouchframe(0,1); // 最外周に接触するプリミティブをレイヤ1へ移動する
// 枠に接触するプリミティブの除去
pjocrprim->mdeleteprim(1); // レイヤ1のプリミティブを消去する
// 元データにも反映する
delete pjocrprim;
...
// プリミティブをレイヤfromからtoに移動
int moveprim(int from = 0,int to = 1);
入力
int from; // 移動元レイヤ
int to; // 移動先レイヤ
返り値
移動したプリミティブの数
// プリミティブをレイヤfromからtoに移動(長方形指定)
int moveprimloc(int x1,int y1,int x2,int y2,int from,int to);
入力
int x1,int y1,int x2,int y2; // (x1,y1)-(x2,y2) 長方形の左上、右下座標
返り値
移動したプリミティブの数
// amin<= pixel <= amaxピクセルのプリミティブをレイヤfromからtoに移動
int moveprimpixel(int amin,int amax,int from = 0,int to = 1);
入力
int amin,amax; プリミティブの最小面積と最大面積
返り値
移動したプリミティブの数
// amin<= 面積 <= amax、heightmin <= 高さ <= heightmax、widthmin <= 幅 <= widthmaxのプリミティブをレイヤfromからtoに移動
int moveprimsizepixel(int areamin,int areamax,int widthmin,int heightmin,int widthmax,int heightmax,int from,int to);
入力
int areamin,int areamax; 面積の範囲(単位:平方ピクセル)
int widthmin,heightmin; 幅と高さの最小値(単位:ピクセル)
int widthmax,heightmax; 幅と高さの最大値(単位:ピクセル)
返り値
移動したプリミティブの数
// layer上のプリミティブ除去と元画像への反映
void mdeleteprim(int layer);
入力
int layer; // 移動先レイヤ
// プリミティブ→ビットマップ逆変換 // 幅と高さは元のドキュメントと同じ // コールする側でバッファを確保、管理、解放する // 入力 // int layer; 0~255...逆変換するレイヤ // 出力 // unsigned char* pdata; ビットマップ void makebitmap(int layer,unsigned char* pdata);
// バッファの管理はライブラリ内部で行われる // 入力 // CLUSTER* pcluster; クラスタ // double angle; 回転角 // 出力 // unsigned char*& pdata; ビットマップ // int& width; ビットマップの幅(ピクセル単位) // int& height; ビットマップの高さ(ピクセル単位) // クラスタのビットマップ取得 void makebitmapcluster(CLUSTER* pcluster,unsigned char*& pdata,int& width,int& height); // クラスタに属するプリミティブをangleライジアン回転したビットマップを返す // クラスタのビットマップ取得(angleラジアン回転) void makebitmapcluster(CLUSTER* pcluster,double angle,unsigned char*& pdata,int& width,int& height);
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// ライセンサーから供給される20桁のコードあるいはライセンスコードファイルのパスを指定して、ライブラリを初期化
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// ライセンスコードパスの場合はCJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // 背景が0前景が1のモノクロ画像
ret = pjocrprim->makeprim();
if(ret < 0) {
エラー;
}
// ユーザーの操作でプリミティブをレイヤ1へ移動
// 斜め矩形内にかかるプリミティブをfromからtoへ移動+移動したプリミティブをクラスタ化
pjocrprim->moveprimrecthookcluster(x1,y1,x2,y2,x3,y3,y4,y4,0,1);
// クラスタを取得
// クラスタのビットマップ取得(angleラジアン回転)
double angle = atan2((double)(y2 - y1),(double)(x2 - x1));
mpjocrprim->makebitmapcluster(mpjocrprim->mgetcluster(),angle,pdata,width,height);
// pdataにwidth×heightピクセルデータが入る
// 矩形の(x1,y1)-(x2,y2)が水平になるようにangle角回転される
delete pjocrprim;
...
// 入力
// int layer; 表示用データに変換するレイヤ(モノクロのみ)
// int width; 作成する画像の幅
// int height; 作成する画像の高さ
// int offsetx; x軸オフセット
// int offsety; y軸オフセット
// double mag; 倍率(等倍は1.0)
// 出力
// unsigned char* pdata; 表示用のデータ(width×heightのdibを入れるために十分なサイズ)
// 指定レイヤDIBモノクロ(4バイトバウンダリ)
void makedispdatadib2(int layer,int width,int height,int offsetx,int offsety,double mag,unsigned char* pdata);
// DIB255色カラー画像データ作成(4バイトバウンダリ)
// 属するレイヤ=パレットインデックスになる
void makedispdatadib255(int width,int height,int offsetx,int offsety,double mag,unsigned char* pdata);
// プリミティブ特徴計算 // int mcalcfeature(); // プリミティブ特徴計算(面積のみ) // int mcalcfeaturepixel();
// カスタマイズを反映するクラスタ抽出 // int mabstractclusterfilter(int from,int to); // オーバーライド用の関数 // 返り値が1のものをクタスタ化の対象とする // virtual int mprimitivefilter(PRIMITIVE* prim); // 返り値が1のものを一つのクラスタにまとめる // virtual int mlocationfilter(PRIMITIVE* prim1,PRIMITIVE* prim2); // 返り値が1のものを有効クラスタとする // virtual int mclusterfilter(CLUSTER* pcluster);オーバーライド用の三つの仮想関数を用いて、クラスタ抽出をカスタマイズします。オーバーライドをするには、CJocrPrimクラスのサブクラスを定義する必要があります。また、オーバーライド関数、mlocationfilterの中では、以下の関数を使うことができます。
// 二つのプリミティブの間にセパレータ(クラスタに属さない図形の一部)があるときに1を返す。 // virtual int mlocationfilter(PRIMITIVE* prim1,PRIMITIVE* prim2);オーバーライドを使ったクラスタ抽出のコード例を以下にあげます。
class CJocrSub : public CJocrPrim {
public:
CJocrSub(char* code) : CJocrPrim(alcode){}
~CJocrSub(){}
private:
int minpixel; // プリミティブの最小面積
int maxpixel; // プリミティブの最大面積
double minrate; // プリミティブの最小高さ/幅
double maxrate; // プリミティブの最大高さ/幅
private:
double mindist; // プリミティブ間の最小距離
double maxdist; // プリミティブ間の最大距離
private:
int mleft; // クラスタの位置(左上)
int mtop; // クラスタの位置(左上)
int mright; // クラスタの位置(右下)
int mbottom; // クラスタの位置(右下)
public:
void msetparameter(int aminpixel,int amaxpixel,double aminrate,double amaxrate)
{
minpixel = aminpixel; // プリミティブの最小面積
maxpixel = amaxpixel; // プリミティブの最大面積
minrate = aminrate; // プリミティブの最小高さ/幅
maxrate = amaxrate; // プリミティブの最大高さ/幅
}
void msetparameter(double amindist,double amaxdist)
{
mindist = amindist;
maxdist = amaxdist;
}
void msetparameter(int left,int top,int right,int bottom)
{
mleft = left; // クラスタの位置(左上)
mtop = top; // クラスタの位置(左上)
mright = right; // クラスタの位置(右下)
mbottom = bottom; // クラスタの位置(右下)
}
public:
// オーバーライド
virtual int mprimitivefilter(PRIMITIVE* prim)
{
PRIMFEATURE* feature = prim->feature;
if(feature && minpixel <= feature->pixel && feature->pixel <= maxpixel)
return 1;
return 0;
}
// オーバーライド
virtual int mlocationfilter(PRIMITIVE* prim1,PRIMITIVE* prim2)
{
double cx1 = (prim1->xmin + prim1->xmax) / 2.0;
double cy1 = (prim1->ymin + prim1->ymax) / 2.0;
double cx2 = (prim2->xmin + prim2->xmax) / 2.0;
double cy2 = (prim2->ymin + prim2->ymax) / 2.0;
double d = sqrt((cx2 - cx1) * (cx2 - cx1) + (cy2 - cy1) * (cy2 - cy1));
if(mindist <= d && d < maxdist && !mcheckseparator(prim1,prim2))
return 1;
return 0;
}
// オーバーライド
virtual int mclusterfilter(CLUSTER* pcluster)
{
if(pcluster->xmin < mleft) return(0);
if(mright < pcluster->xmax) return(0);
if(pcluster->ymin < mtop) return(0);
if(mbottom < pcluster->ymax) return(0);
return(1);
}
};
基本クラスでは、プリミティブのサイズによってクラスタ化の対象とするかどうかを決めますが、サブクラスでは、プリミティブの面積と縦横比でクラスタ化の対象とするかどうかを決めます。// カスタマイズを反映するレイヤ間移動関数 // int moveprimfilter(int from,int to); // オーバーライド用の関数 // 返り値が1のものを移動の対象とする // virtual int mprimitivefilter(PRIMITIVE* prim);オーバーライド用の1つの仮想関数を用いて、レイヤ間移動をカスタマイズします。オーバーライドをするには、CJocrPrimクラスのサブクラスを定義する必要があります。オーバーライド(クラスタ抽出)を参照してください。
// 返り値1のものを移動する
virtual int mojifilter(PRIMITIVE* prim);
入力
PRIMITIVE* prim; // 判定対象のプリミティブ
返り値
1...primは文字の全部あるいは一部である
0...primは文字の一部でも全部でもない
virtual int mojifilter(PRIMITIVE* prim)
{
int width = prim->xmax - prim->xmin;
int height = prim->ymax - prim->ymin;
if(width <= mdpi / 2 && height <= mdpi / 2)
return(1);
else
return(0);
}
// プリミティブ
// プリミティブ領域の保存サイズ取得
// 返り値
// プリミティブの内容を全て保存するために必要なバッファサイズ
int mgetsavesize();
// プリミティブのレイヤ等の保存
// 入力/出力
// char* buffer; プリミティブの内容を保存するバッファ
// mgetsavesizeで取得したサイズ以上が必要
// バッファには以下のようにデータが入ります
// +----------------------+
// | 有効プリミティブ数 n | 4bytes
// +----------------------+
// | PRIMITIVE 0 | sizeof(PRIMITIVE)
// +----------------------+
// | PRIMITIVE 1 | sizeof(PRIMITIVE)
// +----------------------+
// | PRIMITIVE ... | sizeof(PRIMITIVE)
// +----------------------+
// | PRIMITIVE n - 1 | sizeof(PRIMITIVE)
// +----------------------+
// 返り値
// 0....正常終了
// 負...エラー
int makesavebuffer(char* buffer);
// プリミティブのレイヤ等の読み込み
// 前提:全く同じ画像で、同じ連結条件(4連結か8連結か)でmakeprimが終了している必要がある
// 注意:mgetsavesizeで取得したバッファとmreflectloadbufferで与えるバッファとは少し異なっている
// 入力
// int rvalidnum; mgetsavebufferで取得したバッファの先頭4バイト(有効プリミティブ数)
// char* buffer; mgetsavebufferで取得したバッファの先頭4バイトを除いたもの
// +----------------------+
// | PRIMITIVE 0 | sizeof(PRIMITIVE)
// +----------------------+
// | PRIMITIVE 1 | sizeof(PRIMITIVE)
// +----------------------+
// | PRIMITIVE ... | sizeof(PRIMITIVE)
// +----------------------+
// | PRIMITIVE n - 1 | sizeof(PRIMITIVE)
// +----------------------+
int mreflectloadbuffer(int rvalidnum,char* buffer);
// 0....正常終了
// 負...エラー(画像やmakeprimの条件が異なっている場合を含む)
// クラスタ情報
// クラスタの保存サイズ取得
// 入力
// CLUSTER* pcluster; 保存サイズを取得するクラスタ
// 返り値
// pclusterを保存するために必要なバッファのサイズ
int mgetsaveclustersize(CLUSTER* pcluster);
// クラスタ保存バッファの生成
// 入力
// CLUSTER* pcluster; 保存するクラスタ
// 入出力
// char* buffer; クラスタの内容、mgetsaveclustersize/0で取得したサイズ以上必要
// +----------------------+
// | CLUSTER | sizeof(CLUSTER)
// +----------------------+--------------------
// | | sizeof(int) これ以下をmrellectclusterbufferの第2引数で渡す
// +----------------------+
// | | sizeof(int)
// +----------------------+
// | | sizeof(int)
// +----------------------+
// 返り値
// 0....正常終了
// 負...エラー
int makesaveclusterbuffer(CLUSTER* pcluster,char* buffer);
// クラスタ本体のロード(CLUSTERをロードして、pprim領域を確保後、pprim領域をロード)
// プリミティブのレイヤ等の読み込み
// 前提:全く同じ画像で、同じ連結条件(4連結か8連結か)でmakeprimが終了している必要がある
// 注意:この関数を呼ぶ前にsizeof(CLUSTER)の領域を確保して、mgetsaveclusterbufferで保存したバッファの先頭の
// sizeof(CLUSTER)バイトをコピーする
// 入力
// CLUSTER* pcluster; 上記「注意」を参照
// int* pi; mgetsavebufferで取得したバッファの先頭sizeof(CLUSTER)バイトを除いたもの
// 返り値
// 0....正常終了
// 負...エラー
int mreflectclusterbuffer(CLUSTER* pcluster,int* pi);
int mgetmemoryinfo();
// プリミティブ構造編集
// 挿入可能なプリミティブ数の上限を設定する
// 上限に達した場合は、medit_insertやmedit_separateでエラーが返る
// その場合はクラスをいったん破棄して、再度new、その後msetinsertmaxしなおしてから再挿入
// 入力
// int insertmax; デフォルト値は0、通常のA3,400dpi日本語文書では10000で十分
void msetinsertmax(int insertmax){minsertmax = insertmax;}
// プリミティブを削除 // 重複プリミティブ対応 // 入力 // int flag; 1...画像データに反映させる // PRIMITIVE* prim; プリミティブ(アドレスを用いるのでコピーは駄目) int medit_delete(int flag,PRIMITIVE* prim); int medit_delete(int flag,CLUSTER* pcluster); // プリミティブを挿入(pjocrprimがthisの場合はコピーとなる) // 入力 // int flag; 1...画像データに反映させる // CJocrPrim* pjocrprim; prim/pclusterの属するCJocrPrimのインスタンス // PRIMITIVE* prim; 挿入プリミティブ(アドレスを用いるのでコピーは駄目) // CLUSTER* pcluster; primの属するCJocrPrimのインスタンス // int left,top; 移動先 int medit_insert(int flag,CJocrPrim* pjocrprim,PRIMITIVE* prim,int left,int top,PRIMITIVE*& priminsert); int medit_insert(int flag,CJocrPrim* pjocrprim,CLUSTER* pcluster,int left,int top); // プリミティブを移動(コピー+削除ではコストが大きいためこちらを用いると良い) // 入力 // int flag; 1...画像データに反映させる // PRIMITIVE* prim; プリミティブ(アドレスを用いるのでコピーは駄目) // int left,top; 移動先 int medit_move(int flag,PRIMITIVE* prim,int left,int top); int medit_move(int flag,CLUSTER* pcluster,int left,int top);
// 全てのプリミティブをクラスタ化 // レンダリングやクラスタ移動に用いる int mallprim2cluster();
// クラスタを分割(ピクセルデータの消長が存在しない。表示上切れ目は存在しない) // (処理コストが高いので注意:分割対象が多い場合は再初期化のほうが速い) // 入力 // int linenum; 線分の数 // int* px1; 線分始点のx座標値 // int* py1; 線分始点のy座標値 // int* px2; 線分終点のx座標 // int* py2; 線分終点のy座標 // CLUSTER* pcluster; 切断対象のクラスタ // 返り値 // 0.......正常終了 // 負......エラー int medit_separate(int linenum,int* px1,int* py1,int* px2,int* py2,CLUSTER* pcluster); int medit_sever(int linenum,int* px1,int* py1,int* px2,int* py2,CLUSTER* pcluster); // ひとつのプリミティブから線分と線幅を指定した線ラスタの分離
// ポリライン(始点と終点がつながった複数の線分)に沿ったプリミティブの分離 // 入力 // int flag; 0...ビットマップに反映しない // 1...ビットマップに反映する // int bridgeflag; 0...ブリッジ処理を行わない // 1...ブリッジ処理を行う // int horizontalflag; 0...斜め線 // 1...水平・垂直線が対象(通常は0のままでもOK) // int pointnum; ポリラインのポイント数 // int* px; pointnum個のx座標値 // int* py; pointnum個のy座標値 // int lwidth; 線幅 // PRIMITIVE* prim; 元のプリミティブ、primが削除されて分割されたプリミティブが挿入される // 返り値 // 0.......正常終了 // 負......エラー int medit_separateline(int flag,int bridgeflag,int horizontalflag,int pointnum,int* px,int* py,int lwidth,PRIMITIVE* prim);
int mgetprim2rlbuffersize(); // 返り値 // プリミティブ構造にバッファ変換したときのバッファサイズ int mprim2rl(unsigned char* retbuffer); // プリミティブ構造のバッファ変換 // 入力 // unsigned char* retbuffer; mgetprim2rlbuffersizeで取得したサイズのバッファ // 返り値 // 0.......正常終了 // 負......エラー int mrl2prim(unsigned char* buffer); // プリミティブ構造の再現 // 入力 // unsigned char* buffer; PRIMRLバッファ==mprim2rlで取得したもの // 返り値 // 0.......正常終了 // 負......エラー
// バッファの管理はライブラリ内部で行われる // 入力 // PRIMITIVE* prim; プリミティブ // 出力 // unsigned char*& pdata; ビットマップ // int& width; ビットマップの幅(ピクセル単位) // int& height; ビットマップの高さ(ピクセル単位) // クラスタのビットマップ取得 // プリミティブのビットマップ取得 void makebitmapprimitive(PRIMITIVE* prim,unsigned char*& pdata,int& width,int& height);
目次
マニュアルホームページ