見出し画像

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

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


2024年12月16日初稿

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

1.図形の面積計測MeasureArea()

/************************************************************************/
/*****      図形の面積計測                      :計測部(面積専用)*****/
/*****  MEASURE_AREA(c,s,a,mh,mv,cx,cy)            *****/
/************************************************************************/

int             Filter::MeasureArea(
    int         c,                                  // 4/8連結
    TypeArray   *ps,                                // 画像
    TypeSf      buf[],                              // 計測結果Buffer
    int         lmt                                 // Buffer格納制限
){
    int         sti;                                // ステータス情報

    sti = CheckAndClearRoundImage( ps );            // 画像検査&周囲CLR
    if( sti < 0 ){                                  // 不正が有れば
        return( sti );                              // Statusを返す
    }                                               //
    return( measureBase_area( c, ps, buf, lmt ) );  // 面積を計測
}

(1)関数名

「Measure」は、「計測」でココでは、計測を意味
「Area」は、「面積」を意味
だから、「MeasureArea」で面積計測を実際に実行する
を意味します!

(2)仮引数

int             Filter::MeasureFere(
    int         c,                                  // 4/8連結
    TypeArray   *ps,                                // 画像
    TypeSf      buf[],                              // 計測結果Buffer
    int         lmt                                 // Buffer格納制限
){

「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「TypeArray* ps,」は、計測対象の2値化画像、
「TypeSf buf[],」は、計測結果バッファーで型「TypeSf」
解説『解説クラスTypeSf』を参考にして下さい!
「int lmt」は、バッファーサイズ≪lmt名称は、格納制限
とし、この制限値まで計測し、実際に図形がオーバーする
場合は、計測を打ち切ります!≫
※備考※オーバーロード(多重定義)関数として仮引数の
数と型が異なる関数が存在します!

(3)ローカル変数数

){
    int         sti;                                // ステータス情報

「int sti;」は、ステータス情報(エラーコード)

(4)アルゴリズム

    sti = CheckAndClearRoundImage( ps );            // 画像検査&周囲CLR
    if( sti < 0 ){                                  // 不正が有れば
        return( sti );                              // Statusを返す
    }                                               //
    return( measureBase_area( c, ps, buf, lmt ) );  // 面積を計測
}

「sti=CheckAndClearRoundImage(ps);」は、画像「ps」の
検査≪規定通り1バイトの2値化画像のサイズを満足して居
るか如何か≫し、合格ならば、画像の外周一回りクリアする
※備考※外周一回りクリアするので必要な画素が有る場合は
部分画像をコピーする等、工夫して使用して下さい!
「if(sti<0){return(sti);}」は、検査でエラー発生時は、
エラーコードを関数辺値とし返し終了!
「return(measureBase_area(c,ps,buf,lmt));」は、
下請け関数「measureBase_area(c,ps,buf,lmt)」で
フェレ計測の基本的な処理を行い、その関数辺値を返し終了
※備考※
この、MeasureArea()関数の方が、C言語から使用する場合は
便利な筈です!

2.面積計測:処理部measureBase_area()

/************************************************************************/
/*****      図形のフェレ計測+面積計測:処理部                      *****/
/*****  MEASURE_AREA(c,s,a)                        *****/
/*****  ※注:フェレ計測と面積を計測します。モーメントはしません。  *****/
/*****  ※注:結果が buf_lmt個までは、バッファーに格納しますがそれ  *****/
/*****       以上ある場合は、バッファーの buf_lmt + 1 個目を更新す *****/
/*****       るのみです。                                          *****/
/************************************************************************/

int             Filter::measureBase_area(
    int         c,                                          // 4/8連結
    TypeArray   *ps,                                        // 画像
    TypeSf      *buf,                                       // 計測結果Buffer
    int         buf_lmt                                     // Buffer格納制限
){
    char        **bufptr;                                   // 追跡点履歴Buffer
    int         dir_off[ 8 ];                               // 方向OffSetTable
    char        *px;                                        // x方向処理Ptr
    char        *py;                                        // y方向処理Ptr
    int         h;                                          // 処理水平幅
    int         v;                                          // 処理垂直幅
    int         inc;                                        // 処理インクリ幅
    int         x;                                          // x座標カウンタ
    int         y;                                          // y座標カウンタ
    int         n;                                          // 計測個数
    int         size;                                       // 履歴Bufferサイズ

    size   = BORDERSIZE;                                    // 履歴BufferSize初期値
    bufptr = (char**)malloc( sizeof(char*) * size );        // 履歴Buffer取得
    if( bufptr == 0 ){                                      // 失敗時は
        return( STI_MEM );                                  // 左記を返し終了
    }                                                       // 
    py  = (char*)ps->adr;                                   // 処理ADRを取出し
    h   = ps->h - 2;                                        // 水平幅-2を算出
    v   = ps->v - 2;                                        // 垂直幅-2を算出
    inc = ps->inc;                                          // 処理Inc幅取出
    py += inc + 1;                                          // 座標(1,1)にセット
    SetDirOffset( c, dir_off, inc );                        // 方向OffSetTblSet
    n = 0;                                                  // 個数初期化
    for( y = 1; y <= v; y++, py += inc ){                   // 垂直処理幅分繰返
        px = py;                                            // 水平処理始点Setし
        for( x = 1; x <= h; x++, px++ ){                    // 水平方向繰り返し
            if( *px > 0 ){                                  // 画素を発見したら
                if( c == 4 ){                               // 4連結なら
                    bufptr = search4fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }else{                                      // 8連結なら
                    bufptr = search8fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }                                           //
                if( bufptr == 0 ){                          // 上記でメモリ確保失敗時は
                    return( STI_MEM );                      // 左記を返し終了
                }                                           // 
                search_area( px - x + buf->x, buf, inc );   // 個別の面積計測
                n++;                                        // 個数を更新
                if( n <= buf_lmt ){                         // buf_lmt以下なら
                    buf++;                                  // 結果バッファ更新
                }else{                                      // Overなら
                    free( bufptr );                         // 履歴Buffer解放し
                    return( n );                            // 個数を返す
                }                                           //
            }                                               //
        }                                                   //
    }                                                       //
    free( bufptr );                                         // 履歴Buffer解放
    return( n );                                            // 個数を返す
}

(1)関数名

