見出し画像

この仕事は天職だと感じたアルゴリズム開発(続3)

この仕事は天職だと感じたアルゴリズム開発(続3)


2024年12月14日初稿


このエッセイは、
『この仕事は天職だと感じたアルゴリズム開発(続2)』
直接の続編です!

1.図形個別のフェレ計測8連結search8fere()

/****************************************************************************/
/*****      図形のフェレ計測:処理部:ラベル個別のフェレ計測            *****/
/*****  時計回りに輪郭を追跡します                                      *****/
/*****  まず、仮想原点として原点の左隣から処理を始めます。              *****/
/*****  終了条件は、仮想原点をサーチした時とします。                    *****/
/*****  ☆注意:仮想原点を使用するのは、方向サーチを孤立点の時に無      *****/
/*****          限ループにしないためです。                              *****/
/*****  ☆注意:dir_off[]を使用して8連結で時計回りにサーチ             *****/
/*****   dir_off[0..7] = 右・右下・下・左下・左・左上・上・右上の       *****/
/*****   方向のオフセット                                               *****/
/*****  ☆注意:方向オフセットが、サーチ成功時→戻し、失敗時1つ進      *****/
/*****   める事により、処理ポインタを更新し輪郭を追尾します            *****/
/*****   8連結なので2方向分戻します                                  *****/
/*****  ☆注意:画素は、0・正・負と3つに分けて、正の値の画素を追      *****/
/*****         跡します                                                *****/
/*****  注:メモリのサイズもここで変更した分を返します。                *****/
/*****  返値:追跡点履歴Buffer(Overした場合は付け替えした新規メモリ)  *****/
/****************************************************************************/

char**          Filter::search8fere(
    char*       bufptr[],                               // 追跡点履歴Buffer
    char*       p,                                      // 輪郭追跡 Ptr
    int         x,                                      // x座標カウンタ
    int         y,                                      // y座標カウンタ
    TypeSf*     buf,                                    // 計測結果Buffer
    int         dir_off[],                              // 方向OffSetTbl
    int         clr_dt,                                 // ClrData -1 / -2
    int&        size                                    // 座標Bufferサイズ
){
    static const int    tblx[] = {                      // 方向に対するx座
        1, 1, 0, -1, -1, -1, 0, 1                       // 標の変位
    };                                                  //
    static const int    tbly[] = {                      // 方向に対するy座
        0, 1, 1, 1, 0, -1, -1, -1                       // 標の変位
    };                                                  //
    char        **pbufptr;                              // 履歴BufferPtr
    char        **bufNew;                               // 履歴BufferPtr:新規
    char        *ptemp;                                 // 原点
    char        *pp;                                    // 仮想原点
    char        *p1;                                    // 輪郭追跡 Ptr
    int         n;                                      // 履歴個数DownCnt
    int         min_x;                                  // x座標最小値
    int         max_x;                                  // x座標最大値
    int         max_y;                                  // y座標最大値
    int         h;                                      // 水平フェレ径
    int         v;                                      // 垂直フェレ径
    int         len1;                                   // 周囲長:縦横
    int         len2;                                   // 周囲長:斜め
    int         dir;                                    // 方向 0..7
                                                        // 0:右,    1:右下
                                                        // 2:下,    3:左下
                                                        // 4:左,    5:左上
                                                        // 6:上,    7:右上
    int         inc;                                    // インクリ幅

    pbufptr = bufptr;                                   // 履歴BufferptrSet
    n       = size - 3;                                 // 履歴制限数初期値
    buf->xl = x;                                        // Labelx座標格納
    buf->y  = y;                                        // Labely座標格納
    ptemp   = p;                                        // 原点を保存
    pp      = p + dir_off[ 5 ];                         // 仮想原点をセット
    dir     = 0;                                        // 初期値=右
    min_x   = x;                                        // x座標の最小/最
    max_x   = x;                                        // 大値を初期化
    max_y   = y;                                        // y最大座標初期化
    len1    = 0;                                        // 縦横成分の初期化
    len2    = 0;                                        // 斜め成分の初期化
    for(;;){                                            // 以下を繰り返す
        p1 = p + dir_off[ dir ];                        // 次追跡点をセット
        if( p1 == pp ){                                 // 仮想原点なら
            break;                                      // Loopを抜ける
        }                                               //
        if( *p1 > 0 ){                                  // サーチ成功なら
            if( --n <= 0 ){                             // 履歴BufferがOver
                bufNew = reMallocSearchFere( size );    // 再メモリ確保
                if( bufNew == 0 ){                      // 確保失敗時は
                    return( 0 );                        // 「空」を返す
                }else{                                  // 確保成功時は
                    pbufptr = copyXYSearchFere(         // 新規履歴バッファーへ
                            bufptr, pbufptr, bufNew,    // コピー
                            size, n );                  // 
                    free( bufptr );                     // 元の追跡履歴バッファー解放
                    bufptr = bufNew;                    // 新規履歴バッファーをセット
                }                                       // 
            }                                           //
            *pbufptr++ = p;                             // 追跡履歴を取る
            p  = p1;                                    // 追跡点を更新
            x += tblx[ dir ];                           // x座標を更新
            y += tbly[ dir ];                           // y座標を更新
            if( min_x > x ){                            // x座標最小値を
                min_x = x;                              // 更新
            }                                           //
            if( max_x < x ){                            // x座標最大値を
                max_x = x;                              // 更新
            }                                           //
            if( max_y < y ){                            // y座標最大値を
                max_y = y;                              // 更新
            }                                           //
            if( ( dir & 0x01 ) == 0 ){                  // 縦横成分なら
                len1++;                                 // 縦横成分計数UP
            }else{                                      // 斜め成分なら
                len2++;                                 // 斜め成分計数UP
            }                                           //
            dir = ( dir - 2 ) & 0x07;                   // 方向を二つ戻す
        }else{                                          // なければ
            dir = ( dir + 1 ) & 0x07;                   // 方向を進める
        }                                               //
    }                                                   //
    *pbufptr++ = p;                                     // 最終履歴をSetし
    *pbufptr   = 0;                                     // 追跡終点をセット
    h          = max_x - min_x + 1;                     // 水平径算出
    v          = max_y - buf->y + 1;                    // 垂直径算出
    buf->x     = min_x;                                 // フェレx座標格納
    buf->h     = h;                                     // 水平径格納
    buf->v     = v;                                     // 垂直径格納
    if( len1 == 0 && len2 == 0 ){                       // 連結数=0の時は
        len1 = 1;                                       // 1に補正
    }                                                   //
    buf->len = len1 + (int)(                            // 周囲長算出格納
                (double)len2 * 1.41421356 + 0.5 );      // 縦+√2×横成分
    if( h < 3 || v < 3 ){                               // 水平垂直が3未満
        search_clear( bufptr, clr_dt );                 // 輪郭をクリア
    }else if( h == 3 ){                                 // 水平が3の時
        search_clear_right( bufptr, clr_dt );           // 輪郭+右側 クリア
    }else if( v == 3 ){                                 // 垂直が3の時
        inc = dir_off[2];                               // インクリ幅を取出
        search_clear_down( bufptr, inc, clr_dt );       // 輪郭+下側 クリア
    }else if( h == 4 ){                                 // 水平が4の時
        search_clear_rl( bufptr, clr_dt );              // 輪郭+左右 クリア
    }else if( v == 4 ){                                 // 垂直が4の時
        inc = dir_off[2];                               // インクリ幅を取出
        search_clear_ud( bufptr, inc, clr_dt );         // 輪郭+上下 クリア
    }else{                                              // 5×5以上なら
        inc = dir_off[2];                               // インクリ幅を取出
        if( m_swMeasureBorder ){                        // 「真→輪郭線図形計測」時
            search_clear_round( bufptr, inc, clr_dt );  // 輪郭+周辺をクリア
        }else{                                          // 「偽→任意図形」時
            search_clear( bufptr, clr_dt );             // 輪郭をクリア
            p = ptemp - buf->xl + min_x + inc + 1;      // 一回内側始点算出
            search8clear_base( p, h - 2, v - 2, inc,    // Labeling手法でCLR
                                            clr_dt );   //
        }                                               //
    }                                                   // 
    return( bufptr );                                   // 正常終了
}

