孤立点除去・収縮・膨脹
孤立点除去・収縮・膨脹
2024年11月3初稿
解説エッセイ『2値画像と4連結・8連結』で孤立点除去は
2値画像処理の典型的な例と図示して説明しましたが、良く
使われる処理として収縮・膨脹も図示して説明し、
孤立点除去・収縮・膨脹のソースコードも説明します!
1.孤立点除去
注視点に隣接する点≪上・左・下≫が有る(1)あれば、
変化無しだが、全て無い(0)の状態ならば、注視点が、
有る(1)でも消滅(0)に成る!
注視点に隣接する点≪上・左・右・下・左上・右上・左下・
右下≫が有る(1)あれば、変化無しだが、
全て無い(0)の状態ならば、注視点が、有る(1)でも
消滅(0)に成る!
細かい、点≪これが孤立点≫が有る2値化画像
孤立点除去した結果を示す?!ノイズ的な孤立点が除去され
ている事に注意!
1-1.孤立点除去ソースコード
code:孤立点除去ソースコード
/************************************************************************/
/***** 孤立点除去 :実行部:4連結:x方向*****/
/***** REM_ISOLATION,s,d,4 *****/
/************************************************************************/
void Filter::rem_isolation_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) || *( ps - inc ) // 左か上か
|| *( ps + 1 ) || *( ps + inc ) ){ // 右か下が有効なら
*pd = data; // ば、書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
//page
/************************************************************************/
/***** 孤立点除去 :実行部:4連結*****/
/***** REM_ISOLATION,s,d,4 *****/
/************************************************************************/
void Filter::rem_isolation_4(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
rem_isolation_4_x( ptrs, ptrd, incs, data, // 水平方向の処理
h ); //
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
//page
/************************************************************************/
/***** 孤立点除去 :実行部:8連結:x方向*****/
/***** REM_ISOLATION,s,d,8 *****/
/************************************************************************/
void Filter::rem_isolation_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
BYTE *p; // S画像Ptr
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) || *( ps + 1 ) ){ // 左右が有効なら
*pd = data; // 書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p || *(p+1) || *(p+2) ){ // 上側が有効なら
*pd = data; // 書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p || *(p+1) || *(p+2) ){ // 下側が有効なら
*pd = data; // 書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
//page
/************************************************************************/
/***** 孤立点除去 :実行部:8連結*****/
/***** REM_ISOLATION,s,d,8 *****/
/************************************************************************/
void Filter::rem_isolation_8(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
rem_isolation_8_x( ptrs, ptrd, incs, data, // 水平方向の処理
h ); //
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
//page
/************************************************************************/
/***** 孤立点除去 :実行部:基本部*****/
/***** REM_ISOLATION,s,d,c *****/
/************************************************************************/
int Filter::rem_isolation(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
int sti; // ステータス情報
sti = Clear( pd, 0 ); // D画像0クリア
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
s = *ps; // 一旦、S画像情報
ps = &s; // を局所化
d = *pd; // 一旦、D画像情報
pd = &d; // を局所化
sti = PreProcessor3By3( ps, pd ); // 前処理
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
if( c == 4 ){ // 4連結なら
rem_isolation_4( ps, pd, data ); // 左記で処理
}else{ // 8連結なら
rem_isolation_8( ps, pd, data ); // 左記で処理
} //
return( END_STI ); // 正常終了
}
//page
/************************************************************************/
/***** 孤立点除去 :実行部*****/
/***** REM_ISOLATION,s,d,c *****/
/************************************************************************/
int Filter::RemoveIsolation(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ(省略時255)
){
int sti; // ステータス情報
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
sti = rem_isolation( ps, pd, c, data ); // 基本部で処理
if( sti == END_STI ){ // 処理成功の場合
ClearRoundImage( pd, 0, 1 ); // 1周周囲クリア
} //
return( sti ); // ステータスを返す
}
(1)RemoveIsolation(仮引数){アルゴリズム}
code:RemoveIsolation(仮引数){
/************************************************************************/
/***** 孤立点除去 :実行部*****/
/***** REM_ISOLATION,s,d,c *****/
/************************************************************************/
int Filter::RemoveIsolation(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ(省略時255)
){
int sti; // ステータス情報
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
sti = rem_isolation( ps, pd, c, data ); // 基本部で処理
if( sti == END_STI ){ // 処理成功の場合
ClearRoundImage( pd, 0, 1 ); // 1周周囲クリア
} //
return( sti ); // ステータスを返す
}
(1-1)関数名
「Remove」は、取り除くとの意味です!
「Isolation」は、分離と言う動詞で品詞とし孤立を意味!
(1-2)仮引数
code:仮引数
int Filter::RemoveIsolation(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ(省略時255)
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int data)」は、結果書き込み画素の値です!
(1-3)ローカル変数
code:ローカル変数
){
int sti; // ステータス情報
「int sti;」は、関数のステータス情報(エラーコード)で
す!
(1-4)アルゴリズム
code:アルゴリズム
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
sti = rem_isolation( ps, pd, c, data ); // 基本部で処理
if( sti == END_STI ){ // 処理成功の場合
ClearRoundImage( pd, 0, 1 ); // 1周周囲クリア
} //
return( sti ); // ステータスを返す
}
「if(c!=4&&c!=8){return(STI_FLG);}」は、連結性が4でも
8でも無い場合はエラーとし「STI_FLG」を関数辺値とし返
し終了!
「sti=rem_isolation(ps,pd,c,data);」は、下請け関数「
rem_isolation(ps,pd,c,data);」で処理しステータスを一旦
格納、
「if(sti==END_STI){ClearRoundImage(pd,0,1);}」は、実行
成功ならば、「ClearRoundImage(pd,0,1);」で結果画像の
外周を0クリア
「return(sti);」は、ステータス(成功)を関数辺値とし
返し終了!
(2)rem_isolation(仮引数){アルゴリズム}
code:rem_isolation(仮引数){
/************************************************************************/
/***** 孤立点除去 :実行部:基本部*****/
/***** REM_ISOLATION,s,d,c *****/
/************************************************************************/
int Filter::rem_isolation(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
int sti; // ステータス情報
sti = Clear( pd, 0 ); // D画像0クリア
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
s = *ps; // 一旦、S画像情報
ps = &s; // を局所化
d = *pd; // 一旦、D画像情報
pd = &d; // を局所化
sti = PreProcessor3By3( ps, pd ); // 前処理
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
if( c == 4 ){ // 4連結なら
rem_isolation_4( ps, pd, data ); // 左記で処理
}else{ // 8連結なら
rem_isolation_8( ps, pd, data ); // 左記で処理
} //
return( END_STI ); // 正常終了
}
(2-1)関数名
「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
(2-2)仮引数
code:仮引数
int Filter::rem_isolation(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int data)」は、結果書き込み画素の値です!
(2-3)ローカル変数
code:ローカル変数
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
int sti; // ステータス情報
「TypeArray s;」は、元画像情報のローカル変数です!
「TypeArray d;」は、結果画像情報のローカル変数です!
「int sti;」は、関数のステータス情報(エラーコード)で
す!
(2-4)アルゴリズム
code:アルゴリズム
sti = Clear( pd, 0 ); // D画像0クリア
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
s = *ps; // 一旦、S画像情報
ps = &s; // を局所化
d = *pd; // 一旦、D画像情報
pd = &d; // を局所化
sti = PreProcessor3By3( ps, pd ); // 前処理
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
if( c == 4 ){ // 4連結なら
rem_isolation_4( ps, pd, data ); // 左記で処理
}else{ // 8連結なら
rem_isolation_8( ps, pd, data ); // 左記で処理
} //
return( END_STI ); // 正常終了
}
「sti=Clear(pd,0);if(sti!=END_STI){return(sti);」は、
結果画像を0クリア!エラーが有れば終了!
「s=*ps;ps=&s;d=*pd;pd=&d;」は、画像情報をローカル変数
にセット※備考:元の情報を弄るので影響が無い様にする為
「sti=PreProcessor3By3(ps,pd);if(sti!=END_STI){
return(sti);}」は、2値画像変換用の前処理として「
S・D画像情報をS・D画像情報の最小幅に補正&検査」を
行う!
「if(c==4){rem_isolation_4(ps,pd,data);}」は、4連結時
でサブルーチン関数「rem_isolation_4(ps,pd,data);」で
処理!
「}else{if(c==8){rem_isolation_4(ps,pd,data);}」は、
8連結時でサブルーチン関数「
rem_isolation_8(ps,pd,data);」で処理
「return(END_STI);」は、正常終了を関数辺値とし返す!
(3)rem_isolation_4(仮引数){アルゴリズム}
code:rem_isolation_4(仮引数){
/************************************************************************/
/***** 孤立点除去 :実行部:4連結*****/
/***** REM_ISOLATION,s,d,4 *****/
/************************************************************************/
void Filter::rem_isolation_4(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
rem_isolation_4_x( ptrs, ptrd, incs, data, // 水平方向の処理
h ); //
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
(3-1)関数名
「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_4」は、4連結の処理を意味!
(3-2)仮引数
code:仮引数
void Filter::rem_isolation_4(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int data // 描画データ
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int data)」は、結果書き込み画素の値です!
(3-3)ローカル変数
code:ローカル変数
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅
(3-4)アルゴリズム
code:アルゴリズム
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
rem_isolation_4_x( ptrs, ptrd, incs, data, // 水平方向の処理
h ); //
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「rem_isolation_4_x(ptrs,ptrd,incs,data,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加
(4)rem_isolation_4_x(仮引数){アルゴリズム}
code:rem_isolation_4_x(仮引数){
/************************************************************************/
/***** 孤立点除去 :実行部:4連結:x方向*****/
/***** REM_ISOLATION,s,d,4 *****/
/************************************************************************/
void Filter::rem_isolation_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) || *( ps - inc ) // 左か上か
|| *( ps + 1 ) || *( ps + inc ) ){ // 右か下が有効なら
*pd = data; // ば、書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
(4-1)関数名
「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_4」は、4連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!
(4-2)仮引数
code:仮引数
void Filter::rem_isolation_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!
(4-3)アルゴリズム
code:アルゴリズム
){
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) || *( ps - inc ) // 左か上か
|| *( ps + 1 ) || *( ps + inc ) ){ // 右か下が有効なら
*pd = data; // ば、書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps){・・分岐中身・・}」は、「if(ps){」で元画像
が条件「(≠0)」で分岐中身を処理と「ps++;pd++;」で
元画像・結果画像のポインタを水平方向に進める!つまり、
水平方向の処理として繰り返し、条件有効な場合で分岐中身
を処理します?!そして分岐中身は、
「if((ps-1)||(ps-inc)||(ps+1)||(ps+inc)){
*pd=data;}」で条件として「元画像画素ポインタから相対的
に4連結で隣接(左・上・右・下)の何れかが有効(≠0)
ならば」、「*pd=data;」と結果画像画素に結果書き込み
画素の値をセットします!
(5)rem_isolation_8(仮引数){アルゴリズム}
code:rem_isolation_8(仮引数){
/************************************************************************/
/***** 孤立点除去 :実行部:8連結*****/
/***** REM_ISOLATION,s,d,8 *****/
/************************************************************************/
void Filter::rem_isolation_8(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
rem_isolation_8_x( ptrs, ptrd, incs, data, // 水平方向の処理
h ); //
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
(5-1)関数名
「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_8」は、8連結の処理を意味!
(5-2)仮引数
code:仮引数
void Filter::rem_isolation_8(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int data // 描画データ
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int data)」は、結果書き込み画素の値です!
(5-3)ローカル変数
code:ローカル変数
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅
(5-4)アルゴリズム
code:アルゴリズム
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
rem_isolation_8_x( ptrs, ptrd, incs, data, // 水平方向の処理
h ); //
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「rem_isolation_8_x(ptrs,ptrd,incs,data,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加
(6)rem_isolation_8_x(仮引数){アルゴリズム}
code:rem_isolation_8_x(仮引数){
/************************************************************************/
/***** 孤立点除去 :実行部:8連結:x方向*****/
/***** REM_ISOLATION,s,d,8 *****/
/************************************************************************/
void Filter::rem_isolation_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
BYTE *p; // S画像Ptr
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) || *( ps + 1 ) ){ // 左右が有効なら
*pd = data; // 書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p || *(p+1) || *(p+2) ){ // 上側が有効なら
*pd = data; // 書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p || *(p+1) || *(p+2) ){ // 下側が有効なら
*pd = data; // 書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
(6-1)関数名
「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_8」は、8連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!
(6-2)仮引数
code:仮引数
void Filter::rem_isolation_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!
(6-3)ローカル変数
code:ローカル変数
){
BYTE *p; // S画像Ptr
「BYTE *p;」は、元画像画素から左上・左下位置を使用する
為のポインタ
(6-4)アルゴリズム
code:アルゴリズム
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) || *( ps + 1 ) ){ // 左右が有効なら
*pd = data; // 書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p || *(p+1) || *(p+2) ){ // 上側が有効なら
*pd = data; // 書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p || *(p+1) || *(p+2) ){ // 下側が有効なら
*pd = data; // 書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps){・・分岐中身・・}」は、「if(ps){」で元画像
が条件「(≠0)」で分岐中身を処理と「ps++;pd++;」で
元画像・結果画像のポインタを水平方向に進める!つまり、
水平方向の処理として繰り返し、条件有効な場合で分岐中身
を処理します?!そして分岐中身は、
「if((ps-1)||(ps+1)){*pd=data;}」で条件として
「元画像画素ポインタから相対的に左右隣接」ならば、
「pd=data;」と結果画像画素に結果書き込み
画素の値をセットします!
しして「}else{・・非条件分岐・・}」で左右隣接が無かっ
た時の非条件分岐ブロックで
「p=ps-inc-1;」と左上ポインタをセットし、
「if(p||(p+1)||(p+2)){*pd=data;}」で条件として
「元画像画素ポインタから相対的に左上・右上隣接」ならば
「pd=data;」と結果画像画素に結果書き込み、
「}else{」でその条件ではずれ場合、
「p=ps+inc-1;」と左下ポインタをセットし、
「if(p||(p+1)||(p+2)){*pd=data;}」で条件として
「元画像画素ポインタから相対的に左下・右下隣接」ならば
「*pd=data;」と結果画像画素に結果書き込む!
2.収縮
注視点に隣接する点≪上・左・下≫が全部有る(1)なれ
ば、変化無しだが、一つでも無い(0)状態ならば、
注視点が、消滅(0)に成る!
注視点に隣接する点≪上・左・下・左上・右上・左下・
右下≫が全部有る(1)なれば、変化無しだが、一つでも無
注視点が、消滅(0)に成る!
収縮を行う前の2値化画像
収縮した結果を示す?!一回り細く成ったり、消えた事に
注意!
2-1.収縮ソースコード
code:収縮ソースコード
/************************************************************************/
/***** 収縮 :実行部:4連結:x方向*****/
/***** COMPACTION,s,d,4,r *****/
/************************************************************************/
void Filter::compaction_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int h // 水平幅
){
BYTE zero; // 0データ
zero = 0; // 0データセット
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - inc ) == 0 // 上か
|| *( ps - 1 ) == 0 // 左か
|| *( ps + 1 ) == 0 // 右か
|| *( ps + inc ) == 0 ){ // 下が0ならば
*pd = zero; // 0を書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
//page
/************************************************************************/
/***** 収縮 :実行部:4連結*****/
/***** COMPACTION,s,d,4,r *****/
/************************************************************************/
void Filter::compaction_4(
TypeArray *ps, // S画像Ptr
TypeArray *pd // D画像情報
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
compaction_4_x( ptrs, ptrd, incs, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
//page
/************************************************************************/
/***** 収縮 :実行部:8連結:x方向*****/
/***** COMPACTION,s,d,8,r *****/
/************************************************************************/
void Filter::compaction_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int h // 水平幅
){
BYTE *p; // S画像Ptr
BYTE zero; // 0データ
zero = 0; // 0データセット
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) == 0 // 左右に0が
|| *( ps + 1 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p == 0 || *( p + 1 ) == 0 // 上側に0が
|| *( p + 2 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p == 0 || *( p + 1 ) == 0 // 下側に0が
|| *( p + 2 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
//page
/************************************************************************/
/***** 収縮 :実行部:8連結*****/
/***** COMPACTION,s,d,8,r *****/
/************************************************************************/
void Filter::compaction_8(
TypeArray *ps, // S画像Ptr
TypeArray *pd // D画像情報
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
compaction_8_x( ptrs, ptrd, incs, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
//page
/************************************************************************/
/***** 収縮 :実行部:基本部:1回専用 *****/
/***** COMPACTION,s,d,c,1 *****/
/************************************************************************/
int Filter::compactionSingle(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c // 連結性
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
Copy( ps, pd ); // 予め、S→D実行
if( c == 4 ){ // 4連結なら
compaction_4( ps, pd ); // 左記で処理
}else{ // 8連結なら
compaction_8( ps, pd ); // 左記で処理
} //
ClearRoundImage( &d, 0, 1 ); // 1周周囲クリア:D:全体
return( END_STI ); // 正常終了
}
//page
/************************************************************************/
/***** 収縮 :実行部:複数回(2回以上)*****/
/***** COMPACTION,s,d,c,r *****/
/************************************************************************/
int Filter::compaction(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r // 繰返回数(2以上)
){
TypeArray *pt; // T画像情報ptr
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray t; // T画像情報:局所:ここでメモリ確保
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
TypeArray t1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
int i; // カウンタ
int sti; // ステータス情報
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
sti = t.MallocByte( h, v ); // 有効画像メモリ確保
if( sti != END_STI ){ // エラー時
return( sti ); // ステータスを返す
} //
pt = &t1; // 一旦、ptrセット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
pt->subset( &t, 1, 1, h - 2, v - 2 ); // T画像情報ptr:内側
Copy( &s, &d ); // 予め、S→D実行:全体
Copy( &s, &t ); // 予め、S→T実行:全体
if( ( r & 0x01 ) != 0 ){ // 奇数回処理なら
if( c == 4 ){ // 4連結なら
compaction_4( pt, pd ); // 左記処理:T→D
}else{ // 8連結なら
compaction_8( pt, pd ); // 左記処理:T→D
} //
Copy( pd, pt ); // 処理結果→T
r--; // 処理回数をダウン→偶数回
} //
ClearRoundImage( &d, 0, 1 ); // 1周周囲クリア:D:全体
ClearRoundImage( &t, 0, 1 ); // 1周周囲クリア:T:全体
r /= 2; // 2回を一組として組数算出
for( i = 1; i <= r; i++ ){ // 組数分以下繰返す
if( c == 4 ){ // 4連結なら
compaction_4( pd, pt ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
compaction_4( pt, pd ); // 左記処理:T→D
}else{ // 8連結なら
compaction_8( pd, pt ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
compaction_8( pt, pd ); // 左記処理:T→D
} //
if( i < r ){ // 次の回も有る場合
Copy( pd, pt ); // 処理結果→T
} //
} //
t.freeMem(); // T画像メモリ解放
return( END_STI ); // 正常終了
}
//page
/************************************************************************/
/***** 収縮 :実行部*****/
/***** COMPACTION,s,d,c,r *****/
/************************************************************************/
int Filter::Compaction(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r // 繰り返し回数(省略時1)
){
if( ps->w != 1 || pd->w != 1 ){ // 画素単位=1バイト
return( STI_ARY_5 ); // 以外→左記を返す
} //
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
if( r <= 0 ){ // 回数省略時は
r = 1; // 1をセット
} //
if( r == 1 ){ // 1回実行時は
return( compactionSingle( ps, pd, c ) ); // 左記で実行
}else{ // 複数回実行時は
return( compaction( ps, pd, c, r ) ); // 左記で処理
} //
}
(1)Compaction(仮引数){アルゴリズム}
code:Compaction(仮引数){
/************************************************************************/
/***** 収縮 :実行部*****/
/***** COMPACTION,s,d,c,r *****/
/************************************************************************/
int Filter::Compaction(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r // 繰り返し回数(省略時1)
){
if( ps->w != 1 || pd->w != 1 ){ // 画素単位=1バイト
return( STI_ARY_5 ); // 以外→左記を返す
} //
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
if( r <= 0 ){ // 回数省略時は
r = 1; // 1をセット
} //
if( r == 1 ){ // 1回実行時は
return( compactionSingle( ps, pd, c ) ); // 左記で実行
}else{ // 複数回実行時は
return( compaction( ps, pd, c, r ) ); // 左記で処理
} //
}
(1-1)関数名
「Compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
(1-2)仮引数
code:仮引数
int Filter::Compaction(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r // 繰り返し回数(省略時1)
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!
(1-3)アルゴリズム
code:アルゴリズム
){
if( ps->w != 1 || pd->w != 1 ){ // 画素単位=1バイト
return( STI_ARY_5 ); // 以外→左記を返す
} //
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
if( r <= 0 ){ // 回数省略時は
r = 1; // 1をセット
} //
if( r == 1 ){ // 1回実行時は
return( compactionSingle( ps, pd, c ) ); // 左記で実行
}else{ // 複数回実行時は
return( compaction( ps, pd, c, r ) ); // 左記で処理
} //
}
「if(ps->w!=1||pd->w!=1){return(STI_ARY_5);}」は、
元画像(S≒ソース)も結果画像(D≒ディスティネーショ
ン)も画素単位が1バイト以外ならエラー「STI_ARY_5」を
関数辺値とし返し終了!
「if(c!=4&&c!=8){return(STI_FLG);}」は、連結性が4でも
8でも無い場合はエラーとし「STI_FLG」を関数辺値とし返
し終了!
「if(r<=0){r=1;}」は、回数「r」が「0以下」ならば、
「1」にする!
「if(r==1){return(compactionSingle(ps,pd,c));}」は、
回数「r」が「1」ならば、下請け関数「
compactionSingle(ps,pd,c)」で処理し、その辺値を辺値と
し返す!
「else{return(compaction(ps,pd,c,r));}」は、回数「r」
が「1」を超える場合、下請け関数「
compaction(ps,pd,c,r)」で処理し、その辺値を辺値とし返
す!
(2)compaction(仮引数){アルゴリズム}
code:compaction(仮引数){
/************************************************************************/
/***** 収縮 :実行部:複数回(2回以上)*****/
/***** COMPACTION,s,d,c,r *****/
/************************************************************************/
int Filter::compaction(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r // 繰返回数(2以上)
){
TypeArray *pt; // T画像情報ptr
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray t; // T画像情報:局所:ここでメモリ確保
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
TypeArray t1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
int i; // カウンタ
int sti; // ステータス情報
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
sti = t.MallocByte( h, v ); // 有効画像メモリ確保
if( sti != END_STI ){ // エラー時
return( sti ); // ステータスを返す
} //
pt = &t1; // 一旦、ptrセット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
pt->subset( &t, 1, 1, h - 2, v - 2 ); // T画像情報ptr:内側
Copy( &s, &d ); // 予め、S→D実行:全体
Copy( &s, &t ); // 予め、S→T実行:全体
if( ( r & 0x01 ) != 0 ){ // 奇数回処理なら
if( c == 4 ){ // 4連結なら
compaction_4( pt, pd ); // 左記処理:T→D
}else{ // 8連結なら
compaction_8( pt, pd ); // 左記処理:T→D
} //
Copy( pd, pt ); // 処理結果→T
r--; // 処理回数をダウン→偶数回
} //
ClearRoundImage( &d, 0, 1 ); // 1周周囲クリア:D:全体
ClearRoundImage( &t, 0, 1 ); // 1周周囲クリア:T:全体
r /= 2; // 2回を一組として組数算出
for( i = 1; i <= r; i++ ){ // 組数分以下繰返す
if( c == 4 ){ // 4連結なら
compaction_4( pd, pt ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
compaction_4( pt, pd ); // 左記処理:T→D
}else{ // 8連結なら
compaction_8( pd, pt ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
compaction_8( pt, pd ); // 左記処理:T→D
} //
if( i < r ){ // 次の回も有る場合
Copy( pd, pt ); // 処理結果→T
} //
} //
t.freeMem(); // T画像メモリ解放
return( END_STI ); // 正常終了
}
(2-1)関数名
「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
備考※「compaction」と「Compaction」で識別して居る事
に注意!
(2-2)仮引数
code:仮引数
int Filter::compaction(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r // 繰返回数(2以上)
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!
(2-3)ローカル変数
code:ローカル変数
){
TypeArray *pt; // T画像情報ptr
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray t; // T画像情報:局所:ここでメモリ確保
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
TypeArray t1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
int i; // カウンタ
int sti; // ステータス情報
「TypeArray* pt;」は、T画像≪テンポラリ画像と
一時的な使用領域≫情報へのポインタ!
「TypeArray s;」は、S画像(元画像)の変更用局所変数
「TypeArray d;」は、D画像(結果画像)の変更用局所変数
「TypeArray t;」は、T画像(テンポラリ画像)を格納する
局所変数
「TypeArray s1;」は、S画像(元画像)の変更用局所変数
「TypeArray d1;」は、D画像(結果画像)の変更用局所
変数
「TypeArray t1;」は、T画像(テンポラリ画像)を格納
「int h;」は、水平幅
「int v;」は、垂直幅
「int i;」は、ループ用のカウンター
「int sti;」は、ステータス(エラーコード)情報
(2-4)アルゴリズム
code:アルゴリズム
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
sti = t.MallocByte( h, v ); // 有効画像メモリ確保
if( sti != END_STI ){ // エラー時
return( sti ); // ステータスを返す
} //
pt = &t1; // 一旦、ptrセット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
pt->subset( &t, 1, 1, h - 2, v - 2 ); // T画像情報ptr:内側
Copy( &s, &d ); // 予め、S→D実行:全体
Copy( &s, &t ); // 予め、S→T実行:全体
if( ( r & 0x01 ) != 0 ){ // 奇数回処理なら
if( c == 4 ){ // 4連結なら
compaction_4( pt, pd ); // 左記処理:T→D
}else{ // 8連結なら
compaction_8( pt, pd ); // 左記処理:T→D
} //
Copy( pd, pt ); // 処理結果→T
r--; // 処理回数をダウン→偶数回
} //
ClearRoundImage( &d, 0, 1 ); // 1周周囲クリア:D:全体
ClearRoundImage( &t, 0, 1 ); // 1周周囲クリア:T:全体
r /= 2; // 2回を一組として組数算出
for( i = 1; i <= r; i++ ){ // 組数分以下繰返す
if( c == 4 ){ // 4連結なら
compaction_4( pd, pt ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
compaction_4( pt, pd ); // 左記処理:T→D
}else{ // 8連結なら
compaction_8( pd, pt ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
compaction_8( pt, pd ); // 左記処理:T→D
} //
if( i < r ){ // 次の回も有る場合
Copy( pd, pt ); // 処理結果→T
} //
} //
t.freeMem(); // T画像メモリ解放
return( END_STI ); // 正常終了
}
「h=(ps->h<=pd->h)?ps->h:pd->h;」は、水平幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「v=(ps->v<=pd->v)?ps->v:pd->v;」は、垂直幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「if(h<3){return(STI_ARY_2);}」は、水平幅が3未満なら
エラーコード「STI_ARY_2」を関数辺値とし返し終了!
「if(v<3){return(STI_ARY_3);}」は、垂直幅が3未満なら
エラーコード「STI_ARY_3」を関数辺値とし返し終了!
「s.subset(ps,0,0,h,v);d.subset(pd,0,0,h,v);」は、
ローカル変数として元画像・結果画像のサイズを調整!
「sti=t.MallocByte(h,v);」は、T画像をメモリ確保!
「if(sti!=END_STI){return(sti);}」は、メモリ確保が
失敗したらエラーコードを関数辺値とし返し終了!
「pt=&t1;ps=&s1;pd=&d1;」は、T画像・S画像・D画像の
ポインタをセット!
「ps->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pd->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pt->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「Copy(&s,&d);Copy(&s,&t);」は、S(元)画像を
D(結果)画像とT画像にコピー
「if((r&0x01)!=0){・・条件成立・・}」は、
条件「(r&0x01)!=0」で回数「r」が奇数回の場合で成立が
「if(c==4){compaction_4(pt,pd);}」で4連結ならば、
下請け関数「compaction_4(pt,pd);」で処理!
「}else{compaction_8(pt,pd);}」で84連結ならば、
下請け関数「compaction_8(pt,pd);」で処理!
そして「Copy(pd,pt);」結果画像を一旦、T画像にコピー
「r--;」で回数「r」を1回処理したと減らす!
「ClearRoundImage(&d,0,1);」は、結果画像の外周一回り
クリア!
「ClearRoundImage(&t,0,1);」は、T画像の外周一回り
クリア!
「r/=2;」は、回数「r」を半分にする≪処理一組として「
結果画像⇒T画像とT画像⇒結果画像」とするのでコノ回数
にする≫!
「for(i=1;i<=r;i++){・・ループ中身・・}」は、お馴染み
教科書的な繰り返しで回数「r」繰り返す!
そしてループ中身は、
「if(c==4){・4連結処理・}else{・8連結処理・}」で
4連結処理は、
「compaction_4(pd,pt);Copy(pt,pd);
compaction_4(pt,pd);」で「結果画像⇒T画像」しT画像
を結果画像にコピーし、「T画像⇒結果画像」を実行!
8連結処理は、
「compaction_8(pd,pt);Copy(pt,pd);
compaction_8(pt,pd);」で「結果画像⇒T画像」しT画像
を結果画像にコピーし、「T画像⇒結果画像」を実行!
「if(i<r){Copy(pd,pt);}」は、次の回も存在する場合は、
結果画像をT画像にコピーする!
「t.freeMem();」は、「t.MallocByte(h,v);」でメモリ
確保したメモリを後始末!
「return(END_STI);」は、正常終了を関数辺値とし返し終了
(3)compactionSingle(仮引数){アルゴリズム}
code:compactionSingle(仮引数){
/************************************************************************/
/***** 収縮 :実行部:基本部:1回専用 *****/
/***** COMPACTION,s,d,c,1 *****/
/************************************************************************/
int Filter::compactionSingle(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c // 連結性
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
Copy( ps, pd ); // 予め、S→D実行
if( c == 4 ){ // 4連結なら
compaction_4( ps, pd ); // 左記で処理
}else{ // 8連結なら
compaction_8( ps, pd ); // 左記で処理
} //
ClearRoundImage( &d, 0, 1 ); // 1周周囲クリア:D:全体
return( END_STI ); // 正常終了
}
(3-1)関数名
「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「Single」は、シングル、繰り返すで無くシンプルに1回
だけ処理!
(3-2)仮引数
code:仮引数
int Filter::compactionSingle(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c // 連結性
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を
示す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティ
ネーション画像)情報を示す「TypeArray」型の情報への
ポインタ変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
(3-3)ローカル変数
code:ローカル変数
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
「TypeArray s;」は、S画像(元画像)の変更用局所
変数「TypeArray d;」は、D画像(結果画像)の変更用
局所変数
「TypeArray s1;」は、S画像(元画像)の変更用局所変数
「TypeArray d1;」は、D画像(結果画像)の変更用局所変数
「int h;」は、水平幅
「int v;」は、垂直幅
「int i;」は、ループ用のカウンター
(3-4)アルゴリズム
code:アルゴリズム
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
Copy( ps, pd ); // 予め、S→D実行
if( c == 4 ){ // 4連結なら
compaction_4( ps, pd ); // 左記で処理
}else{ // 8連結なら
compaction_8( ps, pd ); // 左記で処理
} //
ClearRoundImage( &d, 0, 1 ); // 1周周囲クリア:D:全体
return( END_STI ); // 正常終了
}
「h=(ps->h<=pd->h)?ps->h:pd->h;」は、水平幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「v=(ps->v<=pd->v)?ps->v:pd->v;」は、垂直幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「if(h<3){return(STI_ARY_2);}」は、水平幅が3未満なら
エラーコード「STI_ARY_2」を関数辺値とし返し終了!
「if(v<3){return(STI_ARY_3);}」は、垂直幅が3未満なら
エラーコード「STI_ARY_3」を関数辺値とし返し終了!
「s.subset(ps,0,0,h,v);d.subset(pd,0,0,h,v);」は、
有効な画像範囲に処理範囲を調整!
「ps=&s1;pd=&d1;」は、ポインタ変数を付け替え、
「ps->subset(&s,1,1,h-2,v-2);
pd->subset(&d,1,1,h-2,v-2);」は、部分画像とし一回り
内側を処理範囲にセット
「Copy(ps,pd);」は、予め、元画像を結果画像にコピー!
「if(c==4){・4連結処理・}else{・8連結処理・}」は、
連結性「c」で処理を分け4連結処理は、
「compaction_4(ps,pd);」で処理し、8連結処理は、
「compaction_8(ps,pd);」で処理!
「ClearRoundImage(&d,0,1);」は、外周一回り0クリア!
「return(END_STI);」は、正常終了を関数辺値とし返し終了
(4)compaction_4(仮引数){アルゴリズム}
code:compaction_4(仮引数){
/************************************************************************/
/***** 収縮 :実行部:4連結*****/
/***** COMPACTION,s,d,4,r *****/
/************************************************************************/
void Filter::compaction_4(
TypeArray *ps, // S画像Ptr
TypeArray *pd // D画像情報
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
compaction_4_x( ptrs, ptrd, incs, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
(4-1)関数名
「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_4」は、4連結の処理を意味!
(4-2)仮引数
code:仮引数
void Filter::compaction_4(
TypeArray *ps, // S画像Ptr
TypeArray *pd // D画像情報
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
(4-3)ローカル変数
code:ローカル変数
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅
(4-4)アルゴリズム
code:アルゴリズム
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
compaction_4_x( ptrs, ptrd, incs, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「compaction_4_x(ptrs,ptrd,incs,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加
(5)compaction_4_x(仮引数){アルゴリズム}
code:compaction_4_x(仮引数){
/************************************************************************/
/***** 収縮 :実行部:4連結:x方向*****/
/***** COMPACTION,s,d,4,r *****/
/************************************************************************/
void Filter::compaction_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int h // 水平幅
){
BYTE zero; // 0データ
zero = 0; // 0データセット
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - inc ) == 0 // 上か
|| *( ps - 1 ) == 0 // 左か
|| *( ps + 1 ) == 0 // 右か
|| *( ps + inc ) == 0 ){ // 下が0ならば
*pd = zero; // 0を書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
(5-1)関数名
「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_4」は、4連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!
(5-2)仮引数
code:仮引数
void Filter::compaction_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int h // 水平幅
){
「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!
(5-3)ローカル変数
code:ローカル変数
){
BYTE zero; // 0データ
「BYTE* zero;」は、高速化技法の為!
(5-4)アルゴリズム
code:アルゴリズム
zero = 0; // 0データセット
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - inc ) == 0 // 上か
|| *( ps - 1 ) == 0 // 左か
|| *( ps + 1 ) == 0 // 右か
|| *( ps + inc ) == 0 ){ // 下が0ならば
*pd = zero; // 0を書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
「zero=0;」は、0書き込み画素データセット※高速化技法
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps){・・分岐中身・・}」は、「if(ps){」で
元画像が画素が条件「ps」詰まり有効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
条件「(ps-inc)==0||(ps-1)==0||(ps+1)==0||
*(ps+inc)==0」で隣接する左・上・右・下の一つでも無効
なら、
「*pd=zero;」と結果画像画素に無効画素を書き込みセット
します!
(6)compaction_8(仮引数){アルゴリズム}
code:compaction_8(仮引数){
/************************************************************************/
/***** 収縮 :実行部:8連結*****/
/***** COMPACTION,s,d,8,r *****/
/************************************************************************/
void Filter::compaction_8(
TypeArray *ps, // S画像Ptr
TypeArray *pd // D画像情報
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
compaction_8_x( ptrs, ptrd, incs, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
(6-1)関数名
「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_8」は、8連結の処理を意味!
(6-2)仮引数
code:仮引数
void Filter::compaction_8(
TypeArray *ps, // S画像Ptr
TypeArray *pd // D画像情報
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
(6-3)ローカル変数
code:ローカル変数
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅
(6-4)アルゴリズム
code:アルゴリズム
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
compaction_8_x( ptrs, ptrd, incs, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
「h=ps->h;v=ps->v;」は、画像の水平幅・垂直幅を取り出
し!元画像・結果画像も同じ有効処理幅に補正されて居る
事が前提!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅を取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の下請け
関数「compaction_8_x(ptrs,ptrd,incs,h);」で水平方向
処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポインタ
の値をソレゾレの垂直幅分増加
(7)compaction_8_x(仮引数){アルゴリズム}
code:compaction_8_x(仮引数){
/************************************************************************/
/***** 収縮 :実行部:8連結:x方向*****/
/***** COMPACTION,s,d,8,r *****/
/************************************************************************/
void Filter::compaction_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int h // 水平幅
){
BYTE *p; // S画像Ptr
BYTE zero; // 0データ
zero = 0; // 0データセット
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) == 0 // 左右に0が
|| *( ps + 1 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p == 0 || *( p + 1 ) == 0 // 上側に0が
|| *( p + 2 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p == 0 || *( p + 1 ) == 0 // 下側に0が
|| *( p + 2 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
(7-1)関数名
「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_8」は、8連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!
(7-2)仮引数
code:仮引数
void Filter::compaction_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int h // 水平幅
){
「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int h」は、水平方向処理幅です!
(7-3)ローカル変数
code:ローカル変数
){
BYTE *p; // S画像Ptr
BYTE zero; // 0データ
「BYTE* p;」は、元画像画素への左上・左下等上下移動分の
ポインタ変数!
「BYTE zero;」は、高速化の為に「int型」で無く画素単位と
同じ「BYTE」を使用!多くのCPU&コンパイらでは大方、
高速化する筈!
(7-4)アルゴリズム
code:アルゴリズム
zero = 0; // 0データセット
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps ){ // 注視点有効時
if( *( ps - 1 ) == 0 // 左右に0が
|| *( ps + 1 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p == 0 || *( p + 1 ) == 0 // 上側に0が
|| *( p + 2 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p == 0 || *( p + 1 ) == 0 // 下側に0が
|| *( p + 2 ) == 0 ){ // あれば
*pd = zero; // 0を書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
「zero=0;」は、高速化の為に「0」の値をセット、初期化で
記述シナイのは、コンパイラに依って遅いコードが出る為!
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps ==0){・・分岐中身・・}」は、「if(ps ==0){」
で元画像が画素が条件「(=0)」詰まり無効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
「if((ps-1)==0||(ps+1)==0){pd=zero;}」で更に
条件「(ps-1)==0||*(ps+1)==0」と左右隣接画素が一つでも
無効「(=0)」なら、「pd=zero;」で「0」を書き込む、
そして条件が非成立「else{・・非成立処理」として
「p=ps-inc-1;」で左上ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左上・右上隣接
画素が一つでも無効「(=0)」なら、「pd=zero;」で
「0」を書き込む、それでも条件が非成立
「else{・・非成立処理」として「p=ps+inc-1;」で
左下ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;}」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左下・右下隣接
画素が一つでも無効「(=0)」なら、「*pd=zero;」で
「0」を書き込む!の値をソレゾレの垂直幅分増加セットします!
3.膨脹
注視点が(0)状態に隣接する点≪上・左・下≫が一つでも
有る(1)なれば、注視点が、存在(1)に成る!
注視点が(0)状態に隣接する点≪上・左・下・左上・右上
右下・左下・左・下上・左・下≫が一つでも有る(1)なれ
ば、注視点が、存在(1)に成る!
膨脹を行う前の2値化画像
膨脹した結果を示す?!一回り太く成った事に注意!
3-1.膨脹ソースコード
code:膨脹ソースコード
/************************************************************************/
/***** 膨脹 :実行部:4連結:x方向*****/
/***** EXPANSION,s,d,4,r *****/
/************************************************************************/
void Filter::expansion_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps == 0 ){ // 注視点画素=0時
if( *( ps - 1 ) || *( ps - inc ) // 左か上か
|| *( ps + 1 ) || *( ps + inc ) ){ // 右か下が有効なら
*pd = data; // ば、書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
//page
/************************************************************************/
/***** 膨脹 :実行部:4連結*****/
/***** EXPANSION,s,d,4,r *****/
/************************************************************************/
void Filter::expansion_4(
TypeArray *ps, // S画像Ptr
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
//page
/************************************************************************/
/***** 膨脹 :実行部:8連結:x方向*****/
/***** EXPANSION,s,d,8,r *****/
/************************************************************************/
void Filter::expansion_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
BYTE *p; // S画像Ptr
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps == 0 ){ // 注視点画素=0時
if( *( ps - 1 ) || *( ps + 1 ) ){ // 左右が有効なら
*pd = data; // 書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p || *(p+1) || *(p+2) ){ // 上側が有効なら
*pd = data; // 書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p || *(p+1) || *(p+2) ){ // 下側が有効なら
*pd = data; // 書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
//page
/************************************************************************/
/***** 膨脹 :実行部:8連結*****/
/***** EXPANSION,s,d,8,r *****/
/************************************************************************/
void Filter::expansion_8(
TypeArray *ps, // S画像Ptr
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
expansion_8_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
//page
/************************************************************************/
/***** 膨脹 :実行部:基本部:回数(r)=1専用*****/
/***** EXPANSION,s,d,c,1 *****/
/************************************************************************/
int Filter::expansionSingle(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
int sti; // ステータス情報
s = *ps; // 一旦、S画像情報
ps = &s; // を局所化
d = *pd; // 一旦、D画像情報
pd = &d; // を局所化
sti = PreProcessor3By3( ps, pd ); // 前処理
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
Copy( ps, pd ); // 予め、S→D実行
if( c == 4 ){ // 4連結なら
expansion_4( ps, pd, data ); // 左記で処理
}else{ // 8連結なら
expansion_8( ps, pd, data ); // 左記で処理
} //
return( END_STI ); // 正常終了
}
//page
/************************************************************************/
/***** 膨脹 :実行部:基本部:複数回繰返 *****/
/***** EXPANSION,s,d,c,r *****/
/************************************************************************/
int Filter::expansion(
TypeArray *ps, // S画像情報ptr
TypeArray *pd, // D画像情報ptr
int c, // 連結性
int r, // 繰返回数(2以上)
int data // 描画データ
){
TypeArray *pt; // T画像情報ptr
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray t; // T画像情報:局所:ここでメモリ確保
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
TypeArray t1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
int i; // カウンタ
int sti; // ステータス情報
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
sti = t.MallocByte( h, v ); // 有効画像メモリ確保
if( sti != END_STI ){ // エラー時
return( sti ); // ステータスを返す
} //
pt = &t1; // 一旦、ptrセット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
pt->subset( &t, 1, 1, h - 2, v - 2 ); // T画像情報ptr:内側
Copy( &s, &d ); // 予め、S→D実行:全体
Copy( &s, &t ); // 予め、S→T実行:全体
if( ( r & 0x01 ) != 0 ){ // 奇数回処理なら
if( c == 4 ){ // 4連結なら
expansion_4( pt, pd, data ); // 左記処理:T→D
}else{ // 8連結なら
expansion_8( pt, pd, data ); // 左記処理:T→D
} //
Copy( pd, pt ); // 処理結果→T
r--; // 処理回数をダウン→偶数回
} //
r /= 2; // 2回を一組として組数算出
for( i = 1; i <= r; i++ ){ // 組数分以下繰返す
if( c == 4 ){ // 4連結なら
expansion_4( pd, pt, data ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
expansion_4( pt, pd, data ); // 左記処理:T→D
}else{ // 8連結なら
expansion_8( pd, pt, data ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
expansion_8( pt, pd, data ); // 左記処理:T→D
} //
if( i < r ){ // 次の回も有る場合
Copy( pd, pt ); // 処理結果→T
} //
} //
t.freeMem(); // T画像メモリ解放
return( END_STI ); // 正常終了
}
//page
/************************************************************************/
/***** 膨脹 :実行部*****/
/***** EXPANSION,s,d,c,r *****/
/************************************************************************/
int Filter::Expansion(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r, // 繰り返し回数(省略時1)
int data // 描画データ(省略時255)
){
if( ps->w != 1 || pd->w != 1 ){ // 画素単位=1バイト
return( STI_ARY_5 ); // 以外→左記を返す
} //
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
if( r <= 0 ){ // 回数省略時は
r = 1; // 1をセット
} //
if( r == 1 ){ // 1回実行時は
return( expansionSingle( ps, pd, c, data ) ); // 左記で実行
}else{ // 複数回実行時は
return( expansion( ps, pd, c, r, data ) ); // 左記で処理
} //
}
(1)Expansion(仮引数){アルゴリズム}
code:Expansion(仮引数){
/************************************************************************/
/***** 膨脹 :実行部*****/
/***** EXPANSION,s,d,c,r *****/
/************************************************************************/
int Filter::Expansion(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r, // 繰り返し回数(省略時1)
int data // 描画データ(省略時255)
){
if( ps->w != 1 || pd->w != 1 ){ // 画素単位=1バイト
return( STI_ARY_5 ); // 以外→左記を返す
} //
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
if( r <= 0 ){ // 回数省略時は
r = 1; // 1をセット
} //
if( r == 1 ){ // 1回実行時は
return( expansionSingle( ps, pd, c, data ) ); // 左記で実行
}else{ // 複数回実行時は
return( expansion( ps, pd, c, r, data ) ); // 左記で処理
} //
}
(1-1)関数名
「Expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
(1-2)仮引数
code:仮引数
int Filter::Expansion(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r, // 繰り返し回数(省略時1)
int data // 描画データ(省略時255)
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!
「int data」は、書き込む画素データ!
(1-3)アルゴリズム
code:アルゴリズム
){
if( ps->w != 1 || pd->w != 1 ){ // 画素単位=1バイト
return( STI_ARY_5 ); // 以外→左記を返す
} //
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
if( r <= 0 ){ // 回数省略時は
r = 1; // 1をセット
} //
if( r == 1 ){ // 1回実行時は
return( expansionSingle( ps, pd, c, data ) ); // 左記で実行
}else{ // 複数回実行時は
return( expansion( ps, pd, c, r, data ) ); // 左記で処理
} //
}
「if(ps->w!=1||pd->w!=1){return(STI_ARY_5);}」は、
元画像(S≒ソース)も結果画像(D≒ディスティネーショ
ン)も画素単位が1バイト以外ならエラー「STI_ARY_5」を
関数辺値とし返し終了!
「if(c!=4&&c!=8){return(STI_FLG);}」は、連結性が4でも
8でも無い場合はエラーとし「STI_FLG」を関数辺値とし返
し終了!
「if(r<=0){r=1;}」は、回数「r」が「0以下」ならば、
「1」にする!
「if(r==1){return(expansionSingle(ps,pd,c,data));}」は、
回数「r」が「1」ならば、下請け関数「
expansionSingle(ps,pd,c,data)」で処理し、その辺値を辺値と
し返す!
「else{return(expansion(ps,pd,c,r,data));}」は、回数「r」
が「1」を超える場合、下請け関数「
expansion(ps,pd,c,r,data)」で処理し、その辺値を辺値とし返
す!
(2)expansion(仮引数){アルゴリズム}
code:expansion(仮引数){
/************************************************************************/
/***** 膨脹 :実行部*****/
/***** EXPANSION,s,d,c,r *****/
/************************************************************************/
int Filter::Expansion(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r, // 繰り返し回数(省略時1)
int data // 描画データ(省略時255)
){
if( ps->w != 1 || pd->w != 1 ){ // 画素単位=1バイト
return( STI_ARY_5 ); // 以外→左記を返す
} //
if( c != 4 && c != 8 ){ // 連結性間違い時
return( STI_FLG ); // 左記を返す
} //
if( r <= 0 ){ // 回数省略時は
r = 1; // 1をセット
} //
if( r == 1 ){ // 1回実行時は
return( expansionSingle( ps, pd, c, data ) ); // 左記で実行
}else{ // 複数回実行時は
return( expansion( ps, pd, c, r, data ) ); // 左記で処理
} //
}
(2-1)関数名
「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
備考※「expansion」と「Expansion」で識別して居る事に
注意!
(2-2)仮引数
code:仮引数
int Filter::Expansion(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int r, // 繰り返し回数(省略時1)
int data // 描画データ(省略時255)
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を
示す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティ
ネーション画像)情報を示す「TypeArray」型の情報への
ポインタ変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!
「int data」は、書き込む画素データ!
(2-3)ローカル変数
code:ローカル変数
){
TypeArray *pt; // T画像情報ptr
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
TypeArray t; // T画像情報:局所:ここでメモリ確保
TypeArray s1; // T画像情報:局所:内側
TypeArray d1; // T画像情報:局所:内側
TypeArray t1; // T画像情報:局所:内側
int h; // 水平幅
int v; // 垂直幅
int i; // カウンタ
int sti; // ステータス情報
「TypeArray* pt;」は、T画像≪テンポラリ画像と一時的
な使用領域≫情報へのポインタ
「TypeArray s;」は、S画像(元画像)の変更用局所変数
「TypeArray d;」は、D画像(結果画像)の変更用局所変数
「TypeArray t;」は、T画像(テンポラリ画像)を格納する
局所変数
「TypeArray s1;」は、S画像(元画像)の変更用局所変数
「TypeArray d1;」は、D画像(結果画像)の変更用局所変数
「TypeArray t1;」は、T画像(テンポラリ画像)を格納する
局所変数
「int h;」は、水平幅
「int v;」は、垂直幅
「int i;」は、ループ用のカウンター
「int sti;」は、ステータス(エラーコード)情報
(2-4)アルゴリズム
code:アルゴリズム
h = ( ps->h <= pd->h ) ? ps->h : pd->h; // 有効水平幅算出
v = ( ps->v <= pd->v ) ? ps->v : pd->v; // 有効垂直幅算出
if( h < 3 ){ // 水平サイズ3未満
return( STI_ARY_2 ); // 左記を返す
} //
if( v < 3 ){ // 垂直サイズ3未満
return( STI_ARY_3 ); // 左記を返す
} //
s.subset( ps, 0, 0, h, v ); // 有効画像情報セット
d.subset( pd, 0, 0, h, v ); // 有効画像情報セット
sti = t.MallocByte( h, v ); // 有効画像メモリ確保
if( sti != END_STI ){ // エラー時
return( sti ); // ステータスを返す
} //
pt = &t1; // 一旦、ptrセット
ps = &s1; // 一旦、ptr付け替え
pd = &d1; // 一旦、ptr付け替え
ps->subset( &s, 1, 1, h - 2, v - 2 ); // S画像情報ptr:内側
pd->subset( &d, 1, 1, h - 2, v - 2 ); // D画像情報ptr:内側
pt->subset( &t, 1, 1, h - 2, v - 2 ); // T画像情報ptr:内側
Copy( &s, &d ); // 予め、S→D実行:全体
Copy( &s, &t ); // 予め、S→T実行:全体
if( ( r & 0x01 ) != 0 ){ // 奇数回処理なら
if( c == 4 ){ // 4連結なら
expansion_4( pt, pd, data ); // 左記処理:T→D
}else{ // 8連結なら
expansion_8( pt, pd, data ); // 左記処理:T→D
} //
Copy( pd, pt ); // 処理結果→T
r--; // 処理回数をダウン→偶数回
} //
r /= 2; // 2回を一組として組数算出
for( i = 1; i <= r; i++ ){ // 組数分以下繰返す
if( c == 4 ){ // 4連結なら
expansion_4( pd, pt, data ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
expansion_4( pt, pd, data ); // 左記処理:T→D
}else{ // 8連結なら
expansion_8( pd, pt, data ); // 左記処理:D→T
Copy( pt, pd ); // 処理結果→D
expansion_8( pt, pd, data ); // 左記処理:T→D
} //
if( i < r ){ // 次の回も有る場合
Copy( pd, pt ); // 処理結果→T
} //
} //
t.freeMem(); // T画像メモリ解放
return( END_STI ); // 正常終了
}
「h=(ps->h<=pd->h)?ps->h:pd->h;」は、水平幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「v=(ps->v<=pd->v)?ps->v:pd->v;」は、垂直幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「if(h<3){return(STI_ARY_2);}」は、水平幅が3未満なら
エラーコード「STI_ARY_2」を関数辺値とし返し終了!
「if(v<3){return(STI_ARY_3);}」は、垂直幅が3未満なら
エラーコード「STI_ARY_3」を関数辺値とし返し終了!
「s.subset(ps,0,0,h,v);d.subset(pd,0,0,h,v);」は、
ローカル変数として元画像・結果画像のサイズを調整!
「sti=t.MallocByte(h,v);」は、T画像をメモリ確保!
「if(sti!=END_STI){return(sti);}」は、メモリ確保が
失敗したらエラーコードを関数辺値とし返し終了!
「pt=&t1;ps=&s1;pd=&d1;」は、T画像・S画像・D画像の
ポインタをセット!
「ps->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pd->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pt->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「Copy(&s,&d);Copy(&s,&t);」は、S(元)画像を
D(結果)画像とT画像にコピー
「if((r&0x01)!=0){・・条件成立・・}」は、
条件「(r&0x01)!=0」で回数「r」が奇数回の場合で成立が
「if(c==4){expansion_4(pt,pd,data);}」で4連結ならば
下請け関数「expansion_4(pt,pd,data);」で処理!
「}else{expansion_8(pt,pd,data);}」で84連結ならば
下請け関数「expansion_8(pt,pd,data);」で処理!
そして「Copy(pd,pt);」結果画像を一旦、T画像にコピー
「r--;」で回数「r」を1回処理したと減らす!
「ClearRoundImage(&d,0,1);」は、結果画像の外周一回り
クリア!
「r/=2;」は、回数「r」を半分にする≪処理一組として「
結果画像⇒T画像とT画像⇒結果画像」とするのでコノ回数
にする≫!
「for(i=1;i<=r;i++){・・ループ中身・・}」は、お馴染み
教科書的な繰り返しで回数「r」繰り返す!
そしてループ中身は、
「if(c==4){・4連結処理・}else{・8連結処理・}」で
4連結処理は、
「expansion_4(pd,pt,data);Copy(pt,pd);
expansion_4(pt,pd,data);」で「結果画像⇒T画像」し
T画像を結果画像にコピーし、「T画像⇒結果画像」を
実行!
8連結処理は、
「expansion_8(pd,pt,data);Copy(pt,pd);
expansion_8(pt,pd,data);」で「結果画像⇒T画像」し
T画像を結果画像にコピーし、「T画像⇒結果画像」を
実行!
「if(i<r){Copy(pd,pt);}」は、次の回も存在する場合は、
結果画像をT画像にコピーする!
「t.freeMem();」は、「t.MallocByte(h,v);」でメモリ
確保したメモリを後始末!
「return(END_STI);」は、正常終了を関数辺値とし返し終了
(3)expansionSingle(仮引数){アルゴリズム}
code:expansionSingle(仮引数){
/************************************************************************/
/***** 膨脹 :実行部:基本部:回数(r)=1専用*****/
/***** EXPANSION,s,d,c,1 *****/
/************************************************************************/
int Filter::expansionSingle(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
int sti; // ステータス情報
s = *ps; // 一旦、S画像情報
ps = &s; // を局所化
d = *pd; // 一旦、D画像情報
pd = &d; // を局所化
sti = PreProcessor3By3( ps, pd ); // 前処理
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
Copy( ps, pd ); // 予め、S→D実行
if( c == 4 ){ // 4連結なら
expansion_4( ps, pd, data ); // 左記で処理
}else{ // 8連結なら
expansion_8( ps, pd, data ); // 左記で処理
} //
return( END_STI ); // 正常終了
}
(3-1)関数名
「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「Single」は、シングル、繰り返すで無くシンプルに1回
だけ処理!
(3-2)仮引数
code:仮引数
int Filter::expansionSingle(
TypeArray *ps, // S画像情報
TypeArray *pd, // D画像情報
int c, // 連結性
int data // 描画データ
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を
示す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティ
ネーション画像)情報を示す「TypeArray」型の情報への
ポインタ変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int data」は、書き込む画素データ!
(3-3)ローカル変数
code:ローカル変数
){
TypeArray s; // S画像情報:局所
TypeArray d; // D画像情報:局所
int sti; // ステータス情報
「TypeArray s;」は、S画像(元画像)の変更用局所
変数「TypeArray d;」は、D画像(結果画像)の変更用
局所変数
「int sti;」は、ステータス(エラーコード)
(3-4)アルゴリズム
code:アルゴリズム
s = *ps; // 一旦、S画像情報
ps = &s; // を局所化
d = *pd; // 一旦、D画像情報
pd = &d; // を局所化
sti = PreProcessor3By3( ps, pd ); // 前処理
if( sti != END_STI ){ // エラーがある場合
return( sti ); // ステータスを返す
} //
Copy( ps, pd ); // 予め、S→D実行
if( c == 4 ){ // 4連結なら
expansion_4( ps, pd, data ); // 左記で処理
}else{ // 8連結なら
expansion_8( ps, pd, data ); // 左記で処理
} //
return( END_STI ); // 正常終了
}
(4)expansion_4(仮引数){アルゴリズム}
code:expansion_4(仮引数){
/************************************************************************/
/***** 膨脹 :実行部:4連結*****/
/***** EXPANSION,s,d,4,r *****/
/************************************************************************/
void Filter::expansion_4(
TypeArray *ps, // S画像Ptr
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
(4-1)関数名
「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_4」は、4連結の処理を意味!
(4-2)仮引数
code:仮引数
void Filter::expansion_4(
TypeArray *ps, // S画像Ptr
TypeArray *pd, // D画像情報
int data // 描画データ
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
(4-3)ローカル変数
code:ローカル変数
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅
(4-4)アルゴリズム
code:アルゴリズム
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「expansion_4_x(ptrs,ptrd,incs,data,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加
(5)expansion_4_x(仮引数){アルゴリズム}
code:expansion_4_x(仮引数){
/************************************************************************/
/***** 膨脹 :実行部:4連結:x方向*****/
/***** EXPANSION,s,d,4,r *****/
/************************************************************************/
void Filter::expansion_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps == 0 ){ // 注視点画素=0時
if( *( ps - 1 ) || *( ps - inc ) // 左か上か
|| *( ps + 1 ) || *( ps + inc ) ){ // 右か下が有効なら
*pd = data; // ば、書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
(5-1)関数名
「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_4」は、4連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!
(5-2)仮引数
code:仮引数
void Filter::expansion_4_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int data,」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!
(5-3)アルゴリズム
code:アルゴリズム
){
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps == 0 ){ // 注視点画素=0時
if( *( ps - 1 ) || *( ps - inc ) // 左か上か
|| *( ps + 1 ) || *( ps + inc ) ){ // 右か下が有効なら
*pd = data; // ば、書き込む
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps ==0){・・分岐中身・・}」は、「if(ps ==0){」
で元画像が画素が条件「(=0)」詰まり無効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
条件「(ps-1)||(ps-inc)||(ps+1)||(ps+inc)」で隣接
する左・上・右・下の一つでも有効なら、
「*pd=data;」と結果画像画素に結果書き込み画素の値を
セットします!
(6)expansion_8(仮引数){アルゴリズム}
code:expansion_8(仮引数){
/************************************************************************/
/***** 膨脹 :実行部:8連結*****/
/***** EXPANSION,s,d,8,r *****/
/************************************************************************/
void Filter::expansion_8(
TypeArray *ps, // S画像Ptr
TypeArray *pd, // D画像情報
int data // 描画データ
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
expansion_8_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
(6-1)関数名
「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_8」は、8連結の処理を意味!
(6-2)仮引数
code:仮引数
void Filter::expansion_8(
TypeArray *ps, // S画像Ptr
TypeArray *pd, // D画像情報
int data // 描画データ
){
「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int data)」は、結果書き込み画素の値です!
(6-3)ローカル変数
code:ローカル変数
){
BYTE *ptrs; // S画像Ptr
BYTE *ptrd; // D画像Ptr
int h; // 水平幅
int v; // 垂直幅
int incs; // S画像:増加幅
int incd; // D画像:増加幅
「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅
(6-4)アルゴリズム
code:アルゴリズム
h = ps->h; // 画像のサイズを
v = ps->v; // 取り出し
incs = ps->inc; // S画像増加幅取出
incd = pd->inc; // D画像増加幅取出
ptrs = (BYTE*)ps->adr; // S画像Ptrを取出す
ptrd = (BYTE*)pd->adr; // D画像Ptrを取出す
while( --v >= 0 ){ // 垂直方向に繰返
expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
ptrs += incs; // S画像垂直増加
ptrd += incd; // D画像垂直増加
} //
}
「h=ps->h;v=ps->v;」は、画像の水平幅・垂直幅を取り出
し!元画像・結果画像も同じ有効処理幅に補正されて居る
事が前提!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅を取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の下請け
関数「expansion_8_x(ptrs,ptrd,incs,data,h);」で水平方向
処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポインタ
の値をソレゾレの垂直幅分増加
(7)expansion_8_x(仮引数){アルゴリズム}
code:expansion_8_x(仮引数){
/************************************************************************/
/***** 膨脹 :実行部:8連結:x方向*****/
/***** EXPANSION,s,d,8,r *****/
/************************************************************************/
void Filter::expansion_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
BYTE *p; // S画像Ptr
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps == 0 ){ // 注視点画素=0時
if( *( ps - 1 ) || *( ps + 1 ) ){ // 左右が有効なら
*pd = data; // 書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p || *(p+1) || *(p+2) ){ // 上側が有効なら
*pd = data; // 書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p || *(p+1) || *(p+2) ){ // 下側が有効なら
*pd = data; // 書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
(7-1)関数名
「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_8」は、8連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!
(7-2)仮引数
code:仮引数
void Filter::expansion_8_x(
BYTE *ps, // S画像Ptr
BYTE *pd, // D画像Ptr
int inc, // S画像:増加幅
int data, // 描画データ
int h // 水平幅
){
「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!
(7-3)ローカル変数
code:ローカル変数
){
BYTE *p; // S画像Ptr
「BYTE* p;」は、元画像画素への左上・左下等上下移動分の
ポインタ変数!
(7-4)アルゴリズム
code:アルゴリズム
while( --h >= 0 ){ // 水平方向に繰返し
if( *ps == 0 ){ // 注視点画素=0時
if( *( ps - 1 ) || *( ps + 1 ) ){ // 左右が有効なら
*pd = data; // 書き込む
}else{ // 上記以外の場合
p = ps - inc - 1; // 左上をセットし
if( *p || *(p+1) || *(p+2) ){ // 上側が有効なら
*pd = data; // 書き込む
}else{ // 上記以外で
p = ps + inc - 1; // 左下をセットし
if( *p || *(p+1) || *(p+2) ){ // 下側が有効なら
*pd = data; // 書き込む
} //
} //
} //
} //
ps++; // S画像進行
pd++; // D画像進行
} //
}
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps ==0){・・分岐中身・・}」は、「if(ps ==0){」
で元画像が画素が条件「(=0)」詰まり無効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
「if((ps-1)==0||(ps+1)==0){pd=zero;}」で更に
条件「(ps-1)==0||*(ps+1)==0」と左右隣接画素が一つでも
無効「(=0)」なら、「pd=zero;」で「0」を書き込む、
そして条件が非成立「else{・・非成立処理」として
「p=ps-inc-1;」で左上ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左上・右上隣接
画素が一つでも無効「(=0)」なら、「pd=zero;」で
「0」を書き込む、それでも条件が非成立
「else{・・非成立処理」として「p=ps+inc-1;」で
左下ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;}」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左下・右下隣接
画素が一つでも無効「(=0)」なら、「*pd=zero;」で
「0」を書き込む!
4.追記
孤立点除去・収縮・膨脹が、基本的なよく使う画像図形変換
だが、画像処理アプリで役に立った画像図形変換処理とし、
骨格化(スケルトニング)処理が有りますが、前段として
距離変換と言う多値画像を生成する事を含む処理なので
別の解説エッセイ『距離変換・骨格化』を近々発表して解説
します?!