「measure」は、「計測」でココでは、計測を意味
「Base」は、「基本部」を意味
「area」は、「面積計測」を意味
だから、「measureBase_area」でフェレ計測内の面積計測を
実際に実行する基本部を意味します!

(2)仮引数

int             Filter::measureBase_area(
    int         c,                                          // 4/8連結
    TypeArray   *ps,                                        // 画像
    TypeSf      *buf,                                       // 計測結果Buffer
    int         buf_lmt                                     // Buffer格納制限
){

「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「TypeArray* ps,」は、計測対象の2値化画像、
「TypeSf buf[],」は、計測結果バッファーで型「TypeSf」
解説『解説クラスTypeSf』を参考にして下さい!
「int buf_lmt」は、バッファーサイズ≪lmt名称は、格納
制限とし、この制限値まで計測し、実際に図形がオーバー
する場合は、計測を打ち切ります!≫
※備考※オーバーロード(多重定義)関数として仮引数の
数と型が異なる関数が存在します!

(3)ローカル変数

){
    char        **bufptr;                                   // 追跡点履歴Buffer
    int         dir_off[ 8 ];                               // 方向OffSetTable
    char        *px;                                        // x方向処理Ptr
    char        *py;                                        // y方向処理Ptr
    int         h;                                          // 処理水平幅
    int         v;                                          // 処理垂直幅
    int         inc;                                        // 処理インクリ幅
    int         x;                                          // x座標カウンタ
    int         y;                                          // y座標カウンタ
    int         n;                                          // 計測個数
    int         size;                                       // 履歴Bufferサイズ

「char** bufptr;」は、追跡点履歴バッファー≪輪郭サーチ
を行った画素の場所「char*」型でポイントをバッファーに
格納する為のバッファー≫
「int dir_off[8];」は、方向オフセットテーブル≪輪郭
サーチ用の次の画素ポインタへのオフセットを格納した
テーブル≫
「char* px;」は、X座標方向画像画素ポインタ≪ラスター
スキャン用≫
「char* py;」は、Y座標方向画像画素ポインタ≪ラスター
スキャン用≫
「int h;」は、水平幅≪画像の水平幅より、外周一回りを
クリアして居るので内側の水平幅≫
「int v;」は、垂直幅≪画像の垂直幅より、外周一回りを
クリアして居るので内側の垂直幅≫
「int inc;」は、画像の増加幅≪画像の垂直方向への進行用

「int x;」は、X座標≪画像を直交XY座標として≫
「int y;」は、Y標≪画像を直交XY座標として≫
「int n;」は、計測個数
「int size;」は、追跡点履歴バッファーのサイズ

(4)関連定義

#define     BORDERSIZE  100000          // 輪郭バッファーのサイズ

「BORDERSIZE」は、「100000」を意味します!
※備考※連結した塊としての図形としては、実用性として
輪郭サーチの輪郭が連結≪4連結・8連結≫での画素数とし
ては、十分と考えましたが、初期値のサイズでもし、想定
以上に輪郭がツナガル画素が遇った場合は、サイズを更新
出来る仕組みを用意しています!

(5)アルゴリズム

    size   = BORDERSIZE;                                    // 履歴BufferSize初期値
    bufptr = (char**)malloc( sizeof(char*) * size );        // 履歴Buffer取得
    if( bufptr == 0 ){                                      // 失敗時は
        return( STI_MEM );                                  // 左記を返し終了
    }                                                       // 
    py  = (char*)ps->adr;                                   // 処理ADRを取出し
    h   = ps->h - 2;                                        // 水平幅-2を算出
    v   = ps->v - 2;                                        // 垂直幅-2を算出
    inc = ps->inc;                                          // 処理Inc幅取出
    py += inc + 1;                                          // 座標(1,1)にセット
    SetDirOffset( c, dir_off, inc );                        // 方向OffSetTblSet
    n = 0;                                                  // 個数初期化
    for( y = 1; y <= v; y++, py += inc ){                   // 垂直処理幅分繰返
        px = py;                                            // 水平処理始点Setし
        for( x = 1; x <= h; x++, px++ ){                    // 水平方向繰り返し
            if( *px > 0 ){                                  // 画素を発見したら
                if( c == 4 ){                               // 4連結なら
                    bufptr = search4fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }else{                                      // 8連結なら
                    bufptr = search8fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }                                           //
                if( bufptr == 0 ){                          // 上記でメモリ確保失敗時は
                    return( STI_MEM );                      // 左記を返し終了
                }                                           // 
                search_area( px - x + buf->x, buf, inc );   // 個別の面積計測
                n++;                                        // 個数を更新
                if( n <= buf_lmt ){                         // buf_lmt以下なら
                    buf++;                                  // 結果バッファ更新
                }else{                                      // Overなら
                    free( bufptr );                         // 履歴Buffer解放し
                    return( n );                            // 個数を返す
                }                                           //
            }                                               //
        }                                                   //
    }                                                       //
    free( bufptr );                                         // 履歴Buffer解放
    return( n );                                            // 個数を返す
}