(1)関数名

「search」は、カタカナ語「サーチ」でココでは、図形を
サーチする意味
「8」は、「8連結」を意味
「fere」は、「フェレ計測」を意味
だから、「search8fere」でフェレ計測様に8連結図形を
サーチするを意味します!

(2)仮引数

char**          Filter::search8fere(
    char*       bufptr[],                               // 追跡点履歴Buffer
    char*       p,                                      // 輪郭追跡 Ptr
    int         x,                                      // x座標カウンタ
    int         y,                                      // y座標カウンタ
    TypeSf*     buf,                                    // 計測結果Buffer
    int         dir_off[],                              // 方向OffSetTbl
    int         clr_dt,                                 // ClrData -1 / -2
    int&        size                                    // 座標Bufferサイズ
){

「char* bufptr[],」は、追跡点履歴バッファー≪輪郭サーチ
を行った画素の場所「char*」型でポイントをバッファーに
格納する為のバッファー≫
「char* p,」は、輪郭サーチ用の画像画素ポインタ
「int x,」は、X座標
「int y,」は、Y座標
「TypeSf* buf,」は、計測結果バッファーを示すポインタ
「int dir_off[],」は、方向オフセットテーブル≪輪郭
サーチ用の次の画素ポインタへのオフセットを格納した
テーブル≫
「int clr_dt,」は、図形≪連結した塊≫を計測後、目印と
してクリアする画素のデータ
「int& size」は、追跡点履歴バッファーのサイズで
「int&」と成って居る事に注意≪内部でバッファーサイズを
変更する可能性が有る≫
ココで「char** Filter::search8fere()」と関数辺値の型は
「char**」と追跡点履歴バッファー自身を関数辺値とし
返します≪内部でバッファーサイズがオーバーした場合に
新たにバッファーを拡大する為です!≫

(3)ローカル変数

){
    static const int    tblx[] = {                      // 方向に対するx座
        1, 1, 0, -1, -1, -1, 0, 1                       // 標の変位
    };                                                  //
    static const int    tbly[] = {                      // 方向に対するy座
        0, 1, 1, 1, 0, -1, -1, -1                       // 標の変位
    };                                                  //
    char        **pbufptr;                              // 履歴BufferPtr
    char        **bufNew;                               // 履歴BufferPtr:新規
    char        *ptemp;                                 // 原点
    char        *pp;                                    // 仮想原点
    char        *p1;                                    // 輪郭追跡 Ptr
    int         n;                                      // 履歴個数DownCnt
    int         min_x;                                  // x座標最小値
    int         max_x;                                  // x座標最大値
    int         max_y;                                  // y座標最大値
    int         h;                                      // 水平フェレ径
    int         v;                                      // 垂直フェレ径
    int         len1;                                   // 周囲長:縦横
    int         len2;                                   // 周囲長:斜め
    int         dir;                                    // 方向 0..7
                                                        // 0:右,    1:右下
                                                        // 2:下,    3:左下
                                                        // 4:左,    5:左上
                                                        // 6:上,    7:右上
    int         inc;                                    // インクリ幅

「static const int tblx[]={1,1,0,-1,-1,-1,0,1};」は、
X座標位置進行テーブル≪添字を「int dir;」の周回方向
カウンタでの位置情報変換テーブル≫
「static const int tbly[]={0,1,1,1,0,-1,-1,-1};」は、
Y座標位置進行テーブル≪添字を「int dir;」の周回方向
カウンタでの位置情報変換テーブル≫
「char** pbufptr;」は、追跡点履歴バッファー
「char* bufptr;」へのポインタ
「char* bufNew;」は、追跡点履歴バッファーがサイズ
オーバーした場合の新規バッファーへのポインタ
「char* ptemp;」は、仮引数「char* p,」を原点とし保存用
「char* pp;」は、仮想原点
「char* p1;」は、作業用追跡ポインタ
「int n;」は、ダウンカウントする個数カウンタ
「int min_x;」は、X座標最小値≪フェレ計測X始点計測用

「int max_x;」は、X座標最大値≪フェレ計測X終点計測用

「int max_y;」は、Y座標最大値≪フェレ計測X終点計測用

「int h;」は、水平フェレ径≪max_x-min_x+1;≫
「int v;」は、水平フェレ径≪max_y-min_y+1;≫
「int len1;」は、周囲長≪縦横ツナガリ画素数≫
「int len2;」は、周囲長≪斜め隣ツナガリ画素数≫
※備考※斜めは長さとして√2を計測値とし乗算します!
「int dir;」は、周回方向カウンタ≪0..7の間をリングカウ
ンタとし方向「0:右、1:右下、2:下、3:左下、4:左、
5:左上、6:上、7:右上」≫
「int inc;」は、インクリメント幅≪画像画素を垂直方向に
ポインタ移動用の増加幅≫

(4)アルゴリズム

    pbufptr = bufptr;                                   // 履歴BufferptrSet
    n       = size - 3;                                 // 履歴制限数初期値
    buf->xl = x;                                        // Labelx座標格納
    buf->y  = y;                                        // Labely座標格納
    ptemp   = p;                                        // 原点を保存
    pp      = p + dir_off[ 5 ];                         // 仮想原点をセット
    dir     = 0;                                        // 初期値=右
    min_x   = x;                                        // x座標の最小/最
    max_x   = x;                                        // 大値を初期化
    max_y   = y;                                        // y最大座標初期化
    len1    = 0;                                        // 縦横成分の初期化
    len2    = 0;                                        // 斜め成分の初期化
    for(;;){                                            // 以下を繰り返す
        p1 = p + dir_off[ dir ];                        // 次追跡点をセット
        if( p1 == pp ){                                 // 仮想原点なら
            break;                                      // Loopを抜ける
        }                                               //
        if( *p1 > 0 ){                                  // サーチ成功なら
            if( --n <= 0 ){                             // 履歴BufferがOver
                bufNew = reMallocSearchFere( size );    // 再メモリ確保
                if( bufNew == 0 ){                      // 確保失敗時は
                    return( 0 );                        // 「空」を返す
                }else{                                  // 確保成功時は
                    pbufptr = copyXYSearchFere(         // 新規履歴バッファーへ
                            bufptr, pbufptr, bufNew,    // コピー
                            size, n );                  // 
                    free( bufptr );                     // 元の追跡履歴バッファー解放
                    bufptr = bufNew;                    // 新規履歴バッファーをセット
                }                                       // 
            }                                           //
            *pbufptr++ = p;                             // 追跡履歴を取る
            p  = p1;                                    // 追跡点を更新
            x += tblx[ dir ];                           // x座標を更新
            y += tbly[ dir ];                           // y座標を更新
            if( min_x > x ){                            // x座標最小値を
                min_x = x;                              // 更新
            }                                           //
            if( max_x < x ){                            // x座標最大値を
                max_x = x;                              // 更新
            }                                           //
            if( max_y < y ){                            // y座標最大値を
                max_y = y;                              // 更新
            }                                           //
            if( ( dir & 0x01 ) == 0 ){                  // 縦横成分なら
                len1++;                                 // 縦横成分計数UP
            }else{                                      // 斜め成分なら
                len2++;                                 // 斜め成分計数UP
            }                                           //
            dir = ( dir - 2 ) & 0x07;                   // 方向を二つ戻す
        }else{                                          // なければ
            dir = ( dir + 1 ) & 0x07;                   // 方向を進める
        }                                               //
    }                                                   //
    *pbufptr++ = p;                                     // 最終履歴をSetし
    *pbufptr   = 0;                                     // 追跡終点をセット
    h          = max_x - min_x + 1;                     // 水平径算出
    v          = max_y - buf->y + 1;                    // 垂直径算出
    buf->x     = min_x;                                 // フェレx座標格納
    buf->h     = h;                                     // 水平径格納
    buf->v     = v;                                     // 垂直径格納
    if( len1 == 0 && len2 == 0 ){                       // 連結数=0の時は
        len1 = 1;                                       // 1に補正
    }                                                   //
    buf->len = len1 + (int)(                            // 周囲長算出格納
                (double)len2 * 1.41421356 + 0.5 );      // 縦+√2×横成分
    if( h < 3 || v < 3 ){                               // 水平垂直が3未満
        search_clear( bufptr, clr_dt );                 // 輪郭をクリア
    }else if( h == 3 ){                                 // 水平が3の時
        search_clear_right( bufptr, clr_dt );           // 輪郭+右側 クリア
    }else if( v == 3 ){                                 // 垂直が3の時
        inc = dir_off[2];                               // インクリ幅を取出
        search_clear_down( bufptr, inc, clr_dt );       // 輪郭+下側 クリア
    }else if( h == 4 ){                                 // 水平が4の時
        search_clear_rl( bufptr, clr_dt );              // 輪郭+左右 クリア
    }else if( v == 4 ){                                 // 垂直が4の時
        inc = dir_off[2];                               // インクリ幅を取出
        search_clear_ud( bufptr, inc, clr_dt );         // 輪郭+上下 クリア
    }else{                                              // 5×5以上なら
        inc = dir_off[2];                               // インクリ幅を取出
        if( m_swMeasureBorder ){                        // 「真→輪郭線図形計測」時
            search_clear_round( bufptr, inc, clr_dt );  // 輪郭+周辺をクリア
        }else{                                          // 「偽→任意図形」時
            search_clear( bufptr, clr_dt );             // 輪郭をクリア
            p = ptemp - buf->xl + min_x + inc + 1;      // 一回内側始点算出
            search8clear_base( p, h - 2, v - 2, inc,    // Labeling手法でCLR
                                            clr_dt );   //
        }                                               //
    }                                                   // 
    return( bufptr );                                   // 正常終了
}
8連結方向

