この仕事は天職だと感じたアルゴリズム開発(続1)
この仕事は天職だと感じたアルゴリズム開発(続1)
このエッセイは、
『この仕事は天職だと感じたアルゴリズム開発』の直接の
続編です!
2024年12月8日初稿
1.引数検査MultcheckArrayMeasure()
/************************************************************************/
/***** 引数配列の検査:5引数を検査 *****/
/************************************************************************/
int CopyClear::MultcheckArrayMeasure(
int ord, // 引数順位
int size, // 計測結果 BufSize
TypeArray *p1, // 検査配列情報ptr1
TypeArray *p2, // 検査配列情報ptr2
TypeArray *p3, // 検査配列情報ptr3
TypeArray *p4, // 検査配列情報ptr4
TypeArray *p5 // 検査配列情報ptr5
){
TypeArray *tbl[ 5 ]; // 検査配列情報Table
TypeArray **pp; // 配列情報ptrのptr
TypeArray *p; // 配列情報ptr
int i; // カウンタ
tbl[ 0 ] = p1; // 一旦、テーブルに
tbl[ 1 ] = p2; // 配列情報ポインタ
tbl[ 2 ] = p3; // をセット
tbl[ 3 ] = p4; //
tbl[ 4 ] = p5; //
pp = tbl; // 検査ポインタSet
for( i = 5; --i >= 0; pp++ ){ // 5回繰り返す
p = *pp; // 配列情報ptr取出
if( p != 0 ){ // ポインタ有効なら
size = CheckArrayMeasure( p, ord, size ); // 配列検査
} //
ord += 10; // 順位更新
} //
return( size ); // サイズを返す
}
(1)関数名
「Mult」は、「複数の」との意味で使用
「check」は、「検査」との意味で使用
「Array」は、「一次元配列」の意味で使用
「Measure」は、「計測」でココでは、計測結果を意味
だから、「ArrayMeasure」で計測結果を格納する配列で
「MultcheckArrayMeasure」で複数に渡る項目の計測結果を
格納する配列の検査を意味します!
(2)仮引数
int CopyClear::MultcheckArrayMeasure(
int ord, // 引数順位
int size, // 計測結果 BufSize
TypeArray *p1, // 検査配列情報ptr1
TypeArray *p2, // 検査配列情報ptr2
TypeArray *p3, // 検査配列情報ptr3
TypeArray *p4, // 検査配列情報ptr4
TypeArray *p5 // 検査配列情報ptr5
){
「int ord,」は、エラー発生時のエラーコードに引数の場所
を特定する為の目印≪順番と言う事で「order」の省略≫
「int size,」は、格納する配列サイズの制限値です!
「TypeArray* p1,」は、最初の「TypeArray*」型の配列情報
「TypeArray* p2,」は、2番目「TypeArray*」型の配列情報
「TypeArray* p3,」は、3番目「TypeArray*」型の配列情報
「TypeArray* p4,」は、4番目「TypeArray*」型の配列情報
「TypeArray* p5,」は、5番目「TypeArray*」型の配列情報
※ナゼ、「TypeArray*」型の配列情報を使用したかは、
ADS社の画像処理装置用のコマンド言語≪解説『参考:
ADS社画像処理装置』で説明しています!≫で呼び出し易
い形として用意したからでC言語のライブラリ関数として
作成した訳で無いからですが、特徴としてデータ型が整数・
浮動小数点型等色々「TypeArray*」型の配列情報のデータ型
を示すメンバー変数「char w;」で指定出来可変設定可能な
便利なデータ型です詳細は、
解説『解説クラスTypeArray』を参考にして下さ
い!
(3)ローカル変数数
){
TypeArray *tbl[ 5 ]; // 検査配列情報Table
TypeArray **pp; // 配列情報ptrのptr
TypeArray *p; // 配列情報ptr
int i; // カウンタ
「TypeArray tbl[5];」は、複数の「TypeArray」型の配列
情報をforループで検査処理する為の一次置き場テーブル
「TypeArray **pp;」は、上記テーブルへのポインタ変数
「TypeArray p;」は、実際に検査する「TypeArray」型の
配列
「int i;」は、5回繰り返す為のループカウンタ
(4)アルゴリズム
tbl[ 0 ] = p1; // 一旦、テーブルに
tbl[ 1 ] = p2; // 配列情報ポインタ
tbl[ 2 ] = p3; // をセット
tbl[ 3 ] = p4; //
tbl[ 4 ] = p5; //
pp = tbl; // 検査ポインタSet
for( i = 5; --i >= 0; pp++ ){ // 5回繰り返す
p = *pp; // 配列情報ptr取出
if( p != 0 ){ // ポインタ有効なら
size = CheckArrayMeasure( p, ord, size ); // 配列検査
} //
ord += 10; // 順位更新
} //
return( size ); // サイズを返す
}
「tbl[0]=p1;tbl[1]=p2;tbl[2]=p3;tbl[3]=p4;tbl[4]=p5;」
は、ローカルテーブル変数に仮引数のポインタ値を格納!
「pp=tbl;」は、テーブルをポインタ化
「for(i=5;--i>=0;pp++){・・ループ中身・・}」は、
forループ構文「for(i=5;--i>=0;pp++)」で5回繰り返
し、「pp++」とテーブルアクセスポインタを進行しループの
中身は、「p=pp;」で仮引数のポインタ変数を取り出し、
「if(p!=0){size=CheckArrayMeasure(p,ord,size);}」で
ポインタの値が有効(≠0)なら、
「size=CheckArrayMeasure(p,ord,size);」と下請け関数
「CheckArrayMeasure()」で「TypeArray」型の配列型の
配列の最小値を算出、
「ord+=10;」で仮引数の位置を示す「ord」値を「10」毎増
やしてドノ場所か示す!
ループが終わると「return(size);」配列のサイズ及び、
エラーコードを関数辺値とし返し終了!
2.引数検査CheckArrayMeasure()
/************************************************************************/
/***** 引数検査関数:結果配列の検査とサイズの調整 *****/
/************************************************************************/
int CopyClear::CheckArrayMeasure(
TypeArray *pa, // 配列
int ord, // 引数順位 10,20,,,
int size // 計測結果BUF-SIZE
){
int w; // 処理単位
if( size < 0 ){ // 前の検査不正なら
return( size ); // サイズを返す
} //
if( pa == 0 ){ // 結果配列が空なら
return( STI_ARY_0 - ord ); // 左記を返す
}else if( pa->adr == 0 ){ // アドレスが空なら
return( size ); // サイズを返す
}else if( ( w = pa->w ) <= 0 || w == 3 // 処理単位が不正
|| w > 102 || ( w > 4 && w < 101 ) ){ // なら
return( STI_ARY_5 - ord ); // 左記を返す
}else if( size > pa->h ){ // サイズ更新時は
size = pa->h; // 更新
} //
return( size ); // サイズを返す
}
(1)関数名
「Check」は、「検査」との意味で使用
「Array」は、「一次元配列」の意味で使用
「Measure」は、「計測」でココでは、計測結果を意味
だから、「ArrayMeasure」で計測結果を格納する配列で
計測結果を格納する配列の検査とサイズ取得を意味します!
(2)仮引数
int CopyClear::CheckArrayMeasure(
TypeArray *pa, // 配列
int ord, // 引数順位 10,20,,,
int size // 計測結果BUF-SIZE
){
「TypeArray* pa,」は、「TypeArray*」型の配列情報
「int ord,」は、エラー発生時のエラーコードに引数の場所
を特定する為の目印≪順番と言う事で「order」の省略≫
「int size,」は、格納する配列サイズの制限値です!
※ナゼ、「TypeArray*」型の配列情報を使用したかは、
ADS社の画像処理装置用のコマンド言語≪解説『参考:
ADS社画像処理装置』で説明しています!≫で呼び出し易
い形として用意したからでC言語のライブラリ関数として
作成した訳で無いからですが、特徴としてデータ型が整数・
浮動小数点型等色々「TypeArray*」型の配列情報のデータ型
を示すメンバー変数「char w;」で指定出来可変設定可能な
便利なデータ型です詳細は、
解説『解説クラスTypeArray』を参考にして下さ
い!
(3)ローカル変数
){
int w; // 処理単位
「int w;」は、格納する配列の処理単位
(4)アルゴリズム
if( size < 0 ){ // 前の検査不正なら
return( size ); // サイズを返す
} //
if( pa == 0 ){ // 結果配列が空なら
return( STI_ARY_0 - ord ); // 左記を返す
}else if( pa->adr == 0 ){ // アドレスが空なら
return( size ); // サイズを返す
}else if( ( w = pa->w ) <= 0 || w == 3 // 処理単位が不正
|| w > 102 || ( w > 4 && w < 101 ) ){ // なら
return( STI_ARY_5 - ord ); // 左記を返す
}else if( size > pa->h ){ // サイズ更新時は
size = pa->h; // 更新
} //
return( size ); // サイズを返す
}
「if(size<0){return(size);}」は、サイズの制限値が、
負の数は、エラーコードと見なして関数辺値とし返し終了!
「if(pa==0){return(STI_ARY_0-ord);}」は、仮引数の
ポインタ値自体が空ならば、エラーコード「STI_ARY_0」と
「-ord」でエラー発生時順番を示す値≪10,20,30・・と10
刻みで設定≫を合成したエラーコードを関数辺値とし返し
終了!
「else if(pa->adr==0){return(size);}」は、格納する配列
のポインタ値が空ならば、サイズの制限値関数辺値とし返し
終了!
「else if((w=pa->w)<=0||w==3||w>102||(w>4&&w<101)){
return(STI_ARY_5-ord);}」は、データ格納する配列の単位
が整数型「1=1バイト単位・2バイト単位=・4=4バイト
単位」か浮動小数点数「101=単精度・102=倍精度」以外な
ら、エラーコード「STI_ARY_5」と「-ord」でエラー発生時
順番を示す値≪10,20,30・・と10刻みで設定≫を合成した
エラーコードを関数辺値とし返し終了!
「else if(size>pa->h){size=pa->h;}」は、配列のサイズ
「pa->h」が制限値より小さい場合は、サイズを更新し、
「return(size);」は、サイズを関数辺値とし返し終了!
3.2値化画像取得&作成temp_bin()
/************************************************************************/
/***** MEASURE_???()系コマンド用前処理 *****/
/***** ☆temp画像に2値化画像(0,1)を作成しその上で計測☆ *****/
/***** 返値: END_STI→成功/STI_MEM→メモリ不足/その他→配列違反*****/
/************************************************************************/
int Filter::temp_bin(
TypeArray *ps, // 元画像情報
TypeArray *pt // Temp画像情報
){
void *p; // 画像Ptr
int t; // 2値しきい値
if( ps == 0 ){ // 画像情報が空なら
return( STI_ARY_0 - 10 ); // 左記を返す
}else if( ps->adr == 0 ){ // 画像Ptrが空なら
return( STI_ARY_1 - 10 ); // 左記を返す
}else if( ps->h <= 0 ){ // 水平幅不正なら
return( STI_ARY_2 - 10 ); // 左記を返す
}else if( ps->v <= 0 ){ // 垂直幅不正なら
return( STI_ARY_3 - 10 ); // 左記を返す
}else if( ps->inc < ps->h ){ // 増加幅不正なら
return( STI_ARY_4 - 10 ); // 左記を返す
}else if( ps->w != 1 ){ // 1BYTE以外なら
return( STI_ARY_5 - 10 ); // 左記を返す
} //
t = m_TblModeMeasureBase[1]; // しきい値を取出し
if( t <= 0 || t > 255 ){ // 無効な場合
*pt = *ps; // 画像情報をCOPYし
return( END_STI ); // 正常終了
} //
p = malloc( ps->h * ps->v ); // メモリを取得
if( p == 0 ){ // 取得失敗時は
return( STI_MEM ); // 左記を返す
} //
pt->adr = (int)p; // アドレスセット
pt->h = ps->h; // 水平幅セット
pt->v = ps->v; // 垂直幅セット
pt->inc = ps->h; // 増加幅セット
pt->w = 1; // 処理幅セット
Binarization( ps, pt, t, 1, 0 ); // 2値化(0,1)
return( END_STI ); // 正常終了
}
(1)関数名
「temp」は、「テンポラリ一時的」との意味で使用
「bin」は、「2値化画像」の意味で使用
だから、「temp_bin」で一時的な2値化画像を動的にメモリ
確保し2値化画像を作成する事を意味します!
(2)仮引数
int Filter::temp_bin(
TypeArray *ps, // 元画像情報
TypeArray *pt // Temp画像情報
){
「TypeArray *ps,」は、元画像(S≒ソース画像)を示す
「TypeArray *pt」は、一時的な2値化画像情報へのポイン
タを示す
(3)ローカル変数
){
void *p; // 画像Ptr
int t; // 2値しきい値
「void* p;」は、汎用ポインタ型「void*」でC言語標準
関数「malloc()」で動的メモリ確保したポインタ!
「int t;」は、2値化しきい値
(4)関連
int m_TblModeMeasureBase[10]; // MeasureBase系設定テーブル
// [1] 0 :2値変換無効
// 1..255:MEASURE前処理
「m_TblModeMeasureBase[10];」は、元々、細かい設定パラ
メータをセットする為に「[10]」と「int型」10個分用意
したが、結局「m_TblModeMeasureBase[1];」に
2値化しきい値をセットするだけに現行の画像処理ライブラ
リで成ったが、拡張出来る設定配列です!
/************************************************************************/
/***** MEASURE_???()形の設定コマンド:実行部 *****/
/***** ☆2値化しきい値指定☆ *****/
/***** SET_MEASURE,,t *****/
/************************************************************************/
int Filter::SetMeasureBase(
int t // 0 :2値変換無効
// 1..255:MEASURE前処理
){
if( t <= 0 || t > 255 ){ // 1..255の範囲外ならば
t = 0; // 0=無効にする
} //
m_TblModeMeasureBase[1] = t; // しきい値セット
return( END_STI ); // 正常終了
}
「int Filter::SetMeasureBase(int t){
if(t<=0||t>255){t=0;}m_TblModeMeasureBase[1]=t;
return(END_STI);}」は、単にパラメータ設定配列の2値化
しきい値設定「m_TblModeMeasureBase[1]」に値をセット
する関数です!見たママの関数です!
※備考※
前準備とし、「SetMeasureBase(1);」と初期値する必要が
有ます!
(5)アルゴリズム
if( ps == 0 ){ // 画像情報が空なら
return( STI_ARY_0 - 10 ); // 左記を返す
}else if( ps->adr == 0 ){ // 画像Ptrが空なら
return( STI_ARY_1 - 10 ); // 左記を返す
}else if( ps->h <= 0 ){ // 水平幅不正なら
return( STI_ARY_2 - 10 ); // 左記を返す
}else if( ps->v <= 0 ){ // 垂直幅不正なら
return( STI_ARY_3 - 10 ); // 左記を返す
}else if( ps->inc < ps->h ){ // 増加幅不正なら
return( STI_ARY_4 - 10 ); // 左記を返す
}else if( ps->w != 1 ){ // 1BYTE以外なら
return( STI_ARY_5 - 10 ); // 左記を返す
} //
t = m_TblModeMeasureBase[1]; // しきい値を取出し
if( t <= 0 || t > 255 ){ // 無効な場合
*pt = *ps; // 画像情報をCOPYし
return( END_STI ); // 正常終了
} //
p = malloc( ps->h * ps->v ); // メモリを取得
if( p == 0 ){ // 取得失敗時は
return( STI_MEM ); // 左記を返す
} //
pt->adr = (int)p; // アドレスセット
pt->h = ps->h; // 水平幅セット
pt->v = ps->v; // 垂直幅セット
pt->inc = ps->h; // 増加幅セット
pt->w = 1; // 処理幅セット
Binarization( ps, pt, t, 1, 0 ); // 2値化(0,1)
return( END_STI ); // 正常終了
}
「if(ps==0){return(STI_ARY_0-10);}」は、仮引数の
ポインタ自体が空ならば、エラーコード「STI_ARY_0-10」を
関数辺値とし返し終了
「else if(ps->adr==0){return(STI_ARY_1-10);}」は、
画像メモリ実態を示すポインタが空ならば、
エラーコード「STI_ARY_1-10」を関数辺値とし返し終了
「else if(ps->h<=0){return(STI_ARY_2-10);}」は、
画像の水平幅が0未満ならば、
エラーコード「STI_ARY_2-10」を関数辺値とし返し終了
「else if(ps->v<=0){return(STI_ARY_3-10);}」は、
画像の垂直幅が0未満ならば、
エラーコード「STI_ARY_3-10」を関数辺値とし返し終了
「else if(ps->inc<ps->h){return(STI_ARY_4-10);}」は、
画像の増加幅が水平幅未満ならば、
エラーコード「STI_ARY_4-10」を関数辺値とし返し終了
「else if(ps->w!=1){return(STI_ARY_5-10);}」は、
画像の画素が1バイト整数以外ならば、
エラーコード「STI_ARY_5-10」を関数辺値とし返し終了
「t=m_TblModeMeasureBase[1];」は、2値化しきい値を取り
出し、
「if(t<=0||t>255){*pt=*ps;return(END_STI);}」は、
設定して有る2値化しきい値が「1..255」の範囲外ならば、
「*pt=ps;」で一時的な2値化画像への情報に元画像の情報
をコピーし、「return(END_STI);」で正常終了を関数辺値と
し返し終了!
「p=malloc(ps->hps->v);」は、元画像の画像サイズと同じ
サイズだけ動的にメモリ確保!
「if(p==0){return(STI_MEM);}」は、メモリ確保に失敗した
ら、エラーコード「STI_MEM」を関数辺値とし返し終了!
「pt->adr=(int)p;」は、一時的な2値化画像情報に確保し
たメモリを割り当て!
「pt->h=ps->h;pt->v=ps->v;pt->inc=ps->h;pt->w=1;」は、
水平幅・垂直幅等の画像情報パラメータをセット!
「Binarization(ps,pt,t,1,0);」は、下請け関数として
「Binarization()」で2値化を行う!この下請け関数は、
解説『解説クラスCopyClear(11)』の
「(4-14-12)」で説明
「return(END_STI);」は、正常終了を関数辺値とし返し
終了!
4.動的取得メモリ後始末free_temp_bin()
/************************************************************************/
/***** MEASURE_???()系コマンド用後始末 *****/
/***** 「temp_bin()」で作成したtemp画像の解放 *****/
/************************************************************************/
void Filter::free_temp_bin(
TypeArray *ps, // 元画像情報
TypeArray *pt // Temp画像情報
){
if( ps->adr != pt->adr ){ // S≠Tの場合で
if( pt->adr != 0 ){ // メモリ確保時なら
free( (void*)pt->adr ); // メモリを解放
} //
} //
}
(1)関数名
「free」は、「解放」を意味し、ココでは動的にメモリ確保
した後始末として確保したメモリを解放≪OSに返す≫です
「temp」は、「テンポラリ一時的」との意味で使用
「bin」は、「2値化画像」の意味で使用
だから、「temp_bin」で一時的な2値化画像を動的にメモリ
確保し2値化画像を作成する事を意味します!今回の
「free_temp_bin」で動的にメモリ確保したメモリの後始末を
行います!
(2)仮引数
void Filter::free_temp_bin(
TypeArray *ps, // 元画像情報
TypeArray *pt // Temp画像情報
){
「TypeArray *ps,」は、元画像(S≒ソース画像)を示す
「TypeArray *pt」は、一時的な2値化画像情報へのポイン
タを示す
(3)アルゴリズム
){
if( ps->adr != pt->adr ){ // S≠Tの場合で
if( pt->adr != 0 ){ // メモリ確保時なら
free( (void*)pt->adr ); // メモリを解放
} //
} //
}
「if(ps->adr!=pt->adr){・・分岐中身・・}」は、
条件「ps->adr!=pt->adr」で元画像と一時的な2値化画像が
独立した画像で有るならばで、条件成立した場合は、
「if(pt->adr!=0){free((void*)pt->adr);}」と
条件「pt->adr!=0」とメモリが存在している場合は、
「free((void*)pt->adr);」でC言語標準関数「free()」を
使用して動的にメモリ確保したメモリを解放≪OSに返す≫
5.標準計測実行部MeasureStandardExecute()
/************************************************************************/
/***** 図形の標準計測 :基本部 *****/
/***** MEASURE_LABEL(c,s,x,y,h,v,xl,a,mh,mv,cx,cy,len)*****/
/************************************************************************/
int Filter::MeasureStandardExecute(
int c, // 4/8連結
TypeArray *ps, // 画像
TypeArray *px, // x座標結果
TypeArray *py, // y座標結果
TypeArray *ph, // 水平径結果
TypeArray *pv, // 垂直径結果
TypeArray *pxl, // ラベルx座標結果
TypeArray *pa, // 面積結果
TypeArray *pmh, // 水平Moment結果
TypeArray *pmv, // 垂直Moment結果
TypeArray *pcx, // 重心x座標結果
TypeArray *pcy, // 重心y座標結果
TypeArray *plen, // 周囲長結果
int size // 計測結果 BufSize
){
TypeSf *buf; // 計測結果 Buffer
int n; // 計測個数
buf = (TypeSf*)malloc( sizeof(TypeSf) * ( size + 10 ) ); // 結果Bufferを確保
if( buf == 0 ){ // 確保失敗時は、
return( STI_MEM ); // 左記を返す
} //
if( ( pmh != 0 && pmh->adr != 0 ) // 1次水平Momentか
|| ( pmv != 0 && pmv->adr != 0 ) // 1次垂直Momentか
|| ( pcx != 0 && pcx->adr != 0 ) // 重心x座標か
|| ( pcy != 0 && pcy->adr != 0 ) ){ // y座標算出時は
n = MeasureMmt1( c, ps, buf, size ); // 左記で計測し
}else if( pa != 0 && pa->adr != 0 ){ // 面積を求める場合
n = MeasureArea( c, ps, buf, size ); // 左記で計測し
}else{ // 上記以外の場合は
n = MeasureFere( c, ps, buf, size ); // 左記で計測する
} //
if( size > n ){ // 個数がSize未満な
size = n; // らSizeを個数にす
} // る
get_fere( buf, px, py, ph, pv, size ); // フェレ計測値格納
GetMeasure( buf, pxl, size, 4 ); // ラベル始点を格納
get_area_mmt1( buf, pa, pmh, pmv, pcx, pcy, size ); // 面積+1次Moment+重心を格納
GetMeasure( buf, plen, size, 17 ); // 周囲長を格納
free( buf ); // Bufferを解放
return( n ); // 個数を返す
}
(1)関数名
「Measure」は、「計測」でココでは、計測を意味
「Standard」は、「標準」を意味
「Execute」は、「実行」を意味
だから、「MeasureStandardExecute」で標準計測を実際に
実行するを意味します!
(2)仮引数
int Filter::MeasureStandardExecute(
int c, // 4/8連結
TypeArray *ps, // 画像
TypeArray *px, // x座標結果
TypeArray *py, // y座標結果
TypeArray *ph, // 水平径結果
TypeArray *pv, // 垂直径結果
TypeArray *pxl, // ラベルx座標結果
TypeArray *pa, // 面積結果
TypeArray *pmh, // 水平Moment結果
TypeArray *pmv, // 垂直Moment結果
TypeArray *pcx, // 重心x座標結果
TypeArray *pcy, // 重心y座標結果
TypeArray *plen, // 周囲長結果
int size // 計測結果 BufSize
){
「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「TypeArray* ps,」は、計測対象の2値化画像、
「TypeArray* px,」は、計測結果格納としてTypeArray型
を1次元配列とて扱い「px,」とX座標結果を格納
「TypeArray py,」は、計測結果格納としてTypeArray型
を1次元配列とて扱い「py,」とY座標結果を格納
「TypeArray ph,」は、計測結果格納としてTypeArray型
を1次元配列とて扱い「ph,」と水平径(水平方向長さ)を
格納
「TypeArray pv,」は、計測結果格納としてTypeArray型
を1次元配列とて扱い「pv,」と垂直径(垂直方向長さ)を
格納
「TypeArray pxl,」は、計測結果格納としてTypeArray型
を1次元配列とて扱い「pxl,」とラベル始点X座標結果を
格納
「TypeArray pa,」は、計測結果格納としてTypeArray型
を1次元配列とて扱い「pa,」と連結塊の面積(画素数)
を格納
「TypeArray pmh,」は、計測結果格納としてTypeArray型
を1次元配列として扱い「pmh,」と水平方向の一次モーメ
ントを格納
「TypeArray pmv,」は、計測結果格納としてTypeArray型
を1次元配列として扱い「pmv,」と垂直の一次モーメント
を格納
「TypeArray pcx,」は、計測結果格納としてTypeArray型
を1次元配列として扱い「pcx,」とX座標(重心)結果を
格納
「TypeArray pcy,」は、計測結果格納としてTypeArray型
を1次元配列として扱い「pcy,」とY座標(重心)結果を
格納
「TypeArray plen」は、計測結果格納としてTypeArray型
を1次元配列として扱い「plen」と周囲長を格納
この計測項目は、解説『解説クラスTypeSf』での説明
を参考にして下さい!
「int size」は、計測結果格納する配列のサイズ≪ソレゾレ
「TypeArray」型の中にメンバー変数「->h」で指定して居
るが、全ての配列に適応可能な最小値サイズ≫
※ナゼ、「TypeArray*」型の配列情報を使用したかは、
ADS社の画像処理装置用のコマンド言語≪解説『参考:
ADS社画像処理装置』で説明しています!≫で呼び出し易
い形として用意したからでC言語のライブラリ関数として
作成した訳で無いからですが、特徴としてデータ型が整数・
浮動小数点型等色々「TypeArray*」型の配列情報のデータ型
を示すメンバー変数「char w;」で指定出来可変設定可能な
便利なデータ型です詳細は、
解説『解説クラスTypeArray』を参考にして下さ
い!
(3)ローカル変数数
){
TypeSf *buf; // 計測結果 Buffer
int n; // 計測個数
「TypeSf *buf;」は、計測結果バッファーで型「TypeSf」は
解説『解説クラスTypeSf』を参考にして下さい!
「int n;」は、計測結果個数≪連結した塊の図形の数≫
(4)アルゴリズム
buf = (TypeSf*)malloc( sizeof(TypeSf) * ( size + 10 ) ); // 結果Bufferを確保
if( buf == 0 ){ // 確保失敗時は、
return( STI_MEM ); // 左記を返す
} //
if( ( pmh != 0 && pmh->adr != 0 ) // 1次水平Momentか
|| ( pmv != 0 && pmv->adr != 0 ) // 1次垂直Momentか
|| ( pcx != 0 && pcx->adr != 0 ) // 重心x座標か
|| ( pcy != 0 && pcy->adr != 0 ) ){ // y座標算出時は
n = MeasureMmt1( c, ps, buf, size ); // 左記で計測し
}else if( pa != 0 && pa->adr != 0 ){ // 面積を求める場合
n = MeasureArea( c, ps, buf, size ); // 左記で計測し
}else{ // 上記以外の場合は
n = MeasureFere( c, ps, buf, size ); // 左記で計測する
} //
if( size > n ){ // 個数がSize未満な
size = n; // らSizeを個数にす
} // る
get_fere( buf, px, py, ph, pv, size ); // フェレ計測値格納
GetMeasure( buf, pxl, size, 4 ); // ラベル始点を格納
get_area_mmt1( buf, pa, pmh, pmv, pcx, pcy, size ); // 面積+1次Moment+重心を格納
GetMeasure( buf, plen, size, 17 ); // 周囲長を格納
free( buf ); // Bufferを解放
return( n ); // 個数を返す
}
「buf=(TypeSf*)malloc(sizeof(TypeSf)*(size+10));」は、
型「TypeSf」の計測結果バッファーを動的にメモリ確保≪
「size+10」は、少しダケ余裕でメモリ確保≫
「if(buf==0){return(STI_MEM);}」は、メモリ確保に失敗し
たら、エラーコード「STI_MEM」を関数辺値とし返し終了!
「if((pmh!=0&&pmh->adr!=0)||(pmv!=0&&pmv->adr!=0)
||(pcx!=0&&pcx->adr!=0)||(pcy!=0&&pcy->adr!=0)){
n=MeasureMmt1(c,ps,buf,size);}」は、
if分岐条件「(pmh!=0&&pmh->adr!=0)||
(pmv!=0&&pmv->adr!=0)||(pcx!=0&&pcx->adr!=0)
||(pcy!=0&&pcy->adr!=0)」で一次モーメントと重心座標
結果を格納する配列情報が有効≒一次モーメントと重心座標
を算出する必要が有る場合は、下請け
関数「n=MeasureMmt1(c,ps,buf,size);」で処理!
「else if(pa!=0&&pa->adr!=0){
n=MeasureArea(c,ps,buf,size);}」は、面積結果を格納する
配列情報が有効≒面積を算出する必要が有る場合は、下請け
関数「n=MeasureArea(c,ps,buf,size);」で処理!
「else{n=MeasureFere(c,ps,buf,size);}」は、下請け
関数「n=MeasureFere(c,ps,buf,size);」で処理!
「if(size>n){size=n;}」は、条件「size>n」で配列の
サイズが、計測結果個数未満の場合は、
「size=n;」とサイズを計測結果個数にする!下請け関数
「get_fere(buf,px,py,ph,pv,size);」は、フェレ計測結果
≪フェレ始点座標「px,py,」、水平フェレ径「ph,」、及び
垂直フェレ径「pv,」≫配列に格納!
「GetMeasure(buf,pxl,size,4);」は、下請け関数
「GetMeasure(・・・,4);」と最後の「,4)」で
ラベル始点X座標を「pxl,」配列に格納!
「get_area_mmt1(buf,pa,pmh,pmv,pcx,pcy,size);」は、
下請け関数「get_area_mmt1()」で面積「pa,」と一次モーメ
ント「pmh,pmv,」及び重心座標「pcx,pcy,」配列に格納!
「GetMeasure(buf,plen,size,17);」は、最後の「,17)」で
周囲長「plen,」配列に格納!
「free(buf);」は、計測結果バッファーを動的にメモリ確保
したが、それを解放してOSに返す!
「return(n);」は、関数辺値とし計測結果個数「n」を返し
終了!
※備考※
この中で一次モーメントと重心座標計測結果を格納する配列
が存在する場合は、下請け関数「MeasureMmt1()」で処理し
一次モーメントと重心座標計測結果が不要でも面積結果を
格納する配列が存在する場合は、下請け
関数「MeasureArea()」で処理し、一次モーメントと重心座
標計測結果及び面積結果も不要な場合は、下請け
関数「MeasureFere()」で処理と計測結果を格納する配列有
無で「MeasureMmt1()」・「MeasureArea()」及び、
「MeasureFere()」と計測結果を算出する関数を分けて不要な
処理を行って処理時間をロスしない様にしています!
基本的な動作は、同じですが、計測結果を算出する処理が、
異なります!一番シンプルな部分の「MeasureFere()」を
先ず理解してから他の処理を理解する方が理解は早い筈です
6.図形のフェレ計測MeasureFere()
/************************************************************************/
/***** 図形のフェレ計測 :計測部 *****/
/***** MEASURE_FERE(c,s,x,y,h,v,xl) *****/
/************************************************************************/
int Filter::MeasureFere(
int c, // 4/8連結
TypeArray *ps, // 画像
TypeSf buf[], // 計測結果Buffer
int lmt // Buffer格納制限
){
int sti; // ステータス情報
sti = CheckAndClearRoundImage( ps ); // 画像検査&周囲CLR
if( sti < 0 ){ // 不正が有れば
return( sti ); // Statusを返す
} //
return( measureBase_fere( c, ps, buf, lmt ) ); // フェレ計測処理部
}
(1)関数名
「Measure」は、「計測」でココでは、計測を意味
「Fere」は、「フェレ計測」を意味
だから、「MeasureFere」でフェレ計測を実際に実行する
を意味します!
(2)仮引数
int Filter::MeasureFere(
int c, // 4/8連結
TypeArray *ps, // 画像
TypeSf buf[], // 計測結果Buffer
int lmt // Buffer格納制限
){
「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「TypeArray* ps,」は、計測対象の2値化画像、
「TypeSf buf[],」は、計測結果バッファーで型「TypeSf」
は解説『解説クラスTypeSf』を参考にして下さい!
「int lmt」は、バッファーサイズ≪lmt名称は、格納制限
とし、この制限値まで計測し、実際に図形がオーバーする
場合は、計測を打ち切ります!≫
※備考※オーバーロード(多重定義)関数として仮引数の
数と型が異なる関数が存在します!
(3)ローカル変数数
){
int sti; // ステータス情報
「int sti;」は、ステータス情報(エラーコード)
(4)アルゴリズム
sti = CheckAndClearRoundImage( ps ); // 画像検査&周囲CLR
if( sti < 0 ){ // 不正が有れば
return( sti ); // Statusを返す
} //
return( measureBase_fere( c, ps, buf, lmt ) ); // フェレ計測処理部
}
「sti=CheckAndClearRoundImage(ps);」は、画像「ps」の
検査≪規定通り1バイトの2値化画像のサイズを満足して居
るか如何か≫し、合格ならば、画像の外周一回りクリアする
※備考※外周一回りクリアするので必要な画素が有る場合は
部分画像をコピーする等、工夫して使用して下さい!
「if(sti<0){return(sti);}」は、検査でエラー発生時は、
エラーコードを関数辺値とし返し終了!
「return(measureBase_fere(c,ps,buf,lmt));」は、
下請け関数「measureBase_fere(c,ps,buf,lmt)」で
フェレ計測の基本的な処理を行い、その関数辺値を返し終了
※備考※
この、MeasureFere()関数の方が、C言語から使用する場合は
便利な筈です!
7.計測用画像情報の検査と画像の周囲1周のクリア
CheckAndClearRoundImage()
/************************************************************************/
/***** 図形の計測用画像情報の検査と画像の周囲1周のクリア *****/
/************************************************************************/
int Filter::CheckAndClearRoundImage(
TypeArray *ps // 画像
){
int sti; // ステータス情報
sti = CheckImageMeasure( ps ); // 画像を検査し
if( sti < 0 ){ // 不正が有れば
return( sti ); // Statusを返す
} //
ClearRoundImage( ps, 0, 1 ); // 1周を0でクリア
return( END_STI ); // 正常終了
}
(1)関数名
「Check」は、「検査」でココでは、画像情報の検査を意味
「And」は、「接続詞and」を意味
「Clear」は、クリアと画像の画素を消去
「Round」は、周囲を意味
「Image」は、画像で「ClearRoundImage」で周囲1周を
消去を意味
(2)仮引数
int Filter::CheckAndClearRoundImage(
TypeArray *ps // 画像
){
「TypeArray* ps,」は、計測対象の2値化画像、
(3)ローカル変数数
){
int sti; // ステータス情報
「int sti;」は、ステータス情報(エラーコード)
(4)アルゴリズム
sti = CheckImageMeasure( ps ); // 画像を検査し
if( sti < 0 ){ // 不正が有れば
return( sti ); // Statusを返す
} //
ClearRoundImage( ps, 0, 1 ); // 1周を0でクリア
return( END_STI ); // 正常終了
}
「sti=CheckImageMeasure(ps);」は、検査関数で
解説『解説クラスCopyClear(6)』の
(4-10-11)で関数「int CheckImageMeasure(
TypeArray* pa);」で下請け関数「CheckImageMeasure()」は
説明しています!
「if(sti<0){return(sti);}」は、エラー発生の場合は、
関数辺値としエラーコードを返し終了
「ClearRoundImage(ps,0,1);」は、
下請け関数「ClearRoundImage()」で周囲クリア
解説『解説クラスCopyClear(7)』の
(4-11-21)で関数「int ClearRoundImage(
TypeArray* pa,int data,int n);」で下請け
関数「ClearRoundImage()」は説明しています!
「return(END_STI);」は、正常終了を返し終了!
8.フェレ計測:処理部measureBase_fere()
/************************************************************************/
/***** 図形のフェレ計測:処理部 *****/
/***** MEASURE_FERE(c,s,x,y,h,v,xl) *****/
/***** ※注:結果が buf_lmt個までは、バッファーに格納しますがそれ *****/
/***** 以上ある場合は、バッファーの buf_lmt + 1 個目を更新す *****/
/***** るのみです。 *****/
/************************************************************************/
int Filter::measureBase_fere(
int c, // 4/8連結
TypeArray *ps, // 画像
TypeSf *buf, // 計測結果Buffer
int buf_lmt // Buffer格納制限
){
char **bufptr; // 追跡点履歴Buffer
int dir_off[ 8 ]; // 方向OffSetTable
char *px; // x方向処理Ptr
char *py; // y方向処理Ptr
int h; // 処理水平幅
int v; // 処理垂直幅
int inc; // 処理インクリ幅
int x; // x座標カウンタ
int y; // y座標カウンタ
int n; // 計測個数
int size; // 履歴Bufferサイズ
size = BORDERSIZE; // 履歴BufferSize初期値
bufptr = (char**)malloc( sizeof(char*) * size ); // 履歴Buffer取得
if( bufptr == 0 ){ // 失敗時は
return( STI_MEM ); // 左記を返し終了
} //
py = (char*)ps->adr; // 処理ADRを取出し
h = ps->h - 2; // 水平幅-2を算出
v = ps->v - 2; // 垂直幅-2を算出
inc = ps->inc; // 処理Inc幅取出
py += inc + 1; // 座標(1,1)にセット
SetDirOffset( c, dir_off, inc ); // 方向OffSetTblSet
n = 0; // 個数初期化
for( y = 1; y <= v; y++, py += inc ){ // 垂直処理幅分繰返
px = py; // 水平処理始点Setし
for( x = 1; x <= h; x++, px++ ){ // 水平方向繰り返し
if( *px > 0 ){ // 画素を発見したら
if( c == 4 ){ // 4連結なら
bufptr = search4fere( bufptr, px, x, y, // 個別のフェレ計測
buf, dir_off, -1, size ); //
}else{ // 8連結なら
bufptr = search8fere( bufptr, px, x, y, // 個別のフェレ計測
buf, dir_off, -1, size ); //
} //
if( bufptr == 0 ){ // 上記でメモリ確保失敗時は
return( STI_MEM ); // 左記を返し終了
} //
n++; // 個数を更新
if( n <= buf_lmt ){ // buf_lmt以下なら
buf++; // 結果バッファ更新
}else{ // Overなら
free( bufptr ); // 履歴Buffer解放し
return( n ); // 個数を返す
} //
} //
} //
} //
free( bufptr ); // 履歴Buffer解放
return( n ); // 個数を返す
}
(1)関数名
「measure」は、「計測」でココでは、計測を意味
「Base」は、「基本部」を意味
「Fere」は、「フェレ計測」を意味
だから、「measureBase_Fere」でフェレ計測を実際に実行
する基本部を意味します!
(2)仮引数
int Filter::measureBase_fere(
int c, // 4/8連結
TypeArray *ps, // 画像
TypeSf *buf, // 計測結果Buffer
int buf_lmt // Buffer格納制限
){
「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「TypeArray* ps,」は、計測対象の2値化画像、
「TypeSf buf[],」は、計測結果バッファーで型「TypeSf」
は解説『解説クラスTypeSf』を参考にして下さい!
「int buf_lmt」は、バッファーサイズ≪lmt名称は、格納
制限とし、この制限値まで計測し、実際に図形がオーバー
する場合は、計測を打ち切ります!≫
※備考※オーバーロード(多重定義)関数として仮引数の
数と型が異なる関数が存在します!
(3)ローカル変数
){
char **bufptr; // 追跡点履歴Buffer
int dir_off[ 8 ]; // 方向OffSetTable
char *px; // x方向処理Ptr
char *py; // y方向処理Ptr
int h; // 処理水平幅
int v; // 処理垂直幅
int inc; // 処理インクリ幅
int x; // x座標カウンタ
int y; // y座標カウンタ
int n; // 計測個数
int size; // 履歴Bufferサイズ
「char** bufptr;」は、追跡点履歴バッファー≪輪郭サーチ
を行った画素の場所「char*」型でポイントをバッファーに
格納する為のバッファー≫
「int dir_off[8];」は、方向オフセットテーブル≪輪郭
サーチ用の次の画素ポインタへのオフセットを格納したテー
ブル≫
「char* px;」は、X座標方向画像画素ポインタ≪ラスター
スキャン用≫
「char* py;」は、Y座標方向画像画素ポインタ≪ラスター
スキャン用≫
「int h;」は、水平幅≪画像の水平幅より、外周一回りを
クリアして居るので内側の水平幅≫
「int v;」は、垂直幅≪画像の垂直幅より、外周一回りを
クリアして居るので内側の垂直幅≫
「int inc;」は、画像の増加幅≪画像の垂直方向への進行用
≫
「int x;」は、X座標≪画像を直交XY座標として≫
「int y;」は、Y標≪画像を直交XY座標として≫
「int n;」は、計測個数
「int size;」は、追跡点履歴バッファーのサイズ
(4)関連定義
#define BORDERSIZE 100000 // 輪郭バッファーのサイズ
「BORDERSIZE」は、「100000」を意味します!
(5)アルゴリズム
size = BORDERSIZE; // 履歴BufferSize初期値
bufptr = (char**)malloc( sizeof(char*) * size ); // 履歴Buffer取得
if( bufptr == 0 ){ // 失敗時は
return( STI_MEM ); // 左記を返し終了
} //
py = (char*)ps->adr; // 処理ADRを取出し
h = ps->h - 2; // 水平幅-2を算出
v = ps->v - 2; // 垂直幅-2を算出
inc = ps->inc; // 処理Inc幅取出
py += inc + 1; // 座標(1,1)にセット
SetDirOffset( c, dir_off, inc ); // 方向OffSetTblSet
n = 0; // 個数初期化
for( y = 1; y <= v; y++, py += inc ){ // 垂直処理幅分繰返
px = py; // 水平処理始点Setし
for( x = 1; x <= h; x++, px++ ){ // 水平方向繰り返し
if( *px > 0 ){ // 画素を発見したら
if( c == 4 ){ // 4連結なら
bufptr = search4fere( bufptr, px, x, y, // 個別のフェレ計測
buf, dir_off, -1, size ); //
}else{ // 8連結なら
bufptr = search8fere( bufptr, px, x, y, // 個別のフェレ計測
buf, dir_off, -1, size ); //
} //
if( bufptr == 0 ){ // 上記でメモリ確保失敗時は
return( STI_MEM ); // 左記を返し終了
} //
n++; // 個数を更新
if( n <= buf_lmt ){ // buf_lmt以下なら
buf++; // 結果バッファ更新
}else{ // Overなら
free( bufptr ); // 履歴Buffer解放し
return( n ); // 個数を返す
} //
} //
} //
} //
free( bufptr ); // 履歴Buffer解放
return( n ); // 個数を返す
}
「size=BORDERSIZE;」は、輪郭サーチサイズの初期値セット
「bufptr=(char**)malloc(sizeof(char*)size);」は、輪郭
サーチして「char」と画像画素へのポインタをバッファー
に格納する為のバッファーを動的にメモリ確保
「if(bufptr==0){return(STI_MEM);}」は、メモリ確保に
失敗したらエラーコード「STI_MEM」を関数辺値とし返し
終了!
「py=(char*)ps->adr;」は、Y座標方向画像画素ポインタを
画像画素ポインタ始点(左上隅)にセット
「h=ps->h-2;v=ps->v-2;」は、画像「TypeArray* ps,」の
一回り内側の水平幅・垂直幅を「int h;int v;」にセット
「inc=ps->inc;」は、垂直方向増加幅をセット
「py+=inc+1;」は、Y座標方向画像画素ポインタをラスター
スキャンの始点≪一回り内側なのでXY座標(1,1)≫として
セット
「SetDirOffset(c,dir_off,inc);」は、方向オフセット
テーブルにオフセット値を作成する
「n=0;」は、図形の個数を初期化
「for(y=1;y<=v;y++,py+=inc){・・垂直方向・・}」は、
画像画素をラスタースキャンとして処理する垂直方向の
forループです、教科書的な「y=1;y<=v;y++,」とY座標を
「1・・v」まで繰り返し、ループ最後に「py+=inc」と
Y座標方向画像画素ポインタを垂直方向に進行し、
「・・垂直方向・・」と垂直方向の処理を行う、その処理は
「px=py;」でX座標方向画像画素ポインタをセット、
「for(x=1;x<=h;x++,px++){・・水平方向・・}」で
画像画素をラスタースキャンとして処理する水平方向の
forループです、教科書的な「x=1;x<=h;x++,」とX座標を
「1・・h」まで繰り返し、ループ最後に「px++」とX座標
方向画像画素ポインタを水平方向に進行し、
「if(*px>0){・・輪郭サーチ方向・・}」で条件「*px>0」で
有効な画素≪「0」を超える正の値≫の場合は、輪郭サーチ
方向に処理し、その処理の中で
「if(c==4){bufptr=search4fere(bufptr,px,x,y,buf,
dir_off,-1,size);}」で条件「c==4」詰まり、4連結時は、
下請け関数「bufptr=search4fere(bufptr,px,x,y,buf,
dir_off,-1,size);」と処理し、
「else{bufptr=search8fere(bufptr,px,x,y,buf,dir_off,
-1,size);}」で「else」と4連結以外≒8連結として下請け
関数「bufptr=search8fere(bufptr,px,x,y,buf,dir_off,-1,
size);}」で処理
「if(bufptr==0){return(STI_MEM);}」は、下請け関数「
search4fere()及び、search8fere()」内で輪郭サーチ用の
バッファーを大きなサイズに再メモリ確保≪一旦、新しい
バッファーを確保し、元のデータをコピーし、余裕がある
バッファーとし使用するが、メモリ確保に失敗した場合は、
空ポインタ(=0の値)で返るのでエラーと成る≫に失敗し
たら、らエラーコード「STI_MEM」を関数辺値とし返し終了
「n++;」は、図形≪連結した塊≫の計測が完了したので個数
を増加する!
「if(n<=buf_lmt){buf++;}」は、条件「n<=buf_lmt」で
図形計測バッファーのサイズの制限値を超えて無い場合を
示し「buf++;」格納する場所を示すポインタを進める
「else{free(bufptr);return(n);}」は、バッファーの
サイズの制限値を超えたので「free(bufptr);」で確保した
動的にメモリをOSに返し、「return(n);」で制限値を超え
たまでの個数を関数辺値とし返し終了
そして全てのループが終了すると
「free(bufptr);」は、確保した動的にメモリをOSに返し
「return(n);」は、計測した図形の個数を関数辺値とし返し
終了
9.方向オフセットテーブルの設定
SetDirOffset()
/************************************************************************/
/***** 図形のフェレ計測:処理部:方向オフセットテーブルの設定 *****/
/************************************************************************/
void Filter::SetDirOffset(
int c, // 4/8連結
int dir_off[], // 方向OffSetTable
int inc // 処理インクリ幅
){
if( c == 4 ){ // 4連結なら
dir_off[ 0 ] = 1; // 0:右方向
dir_off[ 1 ] = inc; // 1:下方向
dir_off[ 2 ] = -1; // 2:左方向
dir_off[ 3 ] = -inc; // 3:上方向
}else{ // 8連結なら
dir_off[ 0 ] = 1; // 0:右方向
dir_off[ 1 ] = 1 + inc; // 1:右下方向
dir_off[ 2 ] = inc; // 2:下方向
dir_off[ 3 ] = -1 + inc; // 3:左下方向
dir_off[ 4 ] = -1; // 4:左方向
dir_off[ 5 ] = -1 - inc; // 5:左上方向
dir_off[ 6 ] = -inc; // 6:上方向
dir_off[ 7 ] = 1 - inc; // 7:右上方向
} //
}
(1)関数名
「Set」は、セットするを意味し
「Dir」は、方向≪4連結「右・下・左・上」及び8連結「
右・右下・下・左下・左・左上・上・右上」≫を意味!
「Offset」は、オフセットを意味し、「DirOffset」で
輪郭サーチする時の次へ進行する為のオフセットを示し、
「SetDirOffset」でそのテーブルをセットする関数
(2)仮引数
void Filter::SetDirOffset(
int c, // 4/8連結
int dir_off[], // 方向OffSetTable
int inc // 処理インクリ幅
){
「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「int dir_off[8];」は、方向オフセットテーブル≪輪郭
サーチ用の次の画素ポインタへのオフセットを格納した
テーブル≫
「int inc」は、増加幅≪画像の垂直(上下)方向の増加幅
(3)アルゴリズム
){
if( c == 4 ){ // 4連結なら
dir_off[ 0 ] = 1; // 0:右方向
dir_off[ 1 ] = inc; // 1:下方向
dir_off[ 2 ] = -1; // 2:左方向
dir_off[ 3 ] = -inc; // 3:上方向
}else{ // 8連結なら
dir_off[ 0 ] = 1; // 0:右方向
dir_off[ 1 ] = 1 + inc; // 1:右下方向
dir_off[ 2 ] = inc; // 2:下方向
dir_off[ 3 ] = -1 + inc; // 3:左下方向
dir_off[ 4 ] = -1; // 4:左方向
dir_off[ 5 ] = -1 - inc; // 5:左上方向
dir_off[ 6 ] = -inc; // 6:上方向
dir_off[ 7 ] = 1 - inc; // 7:右上方向
} //
}
「if(c==4){・・4連結・・}else{・・8連結・・」は、
条件「c==4」で4連結の処理で
「dir_off[0]=1;dir_off[1]=inc;dir_off[2]=-1;
dir_off[3]=-inc;」で「dir_off[]」の「0,1,2,3」に
「右・下・左・上」のオフセットをセットする
「else」と8連結の処理で
「dir_off[0]=1;dir_off[1]=1+inc;dir_off[2]=inc;
dir_off[3]=-1+inc;dir_off[4]=-1;dir_off[5]=-1-inc;
dir_off[6]=-inc;dir_off[7]=1-inc;」で「dir_off[]」の
「0,1,2,3,4,5,6,7」に
「右・右下・下・左下・左・左上・上・右上」の
オフセットをセットする
10.ここの説明は、ここまでとします!
実際に輪郭サーチを実行する
4連結の処理は、「search4fere()」で
8連結の処理は、「search8fere()」と成りますが、
次の『この仕事は天職だと感じたアルゴリズム開発
(続2)』で説明します!