「size=BORDERSIZE;」は、輪郭サーチサイズの初期値セット
「bufptr=(char**)malloc(sizeof(char*)size);」は、輪郭
サーチして「char」と画像画素へのポインタをバッファー
に格納する為のバッファーを動的にメモリ確保
「if(bufptr==0){return(STI_MEM);}」は、メモリ確保に
失敗したらエラーコード「STI_MEM」を関数辺値とし返し
終了!
「py=(char*)ps->adr;」は、Y座標方向画像画素ポインタを
画像画素ポインタ始点(左上隅)にセット
「h=ps->h-2;v=ps->v-2;」は、画像「TypeArray* ps,」の
一回り内側の水平幅・垂直幅を「int h;int v;」にセット
「inc=ps->inc;」は、垂直方向増加幅をセット
「py+=inc+1;」は、Y座標方向画像画素ポインタをラスター
スキャンの始点≪一回り内側なのでXY座標(1,1)≫として
セット
「SetDirOffset(c,dir_off,inc);」は、方向オフセット
テーブルにオフセット値を作成する
「n=0;」は、図形の個数を初期化
「for(y=1;y<=v;y++,py+=inc){・・垂直方向・・}」は、
画像画素をラスタースキャンとして処理する垂直方向の
forループです、教科書的な「y=1;y<=v;y++,」とY座標を
「1・・v」まで繰り返し、ループ最後に「py+=inc」と
Y座標方向画像画素ポインタを垂直方向に進行し、
「・・垂直方向・・」と垂直方向の処理を行う、その処理は
「px=py;」でX座標方向画像画素ポインタをセット、
「for(x=1;x<=h;x++,px++){・・水平方向・・}」で
画像画素をラスタースキャンとして処理する水平方向の
forループです、教科書的な「x=1;x<=h;x++,」とX座標を
「1・・h」まで繰り返し、ループ最後に「px++」とX座標
方向画像画素ポインタを水平方向に進行し、
「if(*px>0){・・輪郭サーチ方向・・}」で条件「*px>0」で
有効な画素≪「0」を超える正の値≫の場合は、輪郭サーチ
方向に処理し、その処理の中で
「if(c==4){bufptr=search4fere(bufptr,px,x,y,buf,
dir_off,-1,size);}」で条件「c==4」詰まり、4連結時は、
下請け関数「bufptr=search4fere(bufptr,px,x,y,buf,
dir_off,-1,size);」と処理し、
「else{bufptr=search8fere(bufptr,px,x,y,buf,dir_off,
-1,size);}」で「else」と4連結以外≒8連結として下請け
関数「bufptr=search8fere(bufptr,px,x,y,buf,dir_off,-1,
size);}」で処理
「if(bufptr==0){return(STI_MEM);}」は、下請け関数「
search4fere()及び、search8fere()」内で輪郭サーチ用の
バッファーを大きなサイズに再メモリ確保≪一旦、新しい
バッファーを確保し、元のデータをコピーし、余裕がある
バッファーとし使用するが、メモリ確保に失敗した場合は、
空ポインタ(=0の値)で返るのでエラーと成る≫に失敗し
たら、らエラーコード「STI_MEM」を関数辺値とし返し終了
「search_area(px-x+buf->x,buf,inc);」は、下請け関数
「search_area()」で図形個別の面積計測を行います、
「px-x+buf->x」で図形のフェレ始点を算出する事に注意し
て下さい!
※備考※この「search_area(px-x+buf->x,buf,inc);」の部分
が図形のフェレ計測:処理部「measureBase_fere()」と異な
る部分です!「measureBase_fere()」は「search_area()」
を呼び出さ無いだけ処理時間が短く成るから存在します!
ここの「measureBase_area()」は、フェレ計測に加えて面積
も計測出来る事が特徴です!
「n++;」は、図形≪連結した塊≫の計測が完了したので個数
を増加する!
「if(n<=buf_lmt){buf++;}」は、条件「n<=buf_lmt」で
図形計測バッファーのサイズの制限値を超えて無い場合を
示し「buf++;」格納する場所を示すポインタを進める
「else{free(bufptr);return(n);}」は、バッファーの
サイズの制限値を超えたので「free(bufptr);」で確保した
動的にメモリをOSに返し、「return(n);」で制限値を超え
たまでの個数を関数辺値とし返し終了
そして全てのループが終了すると
「free(bufptr);」は、確保した動的にメモリをOSに返し
「return(n);」は、計測した図形の個数を関数辺値とし返し
終了

3.図形の面積計測:search_area()

/************************************************************************/
/*****      図形の面積計測:※面積選択用※                          *****/
/*****  フェレ径を求めた図形に対して処理します                      *****/
/*****  ※注意※    面積の前準備としてフェレ径を求めるのと同時に    *****/
/*****              対象図形を「-2」の画素にしておく                *****/
/*****  ※注意※    対象図形は、計測済みを示す「-1」にします。      *****/
/************************************************************************/

void            Filter::search_area(
    char        *py,                                // フェレ始点Ptr
    TypeSf      *buf,                               // 計測結果Buffer
    int         inc                                 // インクリ幅
){
    char        *px;                                // 追跡点:水平方向
    int         h;                                  // 水平処理幅
    int         v;                                  // 垂直処理幅
    int         x;                                  // 水平方向カウンタ
    int         a;                                  // 面積データ

    h    = buf->h;                                  // 水平処理幅取出し
    v    = buf->v;                                  // 垂直処理幅取出し
    a    = 0;                                       // 面積Data初期化
    for( ; --v >= 0; py += inc ){                   // 垂直処理幅分繰返
        px = py;                                    // 水平処理始点Setし
        for( x = h; --x >= 0; px++ ){               // 水平方向繰り返し
            if( *px == -2 ){                        // 対象画素なら
                *px = -1;                           // 計測済みをセット
                a++;                                // 面積カウントUp
            }                                       //
        }                                           //
    }                                               //
    buf->a = a;                                     // 面積を格納
}

(1)関数名

「search」は、カタカナ語「サーチ」でココでは、図形を
サーチする意味
「area」は、「面積計測」を意味
だから、「search_area」で図形≪4及び8連結の塊≫の
面積を計測するを意味します!

(2)仮引数

void            Filter::search_area(
    char        *py,                                // フェレ始点Ptr
    TypeSf      *buf,                               // 計測結果Buffer
    int         inc                                 // インクリ幅
){

「char* py,」は、フェレ計測始点の画像画素ポインタ
「TypeSf* buf,」は、計測結果バッファーを示すポインタ
「int inc」は、画像の増加幅≪画像の垂直方向への進行用

(3)ローカル変数

){
    char        *px;                                // 追跡点:水平方向
    int         h;                                  // 水平処理幅
    int         v;                                  // 垂直処理幅
    int         x;                                  // 水平方向カウンタ
    int         a;                                  // 面積データ

「char* px;」は、ラスタースキャンX座標方向追跡点
「int h;」は、水平幅≪X座標方向処理幅≫
「int v;」は、垂直幅≪Y座標方向処理幅≫
「int x,」は、X座標方向処理カウンター
「int a;」は、面積≪画素数≫

(4)アルゴリズム

    h    = buf->h;                                  // 水平処理幅取出し
    v    = buf->v;                                  // 垂直処理幅取出し
    a    = 0;                                       // 面積Data初期化
    for( ; --v >= 0; py += inc ){                   // 垂直処理幅分繰返
        px = py;                                    // 水平処理始点Setし
        for( x = h; --x >= 0; px++ ){               // 水平方向繰り返し
            if( *px == -2 ){                        // 対象画素なら
                *px = -1;                           // 計測済みをセット
                a++;                                // 面積カウントUp
            }                                       //
        }                                           //
    }                                               //
    buf->a = a;                                     // 面積を格納
}