「dir=0;」は、追跡方向を「0=右側」にセット
「min_x=x;max_x=x;max_y=y;」は、計測対象のX座標最小
最大値及びY座標最大値を初期化
「len1=0;len2=0;」は、周囲長≪画素数縦横・斜め≫を
初期化
「for(;;){・・処理ループ・・}」は、無限forループで
処理ループ≪ループから抜けるのは正常動作なら「break;」
でループから抜け、エラー発生時は「return(0);」で関数
終了≫、で処理ループは、以下に説明します!
「p1=p+dir_off[dir];」は、注視点の隣接周辺追跡点作成
「if(p1==pp){break;}」は、条件「p1==pp」で追跡点が、
仮想原点≪時計回り一筆書きなので一周回った事に成る≫に
到達した事で図形の輪郭サーチ処理ループ終了で「break;」
とループを抜ける!
「if(*p1>0){・・処理・・}else{dir=(dir+1)&0x07;}」は、
条件「*p1>0」で有効画素(正の値)なら、以下に説明する
処理で図形≪8連結での塊≫を計測し、「else」詰まり無効
画素の場合で
「dir=(dir+1)&0x07;」と方向「dir」を示す値を更新≪
「dir+1」でカウントアップ≪「+1」と進行する事で【時計
回り方向「右⇒右下⇒下⇒左下⇒左⇒左上⇒上⇒右上】の
次へ≫、「&0x07」で
※ビット毎の論理積(AND演算)とビット毎論理式に馴染
まない人への解説【C言語算術演算で書き換えると
「(dir+1)%8;」と8で除算した余りと成りますが、多くの
CPUでは高速化手法として使用出来ます】≫、では、
有効画素の場合、
「if(--n<=0){・・履歴バッファー限度超え処置・・}」は、
条件「--n<=0」で「--n」は、バッファー格納制限をダウン
カウントで減じ、0以下に成ったら、履歴バッファー限度超
え処置を行う事で履歴バッファー限度以上に輪郭サーチ履歴
を可能に出来る処置を行う!その処置は、
「bufNew=reMallocSearchFere(size);」で下請け関数
「reMallocSearchFere(size);」でサイズ「size」を大幅に
増やし、この関数の仮引数「int& size」と増やした値を
引数で返し、関数の内部で動的にメモリ確保し新しく確保し
たバッファーの先頭ポインタを返す!
「if(bufNew==0){return(0);}」でメモリ確保に失敗したら
関数辺値とし「0=空ポインタ」返し終了≪メモリ確保失敗
エラーとし扱う≫
「else{pbufptr=copyXYSearchFere(
bufptr,pbufptr,bufNew,size,n);free(bufptr);
bufptr=bufNew;}」で下請け関数「copyXYSearchFere()」で
新しいメモリ確保バッファー「bufNew」に元の履歴バッ
ファー「bufptr」の内容をコピーし、
「free(bufptr);」と元のバッファー「bufptr」を解放≪
動的にメモリ確保した領域をOSに返す≫し、
「bufptr=bufNew;」と履歴バッファーを付け替える!
「*pbufptr++=p;」は、現在の注視点画像画素ポインタを
「*pbufptr++」と履歴バッファーに格納し、
「p=p1;」は、注視点画像画素ポインタを次追跡点に進行
「x+=tblx[dir];y+=tbly[dir];」は、XY座標を更新
「if(min_x>x){min_x=x;}」は、X座標最小値更新
「if(max_x<x){max_x=x;}」は、X座標最大値更新
「if(max_y<y){max_y=y;}」は、Y座標最大値更新
「if((dir&0x01)==0){len1++;}else{len2++;}」は、周囲長
≪条件「(dir&0x01)==0」で※ビット毎の論理積(
AND演算)とビット毎論理式に馴染まない人への解説
【C言語算術演算で書き換えると「(dir+1)%2;」と2で除算
した余りと成りますが、多くのCPUでは高速化手法として
使用出来ます】で偶奇判定で偶数が縦横直交画素数なので
「len1++;」で処理・奇数が斜め方向画素数なので
「len2++;」で処理≫でそれぞれカウントアップ!
「dir=(dir-2)&0x07;」は、「dir」を示す値を変更「二つ戻
す」≪「dir-2」でカウントダウン≪「-2」と逆進する事で
【反時計回り方向「上⇒左上⇒左⇒左下⇒下⇒右下⇒右⇒
左上」】の次へ≫、
「&0x07」で※ビット毎の論理積(AND演算)とビット毎
論理式に馴染まない人への解説【C言語算術演算で書き換え
ると「(dir-1)%8;」と8で除算した余りと成りますが、
多くのCPUでは高速化手法として使用出来ます】≫
「pbufptr++=p;」は、輪郭サーチ最後の画像画素ポインタ
を履歴バッファーに格納
「pbufptr=0;」は、目印として履歴バッファー最後に
空ポインタ「=0」をセット
「h=max_x-min_x+1;」は、水平フェレ径算出
「v=max_y-buf->y+1;」は、垂直フェレ径算出
「buf->x=min_x;」は、フェレX座標を計測値としセット
「buf->h=h;buf->v=v;」は、フェレ水平垂直径を計測値とし
セット
「if(len1==0&&len2==0){len1=1;}」は、周囲長≪画素数≫が
0なら、「len=1;」としてセット
「buf->len=len1+(int)((double)len*21.41421356+0.5);」
は、計測値として周囲長を
算出「len1+(int)((double)len*21.41421356+0.5)」して、
※備考※「(double)len*21.41421356+0.5)」と斜め画素連結
は、√2≒1.41421356を乗算し「+0.5」と四捨五入用の値を
付加して「(int)((double)len*21.41421356+0.5);」と四捨
五入した整数値とし、「buf->len」に格納!
「if(h<3||v<3){search_clear(bufptr,clr_dt);}」は、
条件「h<3||v<3」で図形≪4連結での塊≫水平径か垂直径が
3画素未満の場合は、下請け
関数「search_clear(bufptr,clr_dt);」で図形をクリア
「else if(h==3){search_clear_right(bufptr,clr_dt);}」
は、条件「h==3」で図形水平径が3画素の場合は、下請け
関数「search_clear_right(bufptr,clr_dt);」で図形を
クリア
「else if(v==3){inc=dir_off[2];
search_clear_down(bufptr,inc,clr_dt);}」は、
条件「v==3」で図形垂直径が3画素の場合は、
「inc=dir_off[1];」で画像の増加幅を取り出し、下請け
関数「search_clear_down(bufptr,inc,clr_dt);」で図形
をクリア
「else if(h==4){search_clear_rl(bufptr,clr_dt);}」は、
条件「h==4」で図形水平径が4画素の場合は、下請け
関数「search_clear_rl(bufptr,clr_dt);」で図形をクリア
「else if(v==4){inc=dir_off[1];
search_clear_ud(bufptr,inc,clr_dt);}」は、
条件「v==4」で図形垂直径が4画素の場合は、
「inc=dir_off[2];」で画像の増加幅を取り出し、下請け
関数「search_clear_ud(bufptr,inc,clr_dt);」で図形を
クリア
「else{・・5×5以上図形をクリア・・」は、
「inc=dir_off[2];」で画像の増加幅を取り出し、
「if(m_swMeasureBorder){
search_clear_round(bufptr,inc,clr_dt);
」で条件「m_swMeasureBorder」でこのスイッチが真の場合
は、下請け関数「search_clear_round(bufptr,inc,clr_dt);
」で図形をクリア、
「else{
search_clear(bufptr,clr_dt);
p=ptemp-buf->xl+min_x+inc+1;
search8clear_base(p,h-2,v-2,inc,
clr_dt);}」と「else{」で
条件「m_swMeasureBorder」でこの
スイッチが偽の場合は、
「search_clear(bufptr,clr_dt);」で下請け関数
「search_clear(bufptr,clr_dt);」で輪郭クリアし、
「p=ptemp-buf->xl+min_x+inc+1;」で図形画像の一回り
内側の始点をセットし、下請け関数
「search8clear_base(p,h-2,v-2,inc,clr_dt);」で
図形をクリア
「return(bufptr);」は、追跡点履歴バッファーのポインタ
を関数辺値とし返し終了

2.輪郭のクリア+1周クリア
search_clear_round()

/************************************************************************/
/*****      図形のフェレ計測:処理部:輪郭のクリア+1周クリア      *****/
/*****  輪郭線を履歴バッファーを使用してクリアすると共に            *****/
/*****  輪郭の上下左右斜めに正のデータがあればクリアする            *****/
/*****  クリアは、-1 か -2 でクリア                             *****/
/*****  8連結で「輪郭」や「線分」図形が対象                        *****/
/************************************************************************/

void        Filter::search_clear_round(
    char    **pbufptr,                              // 追跡点履歴 Ptr
    int     inc,                                    // インクリメント幅
    int     clr_dt                                  // クリアデータ
){
    char    *p;                                     // 書き込みポインタ
    char    *p1;                                    // 書き込みポインタ:隣

    while( ( p = *pbufptr++ ) != 0 ){               // ポインタを取出し
        *p = clr_dt;                                // 輪郭点をクリアし
        p1 = p - inc - 1;                           // 左上セット
        if( *p1 > 0 ){                              // 左上隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 上に移動
        if( *p1 > 0 ){                              // 上隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 右上に移動
        if( *p1 > 0 ){                              // 右上隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1 = p - 1;                                 // 左セット
        if( *p1 > 0 ){                              // 左隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1 = p + 1;                                 // 右セット
        if( *p1 > 0 ){                              // 右隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1 = p + inc - 1;                           // 左下セット
        if( *p1 > 0 ){                              // 左下隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 下に移動
        if( *p1 > 0 ){                              // 下隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 右下に移動
        if( *p1 > 0 ){                              // 右下隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
    }                                               //
}

(1)関数名

「search」は、カタカナ語「サーチ」でココでは、図形を
サーチする意味でココではサーチした履歴バッファー
「clear」は、「クリア」消去を意味
「round」は、「1周」を意味≪作成時は恐らく苦し紛れの
命名です私は英単語は苦手なのだ!≫
だから、「search_clear_round」で輪郭のクリア+
1周クリアと無理な命名をしました!

(2)仮引数

void        Filter::search_clear_round(
    char    **pbufptr,                              // 追跡点履歴 Ptr
    int     inc,                                    // インクリメント幅
    int     clr_dt                                  // クリアデータ
){

「char**pbufptr,」は、追跡点履歴バッファー
「int inc,」は、画像の垂直方向増加幅、
「int clr_dt」は、輪郭画素をクリアするデータ

(3)ローカル変数

){
    char    *p;                                     // 書き込みポインタ
    char    *p1;                                    // 書き込みポインタ:隣

「char *p;」は、画素書き込みポインタ
「char *p1」は、画素書き込みポインタ隣

(4)アルゴリズム

    while( ( p = *pbufptr++ ) != 0 ){               // ポインタを取出し
        *p = clr_dt;                                // 輪郭点をクリアし
        p1 = p - inc - 1;                           // 左上セット
        if( *p1 > 0 ){                              // 左上隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 上に移動
        if( *p1 > 0 ){                              // 上隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 右上に移動
        if( *p1 > 0 ){                              // 右上隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1 = p - 1;                                 // 左セット
        if( *p1 > 0 ){                              // 左隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1 = p + 1;                                 // 右セット
        if( *p1 > 0 ){                              // 右隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1 = p + inc - 1;                           // 左下セット
        if( *p1 > 0 ){                              // 左下隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 下に移動
        if( *p1 > 0 ){                              // 下隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
        p1++;                                       // 右下に移動
        if( *p1 > 0 ){                              // 右下隣が正なら
            *p1 = clr_dt;                           // クリア
        }                                           //
    }                                               //
}

「while((p=*pbufptr++)!=0){・・ループ本体・・}」は、
ループ条件「(p=*pbufptr++)!=0」で「p=*pbufptr++」で
画素書き込みポインタを取り出し、
条件「(p=*pbufptr++)!=0」で空ポインタ≪バッファーの
最後を番兵とし空ポインタをセットして有る≫で無い場合は
ループ本体を繰り返し、ループ本体は、
「*p=clr_dt;」で画像画素をクリア≪仮引数「int clr_dt」
を書き込む≫
「p1=p-inc-1;」で左上隣を書き込みポインタにセット
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア
「p1++;」で書き込みポインタを上隣に移動
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア
「p1++;」で書き込みポインタを右上隣に移動
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア
「p1=p-1;」で左隣を書き込みポインタにセット
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア
「p1=p+1;」で右隣を書き込みポインタにセット
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア
「p1=p+inc-1;」で左下を書き込みポインタにセット
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア
「p1++;」で書き込みポインタを下隣に移動
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア
「p1++;」で書き込みポインタを右下隣に移動
「if(*p1>0){*p1=clr_dt;}」で条件「*p1>0」で有効画素な
ら、「*p1=clr_dt;」と画像画素をクリア

3.簡易ラベリングで8連結クリアsearch8clear_base()

/************************************************************************/
/*****      図形のフェレ計測:8連結:  図形のフェレ範囲内で        *****/
/*****                              :簡易ラベリングを使用          *****/
/*****  クリアは、対象図形の輪郭をクリアデータでクリアしてるものとし*****/
/*****  対象画素をクリアします。                                    *****/
/*****  フェレ径 H × V = 5 × 5 以上が対象                   *****/
/************************************************************************/

void        Filter::search8clear_base(
    char    *p,                                                 // フェレ始点
    int     h,                                                  // 水平フェレ径
    int     v,                                                  // 垂直フェレ径
    int     inc,                                                // 増加幅
    int     clr_dt                                              // クリアデータ
){
    char    *px;                                                // 追跡点:水平
    char    *py;                                                // 追跡点:垂直
    char    *p1;                                                // 追跡点:上下
    char    c;                                                  // データ
    int     x;                                                  // 水平方向Cnt
    int     y;                                                  // 垂直方向Cnt
    int     sw;                                                 // 変更有Switch

    sw = TRUE;                                                  // 変更Sw初期化
    while( sw ){                                                // 繰り返し条件
        sw = FALSE;                                             // 変更Swクリア
        py = p;                                                 // 左上追跡点Set
        for( y = v; --y >= 0; py += inc ){                      // 垂直幅分繰返
            px = py;                                            // 水平追跡点Set
            if( sw ){                                           // 変更Swセット済みなら
                for( x = h; --x >= 0; px++ ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px - 1 ) == clr_dt ){            // 左隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                        }else{                                  // それ以外
                            p1 = px - inc - 1;                  // 左上をセット
                            c  = *p1++;                         // 左上を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 上を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右上を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }else{                                              // 変更Swセット未設定なら
                for( x = h; --x >= 0; px++ ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px - 1 ) == clr_dt ){            // 左隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                            sw  = TRUE;                         // 変更有を示す
                        }else{                                  // それ以外
                            p1 = px - inc - 1;                  // 左上をセット
                            c  = *p1++;                         // 左上を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                                sw  = TRUE;                     // 変更有を示す
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 上を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                    sw  = TRUE;                 // 変更有を示す
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右上を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                        sw  = TRUE;             // 変更有を示す
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }                                                   // 
        }                                                       //
        py = p + ( v - 1 ) * inc + h - 1;                       // 右下追跡点Set
        for( y = v; --y >= 0; py -= inc ){                      // 垂直幅分繰返
            px = py;                                            // 水平追跡点Set
            if( sw ){                                           // 変更Swセット済みなら
                for( x = h; --x >= 0; px-- ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px + 1 ) == clr_dt ){            // 右隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                        }else{                                  // それ以外
                            p1 = px + inc - 1;                  // 左下をセット
                            c  = *p1++;                         // 左下を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 下を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右下を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }else{                                              // 変更Swセット未設定なら
                for( x = h; --x >= 0; px-- ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px + 1 ) == clr_dt ){            // 右隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                            sw  = TRUE;                         // 変更有を示す
                        }else{                                  // それ以外
                            p1 = px + inc - 1;                  // 左下をセット
                            c  = *p1++;                         // 左下を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                                sw  = TRUE;                     // 変更有を示す
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 下を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                    sw  = TRUE;                 // 変更有を示す
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右下を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                        sw  = TRUE;             // 変更有を示す
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }                                                   // 
        }                                                       //
        p += inc + 1;                                           // 一つ内側に
        h -= 2;                                                 // 始点と範囲を
        v -= 2;                                                 // 補正
    }                                                           //
}                                                               //

(1)関数名

code:
「search」は、カタカナ語「サーチ」でココでは、図形を
サーチする意味でココではサーチした履歴バッファー
「8」は、8連結を意味で「search8」で8連結サーチ
「clear」は、「クリア」消去を意味
「base」は基本を意味
だから、「search8clear_base」で輪郭座標サーチデータで
輪郭とその中を8連結でクリア

(2)仮引数

void        Filter::search8clear_base(
    char    *p,                                                 // フェレ始点
    int     h,                                                  // 水平フェレ径
    int     v,                                                  // 垂直フェレ径
    int     inc,                                                // 増加幅
    int     clr_dt                                              // クリアデータ
){

「char*p,」は、フェレ始点画像画素へのポインタ
「int h,」は、水平フェレ径
「int v,」は、垂直フェレ径
「int inc,」は、画像の垂直方向増加幅
「int clr_dt」は、輪郭画素をクリアするデータ

(3)ローカル変数

){
    char    *px;                                                // 追跡点:水平
    char    *py;                                                // 追跡点:垂直
    char    *p1;                                                // 追跡点:上下
    char    c;                                                  // データ
    int     x;                                                  // 水平方向Cnt
    int     y;                                                  // 垂直方向Cnt
    int     sw;                                                 // 変更有Switch

「char* px;」は、フェレ径内画像をラスタースキャンする
X座標方向作業ポインタ
「char* py;」は、フェレ径内画像をラスタースキャンする
Y座標方向作業ポインタ
「char* p1;」は、追跡点作業ポインタ
Y座標方向作業ポインタ
「char c;」は、画素データ
「int x;」は、水平方向(X座標方向)ダウンカウンタ
「int y;」は、垂直方向(Y座標方向)ダウンカウンタ
「int sw;」は、画素変更スィッチとし連結していたら
連続してクリアし、スィッチがOFFならクリアするデータ
が有るとONに成るON/OFFスィッチ

(4)アルゴリズム

    sw = TRUE;                                                  // 変更Sw初期化
    while( sw ){                                                // 繰り返し条件
        sw = FALSE;                                             // 変更Swクリア
        py = p;                                                 // 左上追跡点Set
        for( y = v; --y >= 0; py += inc ){                      // 垂直幅分繰返
            px = py;                                            // 水平追跡点Set
            if( sw ){                                           // 変更Swセット済みなら
                for( x = h; --x >= 0; px++ ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px - 1 ) == clr_dt ){            // 左隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                        }else{                                  // それ以外
                            p1 = px - inc - 1;                  // 左上をセット
                            c  = *p1++;                         // 左上を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 上を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右上を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }else{                                              // 変更Swセット未設定なら
                for( x = h; --x >= 0; px++ ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px - 1 ) == clr_dt ){            // 左隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                            sw  = TRUE;                         // 変更有を示す
                        }else{                                  // それ以外
                            p1 = px - inc - 1;                  // 左上をセット
                            c  = *p1++;                         // 左上を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                                sw  = TRUE;                     // 変更有を示す
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 上を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                    sw  = TRUE;                 // 変更有を示す
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右上を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                        sw  = TRUE;             // 変更有を示す
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }                                                   // 
        }                                                       //
        py = p + ( v - 1 ) * inc + h - 1;                       // 右下追跡点Set
        for( y = v; --y >= 0; py -= inc ){                      // 垂直幅分繰返
            px = py;                                            // 水平追跡点Set
            if( sw ){                                           // 変更Swセット済みなら
                for( x = h; --x >= 0; px-- ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px + 1 ) == clr_dt ){            // 右隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                        }else{                                  // それ以外
                            p1 = px + inc - 1;                  // 左下をセット
                            c  = *p1++;                         // 左下を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 下を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右下を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }else{                                              // 変更Swセット未設定なら
                for( x = h; --x >= 0; px-- ){                   // 水平幅分繰返
                    if( *px > 0 ){                              // 未連結画素→
                        if( *( px + 1 ) == clr_dt ){            // 右隣と連結時
                            *px = clr_dt;                       // CLRデータSet
                            sw  = TRUE;                         // 変更有を示す
                        }else{                                  // それ以外
                            p1 = px + inc - 1;                  // 左下をセット
                            c  = *p1++;                         // 左下を取出し
                            if( c == clr_dt ){                  // 連結ならば
                                *px = clr_dt;                   // CLRデータSet
                                sw  = TRUE;                     // 変更有を示す
                            }else{                              // 非連結ならば
                                c = *p1++;                      // 下を取出し
                                if( c == clr_dt ){              // 連結ならば
                                    *px = clr_dt;               // CLRデータSet
                                    sw  = TRUE;                 // 変更有を示す
                                }else{                          // 非連結ならば
                                    c = *p1;                    // 右下を取出し
                                    if( c == clr_dt ){          // 連結ならば
                                        *px = clr_dt;           // CLRデータSet
                                        sw  = TRUE;             // 変更有を示す
                                    }                           //
                                }                               //
                            }                                   //
                        }                                       //
                    }                                           //
                }                                               //
            }                                                   // 
        }                                                       //
        p += inc + 1;                                           // 一つ内側に
        h -= 2;                                                 // 始点と範囲を
        v -= 2;                                                 // 補正
    }                                                           //
}                                                               //

「sw=TRUE;」は、初期化としスィッチON
「while(sw){・・最外側ループ・・}」は、条件「sw」で
スィッチONで繰り返す、そして最外側ループは、
「sw=FALSE;」でループ本体、即、スィッチOFF
ここから、暫く、正方向ラスタースキャン≪外側ループと
してのY座標方向は上から下、内側のX座標方向は左から
右へ≫を二重ループとし処理します!
「py=p;」は、ラスタースキャン用のY座標方向画像画素
ポインタをセット
「for(y=v;--y>=0;py+=inc){・Y座標方向処理・}」は、
forループ「y=v;--y>=0;py+=inc」で
「y=v;--y>=0;」とダウンカウント方式≪往々にしてこの
記載の方が、コンパイラに依って高速化処理コード生成≫で
垂直径「v」の回数繰り返す、ループ終了時に「py+=inc」と
Y座標方向(垂直方向)にポインタを進行する!そして
Y座標方向処理は、
「px=py;」は、ラスタースキャン用のX座標方向画像画素
ポインタをセット
「if(sw){・・ON時処理・・}else{・・OFF時処理・・
}」は、条件「sw」でON時処理は、
「for(x=h;--x>=0;px++){・X座標方向処理・}」は、
forループ「x=h;--x>=0;px++」で「x=h;--x>=0;」と
ダウンカウント方式≪往々にしてこの記載の方が、
コンパイラに依って高速化処理コード生成≫で水平径「h」
の回数繰り返す、ループ終了時に「px++」とX座標方向
(水平方向)にポインタを進行する!そしてX座標方向処理
は、「if(px>0){・・分岐中身・・}」は、
条件「px>0」と有効画素の場合で処理、その分岐中身は、
「if((px-1)==clr_dt){px=clr_dt;}」と
条件「(px-1)==clr_dt」で左隣「(px-1)」がクリアデータ
の場合は、「*px=clr_dt;」と注視点画素をクリア
「else」と左隣がクリアデータ以外ならば、
「p1=px-inc-1;」で追跡点ポインタを左上にセットし、
「c=*p1++;」で左上画素データを取り出し、ポインタを上に
進行
「if(c==clr_dt){*px=clr_dt;}」で追跡点(左上)が
クリアデータなら「*px=clr_dt;」と注視点をクリア
「else{・・条件不成立・・」と追跡点(左上)がクリア
データ以外なら
「c=*p1++;」で上画素データを取り出し、ポインタを右上に
進行
「if(c==clr_dt){*px=clr_dt;}」で追跡点(上)がクリア
データなら「*px=clr_dt;」と注視点をクリア
「else{c=*p1;if(c==clr_dt){*px=clr_dt;}}」で
追跡点(上)がクリアデータ以外なら
「c=*p1;」で右上画素データを取り出し、
「if(c==clr_dt){*px=clr_dt;}」で追跡点(右上)が
クリアデータなら「*px=clr_dt;」と注視点をクリア
条件「sw」がOFFの時は、
「for(x=h;--x>=0;px++){・X座標方向処理・」は、
forループ「x=h;--x>=0;px++」で「x=h;--x>=0;」と
ダウンカウント方式≪往々にしてこの記載の方が、
コンパイラに依って高速化処理コード生成≫で水平径「h」
の回数繰り返す、ループ終了時に「px++」とX座標方向
(水平方向)にポインタを進行する!そしてX座標方向処理
は、「if(px>0){・・分岐中身・・}」は、
条件「px>0」と有効画素の場合で処理、その分岐中身は、
「if((px-1)==clr_dt){px=clr_dt;sw=TRUE;}」と
条件「(px-1)==clr_dt」で左隣「(px-1)」がクリアデータ
の場合は、「*px=clr_dt;」と注視点画素をクリア、そして
「sw=TRUE;」とスィッチON
「else」と左隣がクリアデータ以外ならば、
「p1=px-inc-1;」で追跡点ポインタを左上にセットし、
「c=*p1++;」で左上画素データを取り出し、ポインタを上に
進行
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で
追跡点(左上)がクリアデータなら「*px=clr_dt;」と
注視点をクリアし、「sw=TRUE;」とスィッチON
「else{・・条件不成立・・」と追跡点(左上)がクリア
データ以外なら
「c=*p1++;」で上画素データを取り出し、ポインタを上に
進行
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で追跡点(上)が
クリアデータなら「*px=clr_dt;」と注視点をクリアし、
「sw=TRUE;」とスィッチON
「else{c=*p1;if(c==clr_dt){*px=clr_dt;sw=TRUE;}}」で
追跡点(下)がクリアデータ以外なら
「c=*p1;」で右下画素データを取り出し、
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で
追跡点(右下)がクリアデータなら「*px=clr_dt;」と
注視点をクリアし、「sw=TRUE;」とスィッチON
「for(y=v;--y>=0;py-=inc){){・Y座標逆方向処理・}」は
forループ「y=v;--y>=0;py-=inc」で
「y=v;--y>=0;」とダウンカウント方式≪往々にしてこの
記載の方が、コンパイラに依って高速化処理コード生成≫で
垂直径「v」の回数繰り返す、ループ終了時に「py-=inc」と
Y座標方向(垂直方向)にポインタを逆進行する!そして
Y座標方向処理は、
「px=py;」は、ラスタースキャン用のX座標方向画像画素
ポインタをセット
「if(sw){・・ON時処理・・}else{・・OFF時処理・・
}」は、条件「sw」でON時処理は、
「for(x=h;--x>=0;px--){・X座標逆方向処理・}」は、
forループ「x=h;--x>=0;px--」で「x=h;--x>=0;」と
ダウンカウント方式≪往々にしてこの記載の方が、
コンパイラに依って高速化処理コード生成≫で水平径「h」
の回数繰り返す、ループ終了時に「px--」とX座標方向
(水平方向)にポインタを逆進する!そしてX座標方向処理
は、「if(px>0){・・分岐中身・・}」は、
条件「px>0」と有効画素の場合で処理、その分岐中身は、
「if((px-1)==clr_dt){px=clr_dt;}」と
条件「(px-1)==clr_dt」で左隣「(px-1)」がクリアデータ
の場合は、「*px=clr_dt;」と注視点画素をクリア
「else」と左隣がクリアデータ以外ならば、
「p1=px-inc-1;c=*p1++;」で追跡点を左上側にセットし、
画素データ取り出し追跡点を上側に進行、
「if(c==clr_dt){*px=clr_dt;}」で左上隣「c」がクリア
データの場合は、「*px=clr_dt;」と注視点画素をクリア
「else」と左上隣がクリアデータ以外ならば、
「c=*p1++;」で上側画素データ取り出し追跡点を右上側に
進行、「if(c==clr_dt){*px=clr_dt;}」で上隣「c」が
クリアデータの場合は、「*px=clr_dt;」と注視点画素を
クリア
「else」と上隣がクリアデータ以外ならば、
「c=*p1;」で右上側画素データ取り出し、
「if(c==clr_dt){*px=clr_dt;}」で右上隣「c」がクリア
データの場合は、「*px=clr_dt;」と注視点画素をクリアと
X座標方向の内側ループを終え、
条件「sw」でOFF時処理は、
「for(x=h;--x>=0;px--){・X座標逆方向処理・}」は、
forループ「x=h;--x>=0;px--」で「x=h;--x>=0;」と
ダウンカウント方式≪往々にしてこの記載の方が、
コンパイラに依って高速化処理コード生成≫で水平径「h」
の回数繰り返す、ループ終了時に「px--」とX座標方向
(水平方向)にポインタを逆進する!そしてX座標方向処理
は、「if(px>0){・・分岐中身・・}」は、
条件「px>0」と有効画素の場合で処理、その分岐中身は、
「if((px-1)==clr_dt){px=clr_dt;sw=TRUE;}」と
条件「(px-1)==clr_dt」で左隣「(px-1)」がクリアデータ
の場合は、「*px=clr_dt;sw=TRUE;」と注視点画素をクリア
し、スイッチをONにセット
「else」と左隣がクリアデータ以外ならば、
「p1=px-inc-1;c=*p1++;」で追跡点を左上側にセットし、
画素データ取り出し追跡点を上側に進行、
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で左上隣「c」が
クリア、スイッチをONにセット
データの場合は、「*px=clr_dt;」と注視点画素をクリア
「else」と左上隣がクリアデータ以外ならば、
「c=*p1++;」で上側画素データ取り出し追跡点を右上側に
進行、「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で
上隣「c」がクリアデータの場合は、「*px=clr_dt;」と
注視点画素をクリア、スイッチをONにセット
「else」と上隣がクリアデータ以外ならば、
「c=*p1;」で右上側画素データ取り出し、
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で右上隣「c」が
クリア、スイッチをONにセット
データの場合は、「*px=clr_dt;」と注視点画素をクリアと
X座標方向の内側ループを終えとスイッチON/OFF両方
の処理を終える事で正方向ラスタースキャンを終了!
今度は、暫く、逆方向ラスタースキャン≪外側ループと
してのY座標方向は下から、上に内側のX座標方向は右から
左へ≫を二重ループとし処理します!
「py=p+(v-1)*inc+h-1;」は、ラスタースキャン用のY座標
方向画像画素ポインタ()右下隅をセット
forループ「for(y=v;--y>=0;py-=inc){・
Y座標方向処理・}」は、
「y=v;--y>=0;py-=inc」で
「y=v;--y>=0;」とダウンカウント方式≪往々にしてこの
記載の方が、コンパイラに依って高速化処理コード生成≫で
垂直径「v」の回数繰り返す、ループ終了時に「py-=inc」と
Y座標方向(垂直方向)にポインタを進行する!そして
Y座標方向処理は、
「px=py;」は、ラスタースキャン用のX座標方向画像画素
ポインタをセット
「if(sw){・・ON時処理・・}else{・・OFF時処理・・
}」は、条件「sw」でON時処理は、
「for(x=h;--x>=0;px--){・X座標方向処理・}」は、
forループ「x=h;--x>=0;px--」で「x=h;--x>=0;」と
ダウンカウント方式≪往々にしてこの記載の方が、
コンパイラに依って高速化処理コード生成≫で水平径「h」
の回数繰り返す、ループ終了時に「px--」とX座標方向
(水平方向)にポインタを逆進する!そしてX座標方向処理
は、「if(px>0){・・分岐中身・・}」は、
条件「px>0」と有効画素の場合で処理、その分岐中身は、
「if((px+1)==clr_dt){px=clr_dt;}」と
条件「(px+1)==clr_dt」で右隣「(px+1)」がクリアデータ
の場合は、「*px=clr_dt;」と注視点画素をクリア
「else」と右隣がクリアデータ以外ならば、
「p1=px+inc-1;」で追跡点ポインタを左下にセットし、
「c=*p1++;」で左下画素データを取り出し、ポインタを下に
進行
「if(c==clr_dt){*px=clr_dt;}」で追跡点(左下)が
クリアデータなら「*px=clr_dt;」と注視点をクリア
「else{・・条件不成立・・」と追跡点(左下)がクリア
データ以外なら
「c=*p1++;」で下画素データを取り出し、ポインタを右下に
進行
「if(c==clr_dt){*px=clr_dt;}」で追跡点(下)がクリア
データなら「*px=clr_dt;」と注視点をクリア
「else{c=*p1;if(c==clr_dt){*px=clr_dt;}}」で
追跡点(下)がクリアデータ以外なら
「c=*p1;」で右下画素データを取り出し、
「if(c==clr_dt){*px=clr_dt;}」で追跡点(右下)が
クリアデータなら「*px=clr_dt;」と注視点をクリア
条件「sw」でOFF時処理は、
「for(x=h;--x>=0;px--){・X座標方向処理・}」は、
forループ「x=h;--x>=0;px--」で「x=h;--x>=0;」と
ダウンカウント方式≪往々にしてこの記載の方が、
コンパイラに依って高速化処理コード生成≫で水平径「h」
の回数繰り返す、ループ終了時に「px--」とX座標方向
(水平方向)にポインタを逆進する!そしてX座標方向処理
は、「if(px>0){・・分岐中身・・}」は、
条件「px>0」と有効画素の場合で処理、その分岐中身は、
「if((px+1)==clr_dt){px=clr_dt;sw=TRUE;}」と
条件「(px+1)==clr_dt」で右隣「(px+1)」がクリアデータ
の場合は、「*px=clr_dt;」と注視点画素をクリア
「else」と右隣がクリアデータ以外ならば、
「p1=px+inc-1;」で追跡点ポインタを左下にセットし、
「c=*p1++;」で左下画素データを取り出し、ポインタを下に
進行
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で追跡点(左下)
がクリアデータなら「*px=clr_dt;」と注視点をクリアし、
「sw=TRUE;」でとスィッチON
「else{・・条件不成立・・」と追跡点(左下)がクリア
データ以外なら
「c=*p1++;」で下画素データを取り出し、ポインタを右下に
進行
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で追跡点(下)が
クリアデータなら「*px=clr_dt;」と注視点をクリア、
「sw=TRUE;」でとスィッチON
「else{c=*p1;if(c==clr_dt){*px=clr_dt;sw=TRUE;}}」で
追跡点(下)がクリアデータ以外なら
「c=*p1;」で右下画素データを取り出し、
「if(c==clr_dt){*px=clr_dt;sw=TRUE;}」で追跡点(右下)
がクリアデータなら「*px=clr_dt;」と注視点をクリア、
「sw=TRUE;」でとスィッチON
ココで後半の逆進ラスタースキャンのfor2重ループを
終え
「p+=inc+1;」は、ラスタースキャンの始点をフェレ図形の
一回り内側のポインタにセット
「h-=2;v-=2;」は、処理する水平垂直の幅を一回り内側に
補正

(4-1)アルゴリズム概要

長々とアルゴリズムの文書での解説を辛抱強く読んで頂き
ありがとうございます!確認の為に概要とし、掻い摘んだ事
も記載します!
メインのwhileループ
「while(sw){・・最外側ループ・・}」での処理が、
画素変更スィッチ「int sw;」ループを処理するが、最初は
内部で「sw=FALSE;」にして正方向ラスタースキャン≪上か
ら下への外側ループと左から右への内側ループ※内側ループ
は、変更スィッチON時とOFF時2種有り≫で
変更スィッチONの時は、
4連結で注視点左隣・上隣が既にクリア済ならば、注視点を
クリアする処理で
変更スィッチOFFの時は、ONの時の処理に比べて注視点
をクリアすると同時に「sw =TRUE;」と変更スィッチをON
にする!
正方向ラスタースキャンの二重ループを終えると次は、
逆方向ラスタースキャン≪下から上への外側ループと
右から左への内側ループ※内側ループは、正方向と同じく
変更スィッチON時とOFF時2種有り≫で変更スィッチ
ONの時は、
8連結で注視点隣が既にクリア済ならば、注視点をクリア
する処理で変更スィッチOFFの時は、ONの時の処理に比
べて注視点をクリアすると同時に「sw =TRUE;」と変更
スィッチをONにする事で逆方向ラスタースキャンの
二重ループを終える!
事を詳細の「アルゴリズム」解説で読み取って下さい!
そして正方向・逆方向のラスタースキャンする画像範囲を
「p+=inc+1;h-=2;v-=2;」で一回り内側にしてメインの
whileループを実行する事と理解して下さい!
詰まり、ループ先頭で「sw=FALSE;」と変更スィッチOFF
にして居ますので内部で変更スィッチをONにする処置が
無ければ、ループを終了します!

フェレ計測での8連結の処理は、「search8fere()」と成り
ここまで説明しましたが、分量が多いので一旦、ここまでと
して続きの面積・一次モーメント・重心座標等の処理は、
次の『この仕事は天職だと感じたアルゴリズム開発(続4)
で説明します!

文末

いいなと思ったら応援しよう!