「h=buf->h;v=buf->v;」は、図形の水平垂直幅を取り出し、
「a=0;」は、面積≪画素数≫データを初期化
「for(;--v>=0;py+=inc){・・ループ中身・・}」は、
forループ「;--v>=0;py+=inc」と初期化無しで
ループ条件「--v>=0;」と垂直幅分繰り返し、ループの終わ
りに「py+=inc」と垂直(Y座標)方向処理ポインタを垂直
方向に進めるで、ループ中身が
「px=py;」は、水平方向(X座標)追跡点を初期化し
「for(x=h;--x>=0;px++){if(*px==-2){*px=-1;a++;}}」は、
forループ「x=h;--x>=0;px++」で水平幅(X座標方向幅
)分繰り返し、ループの終わりに「px++」と追跡点を進め、
「if(*px==-2){*px=-1;a++;}」で条件「*px==-2」と追跡点
が「-2」≪search4fere()或はsearch8fere()関数で目印とし
てこれらの関数の仮引数「int clr_dt,」に「-2」を設定し
て画像画素を無効化「負の数」した意味とsearch_area()等
の継続して計測する処理の為の計測対象目印にして居る≫
ので面積計測対象と見なして「*px=-1;a++;」と
「*px=-1;」で計測処理も終了をセットし、「a++;」で面積
をカウントアップ
正方向≪上から下、左から右≫ラスタースキャンの二重ルー
プを終えると
「buf->a=a;」は、画素数を図形面積として計測結果へ格納

4.図形の面積計測MeasureMmt1()

/************************************************************************/
/*****      図形の面積計測          :計測部(面積+1次モーメント)*****/
/*****  MEASURE_AREA(c,s,a,mh,mv,cx,cy)            *****/
/************************************************************************/

int             Filter::MeasureMmt1(
    int         c,                                  // 4/8連結
    TypeArray   *ps,                                // 画像
    TypeSf      buf[],                              // 計測結果Buffer
    int         lmt                                 // Buffer格納制限
){
    int         sti;                                // ステータス情報

    sti = CheckAndClearRoundImage( ps );            // 画像検査&周囲CLR
    if( sti < 0 ){                                  // 不正が有れば
        return( sti );                              // Statusを返す
    }                                               //
    return( measureBase_mmt1( c, ps, buf, lmt ) );  // 左記で計測する
}

(1)関数名

「Measure」は、「計測」でココでは、計測を意味
「Mmt」は、「モーメント」を意味
「1」は、「1次」を意味し、「Mmt1」で一次モーメントで
だから、「MeasureMmt1」で一次モーメント系計測を実際に
実行するを意味します!

(2)仮引数

int             Filter::MeasureMmt1(
    int         c,                                  // 4/8連結
    TypeArray   *ps,                                // 画像
    TypeSf      buf[],                              // 計測結果Buffer
    int         lmt                                 // Buffer格納制限
){

「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「TypeArray* ps,」は、計測対象の2値化画像、
「TypeSf buf[],」は、計測結果バッファーで型「TypeSf」
解説『解説クラスTypeSf』を参考にして下さい!
「int lmt」は、バッファーサイズ≪lmt名称は、格納制限
とし、この制限値まで計測し、実際に図形がオーバーする
場合は、計測を打ち切ります!≫
※備考※オーバーロード(多重定義)関数として仮引数の
数と型が異なる関数が存在します!

(3)ローカル変数

){
    int         sti;                                // ステータス情報

「int sti;」は、ステータス情報(エラーコード)

(4)アルゴリズム

    sti = CheckAndClearRoundImage( ps );            // 画像検査&周囲CLR
    if( sti < 0 ){                                  // 不正が有れば
        return( sti );                              // Statusを返す
    }                                               //
    return( measureBase_mmt1( c, ps, buf, lmt ) );  // 左記で計測する
}

「sti=CheckAndClearRoundImage(ps);」は、画像「ps」の
検査≪規定通り1バイトの2値化画像のサイズを満足して居
るか如何か≫し、合格ならば、画像の外周一回りクリアする
※備考※外周一回りクリアするので必要な画素が有る場合は
部分画像をコピーする等、工夫して使用して下さい!
「if(sti<0){return(sti);}」は、検査でエラー発生時は、
エラーコードを関数辺値とし返し終了!
「return(measureBase_area(c,ps,buf,lmt));」は、
下請け関数「measureBase_mmt1(c,ps,buf,lmt)」で
フェレ計測内モーメント系の基本的な処理を行い、
その関数辺値を返し終了
※備考※
この、MeasureMmt1()関数の方が、C言語から使用する場合は便利な筈です!

5.モーメント系計測:処理部

measureBase_mmt1()

/************************************************************************/
/*****      図形のフェレ計測+面積計測+1次モーメント:処理部      *****/
/*****  MEASURE_AREA(c,s,a,mh,mv)                  *****/
/*****  ※注:フェレ計測と面積と1次モーメントを計測します。        *****/
/*****  ※注:結果が buf_lmt個までは、バッファーに格納しますがそれ  *****/
/*****       以上ある場合は、バッファーの buf_lmt + 1 個目を更新す *****/
/*****       るのみです。                                          *****/
/************************************************************************/

int             Filter::measureBase_mmt1(
    int         c,                                          // 4/8連結
    TypeArray   *ps,                                        // 画像
    TypeSf      *buf,                                       // 計測結果Buffer
    int         buf_lmt                                     // Buffer格納制限
){
    char        **bufptr;                                   // 追跡点履歴Buffer
    int         dir_off[ 8 ];                               // 方向OffSetTable
    char        *px;                                        // x方向処理Ptr
    char        *py;                                        // y方向処理Ptr
    int         h;                                          // 処理水平幅
    int         v;                                          // 処理垂直幅
    int         inc;                                        // 処理インクリ幅
    int         x;                                          // x座標カウンタ
    int         y;                                          // y座標カウンタ
    int         n;                                          // 計測個数
    int         size;                                       // 履歴Bufferサイズ

    size   = BORDERSIZE;                                    // 履歴BufferSize初期値
    bufptr = (char**)malloc( sizeof(char*) * size );        // 履歴Buffer取得
    if( bufptr == 0 ){                                      // 失敗時は
        return( STI_MEM );                                  // 左記を返し終了
    }                                                       // 
    py  = (char*)ps->adr;                                   // 処理ADRを取出し
    h   = ps->h - 2;                                        // 水平幅-2を算出
    v   = ps->v - 2;                                        // 垂直幅-2を算出
    inc = ps->inc;                                          // 処理Inc幅取出
    py += inc + 1;                                          // 座標(1,1)にセット
    SetDirOffset( c, dir_off, inc );                        // 方向OffSetTblSet
    n = 0;                                                  // 個数初期化
    for( y = 1; y <= v; y++, py += inc ){                   // 垂直処理幅分繰返
        px = py;                                            // 水平処理始点Setし
        for( x = 1; x <= h; x++, px++ ){                    // 水平方向繰り返し
            if( *px > 0 ){                                  // 画素を発見したら
                if( c == 4 ){                               // 4連結なら
                    bufptr = search4fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }else{                                      // 8連結なら
                    bufptr = search8fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }                                           //
                if( bufptr == 0 ){                          // 上記でメモリ確保失敗時は
                    return( STI_MEM );                      // 左記を返し終了
                }                                           // 
                search_mmt1( px - x + buf->x, buf, inc );   // 面積+1次Momentを計測
                n++;                                        // 個数を更新
                if( n <= buf_lmt ){                         // buf_lmt以下なら
                    buf++;                                  // 結果バッファ更新
                }else{                                      // Overなら
                    free( bufptr );                         // 履歴Buffer解放し
                    return( n );                            // 個数を返す
                }                                           //
            }                                               //
        }                                                   //
    }                                                       //
    free( bufptr );                                         // 履歴Buffer解放
    return( n );                                            // 個数を返す
}

(1)関数名

code:
「measure」は、「計測」でココでは、計測を意味
「Base」は、「基本部」を意味
「mmt」は、「モーメント」を意味
「1」は、「1次」を意味し、「Mmt1」で一次モーメントで
だから、「mmt1」で一次モーメント系計測を実際に
実行するを意味します!
だから、「measureBase_mmt1」でフェレ計測した範囲で
モーメント系計測を実際に実行する基本部を意味します!

(2)仮引数

int             Filter::measureBase_mmt1(
    int         c,                                          // 4/8連結
    TypeArray   *ps,                                        // 画像
    TypeSf      *buf,                                       // 計測結果Buffer
    int         buf_lmt                                     // Buffer格納制限
){

「int c,」は、連結性≪「4」で4連結、「8」で8連結≫
「TypeArray* ps,」は、計測対象の2値化画像、
「TypeSf buf[],」は、計測結果バッファーで型「TypeSf」
は解説『解説クラスTypeSf』を参考にして下さい!
「int buf_lmt」は、バッファーサイズ≪lmt名称は、格納
制限とし、この制限値まで計測し、実際に図形がオーバー
する場合は、計測を打ち切ります!≫
※備考※オーバーロード(多重定義)関数として仮引数の
数と型が異なる関数が存在します!

(3)ローカル変数

){
    char        **bufptr;                                   // 追跡点履歴Buffer
    int         dir_off[ 8 ];                               // 方向OffSetTable
    char        *px;                                        // x方向処理Ptr
    char        *py;                                        // y方向処理Ptr
    int         h;                                          // 処理水平幅
    int         v;                                          // 処理垂直幅
    int         inc;                                        // 処理インクリ幅
    int         x;                                          // x座標カウンタ
    int         y;                                          // y座標カウンタ
    int         n;                                          // 計測個数
    int         size;                                       // 履歴Bufferサイズ

「char** bufptr;」は、追跡点履歴バッファー≪輪郭サーチ
を行った画素の場所「char*」型でポイントをバッファーに
格納する為のバッファー≫
「int dir_off[8];」は、方向オフセットテーブル≪輪郭
サーチ用の次の画素ポインタへのオフセットを格納した
テーブル≫
「char* px;」は、X座標方向画像画素ポインタ≪ラスター
スキャン用≫
「char* py;」は、Y座標方向画像画素ポインタ≪ラスター
スキャン用≫
「int h;」は、水平幅≪画像の水平幅より、外周一回りを
クリアして居るので内側の水平幅≫
「int v;」は、垂直幅≪画像の垂直幅より、外周一回りを
クリアして居るので内側の垂直幅≫
「int inc;」は、画像の増加幅≪画像の垂直方向への進行用

「int x;」は、X座標≪画像を直交XY座標として≫
「int y;」は、Y標≪画像を直交XY座標として≫
「int n;」は、計測個数
「int size;」は、追跡点履歴バッファーのサイズ

(4)関連定義

#define     BORDERSIZE  100000          // 輪郭バッファーのサイズ

「BORDERSIZE」は、「100000」を意味します!
※備考※連結した塊としての図形としては、実用性として
輪郭サーチの輪郭が連結≪4連結・8連結≫での画素数とし
ては、十分と考えましたが、初期値のサイズでもし、想定
以上に輪郭がツナガル画素が遇った場合は、サイズを更新
出来る仕組みを用意しています!

(5)アルゴリズム

    size   = BORDERSIZE;                                    // 履歴BufferSize初期値
    bufptr = (char**)malloc( sizeof(char*) * size );        // 履歴Buffer取得
    if( bufptr == 0 ){                                      // 失敗時は
        return( STI_MEM );                                  // 左記を返し終了
    }                                                       // 
    py  = (char*)ps->adr;                                   // 処理ADRを取出し
    h   = ps->h - 2;                                        // 水平幅-2を算出
    v   = ps->v - 2;                                        // 垂直幅-2を算出
    inc = ps->inc;                                          // 処理Inc幅取出
    py += inc + 1;                                          // 座標(1,1)にセット
    SetDirOffset( c, dir_off, inc );                        // 方向OffSetTblSet
    n = 0;                                                  // 個数初期化
    for( y = 1; y <= v; y++, py += inc ){                   // 垂直処理幅分繰返
        px = py;                                            // 水平処理始点Setし
        for( x = 1; x <= h; x++, px++ ){                    // 水平方向繰り返し
            if( *px > 0 ){                                  // 画素を発見したら
                if( c == 4 ){                               // 4連結なら
                    bufptr = search4fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }else{                                      // 8連結なら
                    bufptr = search8fere( bufptr, px, x, y, // 個別のフェレ計測
                                buf, dir_off, -2, size );   //
                }                                           //
                if( bufptr == 0 ){                          // 上記でメモリ確保失敗時は
                    return( STI_MEM );                      // 左記を返し終了
                }                                           // 
                search_mmt1( px - x + buf->x, buf, inc );   // 面積+1次Momentを計測
                n++;                                        // 個数を更新
                if( n <= buf_lmt ){                         // buf_lmt以下なら
                    buf++;                                  // 結果バッファ更新
                }else{                                      // Overなら
                    free( bufptr );                         // 履歴Buffer解放し
                    return( n );                            // 個数を返す
                }                                           //
            }                                               //
        }                                                   //
    }                                                       //
    free( bufptr );                                         // 履歴Buffer解放
    return( n );                                            // 個数を返す
}

「size=BORDERSIZE;」は、輪郭サーチサイズの初期値セット
「bufptr=(char**)malloc(sizeof(char*)size);」は、輪郭サーチして「char」と画像画素へのポインタをバッファーに格納
する為のバッファーを動的にメモリ確保
「if(bufptr==0){return(STI_MEM);}」は、メモリ確保に
失敗したらエラーコード「STI_MEM」を関数辺値とし返し
終了!
「py=(char*)ps->adr;」は、Y座標方向画像画素ポインタを
画像画素ポインタ始点(左上隅)にセット
「h=ps->h-2;v=ps->v-2;」は、画像「TypeArray* ps,」の
一回り内側の水平幅・垂直幅を「int h;int v;」にセット
「inc=ps->inc;」は、垂直方向増加幅をセット
「py+=inc+1;」は、Y座標方向画像画素ポインタをラスター
スキャンの始点≪一回り内側なのでXY座標(1,1)≫として
セット
「SetDirOffset(c,dir_off,inc);」は、方向オフセット
テーブルにオフセット値を作成する
「n=0;」は、図形の個数を初期化
「for(y=1;y<=v;y++,py+=inc){・・垂直方向・・}」は、
画像画素をラスタースキャンとして処理する垂直方向の
forループです、教科書的な「y=1;y<=v;y++,」とY座標を
「1・・v」まで繰り返し、ループ最後に「py+=inc」と
Y座標方向画像画素ポインタを垂直方向に進行し、
「・・垂直方向・・」と垂直方向の処理を行う、その処理は
「px=py;」でX座標方向画像画素ポインタをセット、
「for(x=1;x<=h;x++,px++){・・水平方向・・}」で
画像画素をラスタースキャンとして処理する水平方向の
forループです、教科書的な「x=1;x<=h;x++,」とX座標を
「1・・h」まで繰り返し、ループ最後に「px++」とX座標
方向画像画素ポインタを水平方向に進行し、
「if(*px>0){・・輪郭サーチ方向・・}」で条件「*px>0」で
有効な画素≪「0」を超える正の値≫の場合は、輪郭サーチ
方向に処理し、その処理の中で
「if(c==4){bufptr=search4fere(bufptr,px,x,y,buf,
dir_off,-1,size);}」で条件「c==4」詰まり、4連結時は、
下請け関数「bufptr=search4fere(bufptr,px,x,y,buf,
dir_off,-1,size);」と処理し、
「else{bufptr=search8fere(bufptr,px,x,y,buf,dir_off,
-1,size);}」で「else」と4連結以外≒8連結として下請け
関数「bufptr=search8fere(bufptr,px,x,y,buf,dir_off,-1,
size);}」で処理
「if(bufptr==0){return(STI_MEM);}」は、下請け関数「
search4fere()及び、search8fere()」内で輪郭サーチ用の
バッファーを大きなサイズに再メモリ確保≪一旦、新しい
バッファーを確保し、元のデータをコピーし、余裕がある
バッファーとし使用するが、メモリ確保に失敗した場合は、
空ポインタ(=0の値)で返るのでエラーと成る≫に失敗し
たら、らエラーコード「STI_MEM」を関数辺値とし返し終了
「search_mmt1(px-x+buf->x,buf,inc);」は、下請け関数
「search_mmt1()」で図形個別の面積計測を行います、
※備考※この「search_mmt1(px-x+buf->x,buf,inc);」の部分
が図形のフェレ計測:処理部「measureBase_fere()」と異な
る部分です!「measureBase_fere()」は「search_mmt1()」
を呼び出さ無いだけ処理時間が短く成るから存在します!
ここの「measureBase_mmt1()」は、フェレ計測に加えて
一次モーメント系の計測も計測出来る事が特徴です!
「px-x+buf->x」で図形のフェレ始点を算出する事に注意し
て下さい!
「n++;」は、図形≪連結した塊≫の計測が完了したので個数
を増加する!
「if(n<=buf_lmt){buf++;}」は、条件「n<=buf_lmt」で
図形計測バッファーのサイズの制限値を超えて無い場合を
示し「buf++;」格納する場所を示すポインタを進める
「else{free(bufptr);return(n);}」は、バッファーの
サイズの制限値を超えたので「free(bufptr);」で確保した
動的にメモリをOSに返し、「return(n);」で制限値を超え
たまでの個数を関数辺値とし返し終了
そして全てのループが終了すると
「free(bufptr);」は、確保した動的にメモリをOSに返し
「return(n);」は、計測した図形の個数を関数辺値とし返し
終了

6.図形の面積計測:search_mmt1()

/************************************************************************/
/*****      図形の面積計測+水平垂直の1次モーメントの計測          *****/
/*****  フェレ径を求めた図形に対して処理します                      *****/
/*****  ※注意※    面積の前準備としてフェレ径を求めるのと同時に    *****/
/*****              対象図形を「-2」の画素にしておく                *****/
/*****  ※注意※    1次モーメントは、フェレ始点を座標(0,0)と  *****/
/*****              した相対値で算出します。                        *****/
/*****  ※注意※    垂直モーメントは、水平方向の面積×y座標をΣ    *****/
/*****  ※注意※    対象図形は、計測済みを示す「-1」にします。      *****/
/************************************************************************/

void            Filter::search_mmt1(
    char        *py,                                // フェレ始点Ptr
    TypeSf      *buf,                               // 計測結果Buffer
    int         inc                                 // インクリ幅
){
    char        *pend;                              // 追跡点:終点
    char        *px;                                // 追跡点:水平方向
    int         h;                                  // 水平処理幅
    int         x;                                  // x座標
    int         y;                                  // y座標
    int         a;                                  // 面積データ
    int         ax;                                 // 面積Data:x方向
    int         mhx;                                // 1次水平MMTx方向
    double      mh;                                 // 1次水平MomentData
    double      mv;                                 // 1次垂直MomentData

    h    = buf->h;                                  // 水平処理幅取出し
    a    = 0;                                       // 面積Data初期化
    mh   = 0.0;                                     // 水平Data初期化
    mv   = 0.0;                                     // 垂直Data初期化
    pend = py + buf->v * inc;                       // 終点を算出
    for( y = 1; py < pend; y++, py += inc ){        // 垂直処理幅分繰返
        px  = py;                                   // 水平処理始点Setし
        ax  = 0;                                    // 面積Data初期化
        mhx = 0;                                    // 水平MMTData初期化
        x   = 1;                                    // x座標初期化
        while( *px != -2 ){                         // 最初の有効画素を
            px++;                                   // 探しPtrと座標を
            x++;                                    // 進める
        }                                           //
        while( *px == -2 ){                         // 画素有効な間
            *px++ = -1;                             // 計測済みセットしptrを進め
            ax++;                                   // 面積カウントUp
            mhx += x;                               // 水平MmtData更新
            x++;                                    // x座標を進める
        }                                           //
        for(;;){                                    // 2番以降を繰返す
            for( ; x <= h; px++, x++ ){             // 水平方向で
                if( *px == -2 ){                    // 有効画素を探し
                    break;                          // 内側Loopを抜ける
                }                                   //
            }                                       //
            if( x > h ){                            // 水平終了時なら
                break;                              // 中間Loop終了
            }                                       //
            while( *px == -2 ){                     // 画素有効な間
                *px++ = -1;                         // 計測済みセットしptrを進め
                ax++;                               // 面積カウントUp
                mhx += x;                           // 水平MmtData更新
                x++;                                // x座標を進める
            }                                       //
        }                                           //
        a  += ax;                                   // 面積Data更新
        mh += (double)mhx;                          // 水平Moment更新
        mv += (double)( ax * y );                   // 垂直Moment更新
    }                                               //
    buf->a  = a;                                    // 面積を格納
    buf->mh = (float)mh;                            // 水平Momentを格納
    buf->mv = (float)mv;                            // 垂直Momentを格納
}

(1)関数名

「search」は、カタカナ語「サーチ」でココでは、図形を
サーチする意味
「mmt」は、「モーメント」を意味
「mmt1」は、「一次モーメント系計測」を意味
だから、「search_mmt1」で図形≪4及び8連結の塊≫の
一次モーメント系計測を計測するを意味します!

(2)仮引数

void            Filter::search_mmt1(
    char        *py,                                // フェレ始点Ptr
    TypeSf      *buf,                               // 計測結果Buffer
    int         inc                                 // インクリ幅
){

「char* py,」は、フェレ計測始点の画像画素ポインタ
「TypeSf* buf,」は、計測結果バッファーを示すポインタ
解説『解説クラスTypeSf』を参考にして下さい!
「int inc」は、画像の増加幅≪画像の垂直方向への進行用

(3)ローカル変数

    char        *pend;                              // 追跡点:終点
    char        *px;                                // 追跡点:水平方向
    int         h;                                  // 水平処理幅
    int         x;                                  // x座標
    int         y;                                  // y座標
    int         a;                                  // 面積データ
    int         ax;                                 // 面積Data:x方向
    int         mhx;                                // 1次水平MMTx方向
    double      mh;                                 // 1次水平MomentData
    double      mv;                                 // 1次垂直MomentData

「char* pend;」は、ラスタースキャンY座標方向終点≪
ソースコード開発時に使用したMC68060でコンパイラ
MCC68Kの機械コードでデータレジスターをローカル
変数として使い切ってたのでラスタースキャン外側ループの
制御にアドレスレジスターとし使用するポインタで比較制御
を考え高速化の為めに採用≫
「char* px;」は、ラスタースキャンX座標方向追跡点
「int h;」は、水平幅≪X座標方向処理幅≫
「int x,」は、X座標方向処理カウンター
「int y,」は、Y座標方向処理カウンター
「int a;」は、面積≪画素数≫
「int mhx;」は、1次水平方向モーメント値(水平方向分)
「double mh;」は、1次水平方向モーメント値
「double mv;」は、1次垂直方向モーメント値

(4)アルゴリズム

    h    = buf->h;                                  // 水平処理幅取出し
    a    = 0;                                       // 面積Data初期化
    mh   = 0.0;                                     // 水平Data初期化
    mv   = 0.0;                                     // 垂直Data初期化
    pend = py + buf->v * inc;                       // 終点を算出
    for( y = 1; py < pend; y++, py += inc ){        // 垂直処理幅分繰返
        px  = py;                                   // 水平処理始点Setし
        ax  = 0;                                    // 面積Data初期化
        mhx = 0;                                    // 水平MMTData初期化
        x   = 1;                                    // x座標初期化
        while( *px != -2 ){                         // 最初の有効画素を
            px++;                                   // 探しPtrと座標を
            x++;                                    // 進める
        }                                           //
        while( *px == -2 ){                         // 画素有効な間
            *px++ = -1;                             // 計測済みセットしptrを進め
            ax++;                                   // 面積カウントUp
            mhx += x;                               // 水平MmtData更新
            x++;                                    // x座標を進める
        }                                           //
        for(;;){                                    // 2番以降を繰返す
            for( ; x <= h; px++, x++ ){             // 水平方向で
                if( *px == -2 ){                    // 有効画素を探し
                    break;                          // 内側Loopを抜ける
                }                                   //
            }                                       //
            if( x > h ){                            // 水平終了時なら
                break;                              // 中間Loop終了
            }                                       //
            while( *px == -2 ){                     // 画素有効な間
                *px++ = -1;                         // 計測済みセットしptrを進め
                ax++;                               // 面積カウントUp
                mhx += x;                           // 水平MmtData更新
                x++;                                // x座標を進める
            }                                       //
        }                                           //
        a  += ax;                                   // 面積Data更新
        mh += (double)mhx;                          // 水平Moment更新
        mv += (double)( ax * y );                   // 垂直Moment更新
    }                                               //
    buf->a  = a;                                    // 面積を格納
    buf->mh = (float)mh;                            // 水平Momentを格納
    buf->mv = (float)mv;                            // 垂直Momentを格納
}

「h=buf->h;」は、図形の水平幅を取り出し、
「a=0;」は、面積≪画素数≫データを初期化
「mh=0.0;mv=0.0;」は、1次水平垂直モーメント初期化
「pend=py+buf->v*inc;」は、外側ループY座標方向ラス
タースキャンのY座標方向終点を算出し、「pend」にセット
「for(y=1;py<pend;y++,py+=inc){・・ループ中身・・}」
は、forループ「y=1;py<pend;y++,py+=inc」と初期化
「y=1;」でY座標初期化(=1)、ループ条件「py<pend;」
と外側ループY座標方向ポインタと終点で条件にし、増分
「y++,py+=inc」の「y++」とY座標方向を増加し、
「py+=inc」と垂直方向(Y座標方向)ポインタを増加≪
※備考※仮条件「y<buf->v;」の方が判り易いと思われるが
ソースコード開発時に使用したMC68060でコンパイラ
MCC68Kの機械コードでデータレジスターをローカル
変数として使い切る事に成ると処理速度が遅く成るのでポイ
ンタ同士の比較「py<pend」にして高速化した為です≫
ループ条件「py<pend;」と垂直幅分繰り返し、ループの終わ
りに「y++,py+=inc」と垂直(Y座標)方向処理ポインタを
垂直方向に進めるで、外側ループ中身が
「px=py;」は、水平方向(X座標)追跡点を初期化し
「ax=0;mhx=0;」は、水平方向ローカルの面積と水平方向の
モーメント値を初期化
「x=1;」は、X座標初期化(=1)、
「while(*px!=-2){px++;x++;}」は、目印「-2」に到達する
まで「px++;x++;」、水平方向追跡点とX座標を増加
「while(*px==-2){*px++=-1;ax++;mhx+=x;x++;}」は、
目印「-2」が続く間、「*px++=-1;ax++;mhx+=x;x++;」で
「*px++=-1;」と追跡点に計測終了「-1」をセットしポイン
タ進行、
「ax++;」で水平方向ローカル面積カウントアップ、
「mhx+=x;」で水平方向ローカルにモーメント累算、
「x++;」でX座標を増加、
「for(;;){・ラスタースキャン水平(X座標)処理・}」は
無限forループ「for(;;)」でラスタースキャン水平(
X座標)方向処理を行い水平方向処理の中の「break;」で
ループから抜けるループ処理を行い、ループの中は、
「for(;x<=h;px++,x++){if(*px==-2){break;}}」で
最内側forループ「;x<=h;px++,x++」で初期化無しの
ループ条件「x<=h;」でX座標が水平幅いっぱい処理し、
増分「px++,x++」と追跡点とX座標を増加、そして繰り返し
「if(*px==-2){break;}」と最内側forループを脱出する
「break;」が条件「*px==-2」と目印「-2」で脱出※注意:
無限forループ「for(;;)」を脱出する「break;」で無い
事に留意、つまり、目印を見つけるか水平方向終わりまで
繰り返すループです!
「if(x>h){break;}」で条件「x>h」が成立時は、目印が見つ
かる事なく水平方向処理が終わった事を意味して
「break;」で無限forループ「for(;;)」を脱出します!
「while(*px==-2){px++=-1;ax++;mhx+=x;x++;}」で
目印「-2」が続く間、「px++=-1;ax++;mhx+=x;x++;」と
「px++=-1;」と追跡点に計測終了「-1」をセットしポイン
タ進行、
「ax++;」で水平方向ローカル面積カウントアップ、
「mhx+=x;」で水平方向ローカルにモーメント累算、
「x++;」でX座標を増加、
これで、ラスタースキャン水平(X座標)方向処理のループ
が終了し、「ax」にX座標方向ローカルな面積が算出し、
「mhx」にX座標方向ローカルな水平方向一次モーメント
算出!
「a+=ax;」は、全体の面積「a」にX座標方向ローカル面積を累計
「mh+=(double)mhx;」は、全体の水平方向一次モーメント
「mh」にX座標方向ローカル水平方向一次モーメントを累計
「mv+=(double)(axy);」は、「axy」でY座標個別の垂直
一次モーメントを算出で「mv+=(double)(axy);」で全体の
垂直一次モーメントを累計
※注意:内部で演算する場合は、CPUの高精細浮動小数点
演算レジスターに格納される為に「double型」のローカル
変数を使用しています!
ここまでのループで外側垂直方向(Y座標)ループを終了ま
で繰り返します!

※備考※
条件「*px==-2」と追跡点が「-2」≪search4fere()或は、
search8fere()関数で目印としてこれらの関数の
仮引数「int clr_dt,」に「-2」を設定して画像画素を
無効化「負の数」した意味とsearch_mmt1()等の継続して
計測する処理の為の計測対象目印にして居る事に注意≫
正方向≪上から下、左から右≫ラスタースキャンの
二重ループを終えると
「buf->a=a;」は、画素数を図形面積として計測結果へ格納
「buf->mh=(float)mh;」は、内部で「double型」で高精細
計測した1次水平モーメントを格納する「float型」と言う
省メモリに変換して格納
「buf->mv=(float)mv;」は、内部で「double型」で高精細
計測した1次水平モーメントを格納する「float型」と言う
省メモリに変換して格納

7.終わりに

この仕事は天職だと感じたアルゴリズム開発から、
代表的な関数として「MeasureStandard()」≒標準計測を
説明し、4連結のフェレ計測を「search4fere()」で
8連結のフェレ計測を「search8fere()」で解説し、
その方式で作成した図形個別に面積を「search_area()」で
計測し、同じく一次モーメントを「search_mmt1()」で作成
を例に、色々な処理が行って居る事を説明した心算です!
これで、オーソドックスなラベリング処理でのラベル画像
から色々幾何的な計測を行う事に比べて高速化した処理を
説明しました!実際にベンチマークテストを行って
自らが天才で無いかと悦に入った覚えが有るが、それの
説明に10日間以上掛かってシマッタ、
覚えているのは、この機構を徹夜込みで数日間の内に一気に
作成したので天才と考えました!しかしながら、恐らく、
エッセイ『働き方改革』に記した様に私の脳細胞を壊した元
と思える!読者様もくれぐれもご自愛ください!

ベンチマークテストが、想定以上に好成績に成ったのは、
エッセイ『高速大容量の代表的処理が、画像処理』でプログ
ラムが遅く成る原因をメモリアクセスと説明しましたが、
キャッシュメモリを効率的に使えないアルゴリズムを徹底的
に排除した事は、読み取って頂けたかな?

文末

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