見出し画像

解説クラスCopyClear(24)

解説クラスCopyClear(24)


2025年2月6初稿(初講)

正規化相関関数系の「public:属性」の関数の解説を行います
基本的に画像の比較を行う処理です!
解説『解説クラスCopyClear(23)』の続きです

(4-14-164)関数「void AverageImage88XY(
TypeArray* pa,TypeXY* xy,
BYTE* buf,int size,int offX=0,
int offY=0){・・・}

/************************************************************************************/
/*****      8×8画素画像平均適応                                              *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

void            CopyClear::AverageImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    BYTE*       buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = (int)Ave8M( ptrA + x + y * incA, incA, 8 );      // 8×8画素平均算出
        }else{                                                      // 範囲外ならば
            *buf = 0;                                               // 0をセット
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「AverageImage88XY()」の【関数名】

「Average」は、英単語「Average」で「平均値」を意味
「Image」は、勿論、画像です!
「88」は、処理する画像の範囲として「縦×横=8×8=
16画素」のサイズを意味します
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の平均値算出関数です!
この多重定義(オーバーロード)関数は、
仮引数「TypeXY* xy,」で複数指定します!

(B)関数「void AverageImage88XY()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「AverageImage88XY()」の【仮引数】

void            CopyClear::AverageImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    BYTE*       buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){

「TypeArray* pa,」は、画像情報
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「BYTE* buf,」は、結果格納バッファー!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標

(D)関数「AverageImage88XY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = (int)Ave8M( ptrA + x + y * incA, incA, 8 );      // 8×8画素平均算出
        }else{                                                      // 範囲外ならば
            *buf = 0;                                               // 0をセット
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

「BYTE* ptrA;」は、画素単位処理ポインタ
「int incA;」は、増加幅★備考★「int inc;」の方が相応
しいと思われるでしょう、この記載に成ったのは、単に
コピペで他の部分から流用したからです!同じ様に処理ポイ
ンタも「BYTE* ptr;」の方が相応しいが、同じ理由から、
この変数名に成ったのです!
「int minH;」は、水平幅の有効(8×8升枠を考慮)幅
「int minV;」は、垂直幅の有効(8×8升枠を考慮)幅
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = (int)Ave8M( ptrA + x + y * incA, incA, 8 );      // 8×8画素平均算出
        }else{                                                      // 範囲外ならば
            *buf = 0;                                               // 0をセット
        }                                                           // 
    }                                                               // 
}

「minH=pa->h-8;」は、水平有効幅算出
「minV=pa->v-8;」は、垂直有効幅算出
「ptrA=(BYTE*)pa->adr;」は、処理ポインタのセット
「incA=pa->inc;」は、増加幅のセット
「for(i=0;i<size;i++,xy++,buf++){・・ループ本体・・}」
は、ループ初期値「i=0;」ループ条件「i<size;」ループ
終了後処理「i++,xy++,buf++」と教科書的for構文での
アップカウンタ「i=0;」を条件「i<size;」増分「i++,」と
「0からsize未満」まで繰り返し同時に「xy++,buf++」と
バッファを示すポインタ増加でループ本体で
「x=xy->x+offX;y=xy->y+offY;」は仮引数「TypeXY* xy,」
からXY座標を取り出す!
「if(x>=0&&x<minH&&y>=0&&y<minV){
buf=(int)Ave8M(ptrA+x+yincA,incA,8);}」は、if条件
「x>=0&&x<minH&&y>=0&&y<minV」で取り出したXY座標が、
有効な時「buf=(int)Ave8M(ptrA+x+yincA,incA,8);」と
サブルーチン関数「Ave8M(ptrA+x+y*incA,incA,8);」で
平均値算出し、「*buf=(int)・・・」は、整数型に型変換(
小数点以下切り捨て)し結果バッファに格納!
「else{*buf=0;}」は、XY座標が範囲外の場合で
「*buf=0;」とバッファに「0」を格納!

(4-14-165)関数「void AverageImage88XY(
TypeArray* pa,TypeXY* xy,
double* buf,int size,int offX=0,
int offY=0){・・・}

/************************************************************************************/
/*****      8×8画素画像平均適応                                              *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

void            CopyClear::AverageImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Ave8M( ptrA + x + y * incA, incA, 8 );           // 8×8画素平均算出
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「AverageImage88XY()」の【関数名】

「Average」は、英単語「Average」で「平均値」を意味
「Image」は、勿論、画像です!
「88」は、処理する画像の範囲として「縦×横=8×8=
16画素」のサイズを意味します
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の平均値算出関数です!
この多重定義(オーバーロード)関数は、
仮引数「TypeXY* xy,」で複数指定します!

(B)関数「void AverageImage88XY()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「AverageImage88XY()」の【仮引数】

void            CopyClear::AverageImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){

「TypeArray* pa,」は、画像情報
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標

(D)関数「AverageImage88XY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Ave8M( ptrA + x + y * incA, incA, 8 );           // 8×8画素平均算出
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

「BYTE* ptrA;」は、画素単位処理ポインタ
「int incA;」は、増加幅★備考★「int inc;」の方が相応
しいと思われるでしょう、この記載に成ったのは、単に
コピペで他の部分から流用したからです!同じ様に処理ポイ
ンタも「BYTE* ptr;」の方が相応しいが、同じ理由から、
この変数名に成ったのです!
「int minH;」は、水平幅の有効(8×8升枠を考慮)幅
「int minV;」は、垂直幅の有効(8×8升枠を考慮)幅
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Ave8M( ptrA + x + y * incA, incA, 8 );           // 8×8画素平均算出
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

「minH=pa->h-8;」は、水平有効幅算出
「minV=pa->v-8;」は、垂直有効幅算出
「ptrA=(BYTE*)pa->adr;」は、処理ポインタのセット
「incA=pa->inc;」は、増加幅のセット
「for(i=0;i<size;i++,xy++,buf++){・・ループ本体・・}」
は、ループ初期値「i=0;」ループ条件「i<size;」ループ
終了後処理「i++,xy++,buf++」と教科書的for構文での
アップカウンタ「i=0;」を条件「i<size;」増分「i++,」と
「0からsize未満」まで繰り返し同時に「xy++,buf++」と
バッファを示すポインタ増加でループ本体で
「x=xy->x+offX;y=xy->y+offY;」は仮引数「TypeXY* xy,」
からXY座標を取り出す!
「if(x>=0&&x<minH&&y>=0&&y<minV){
buf=(int)Ave8M(ptrA+x+yincA,incA,8);}」は、if条件
「x>=0&&x<minH&&y>=0&&y<minV」で取り出したXY座
標が、有効な時「buf=(int)Ave8M(ptrA+x+yincA,incA,8);」と
サブルーチン関数「Ave8M(ptrA+x+y*incA,incA,8);」で
平均値算出し、「*buf=(int)・・・」は、整数型に型変換(
小数点以下切り捨て)し結果バッファに格納!
「else{*buf=0;}」は、XY座標が範囲外の場合で
「*buf=0.0;」とバッファに「0.0」を格納!

(4-14-166)関数「double CorrImage88XY(
TypeArray* pa,TypeArray* pb,
int x,int y){・・・}」

/************************************************************************************/
/*****      8×8画素正規化相関画像適応:個別                                  *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

double          CopyClear::CorrImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    int         x,                                                  // X座標値
    int         y                                                   // Y座標値
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         incB;                                               // B配列:増加幅
    int         minH;                                               // ABの最小値:水平幅
    int         minV;                                               // ABの最小値:垂直幅

    minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - 8;               // 水平幅の最小値算出
    minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - 8;               // 垂直幅の最小値算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    ptrB = (BYTE*)pb->adr;                                          // B配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    incB = pb->inc;                                                 // B配列:増加幅
    if( x >= 0 && x < minH && y >= 0 && y < minV ){                 // 有効範囲内ならば
        return( Corr88( ptrA + x + y * incA,                        // 8×8画素の正規相関を
                            ptrB + x + y * incB, incA, incB ) );    // 演算
    }else{                                                          // 範囲外ならば
        return( 0.0 );                                              // 0.0を返す
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88XY()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の相関値算出関数です!

(B)関数「double CorrImage88XY()」の【返値】

関数返値として算出し相関値(一致率)を返す関数です!

(C)関数「CorrImage88XY()」の【仮引数】

double          CopyClear::CorrImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    int         x,                                                  // X座標値
    int         y                                                   // Y座標値
){

「TypeArray* pa,」は、比較対象画像A
「TypeArray* pb,」は、比較対象画像B
「int x」は、X座標
「int y」は、Y座標

(D)関数「CorrImage88XY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         incB;                                               // B配列:増加幅
    int         minH;                                               // ABの最小値:水平幅
    int         minV;                                               // ABの最小値:垂直幅

    minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - 8;               // 水平幅の最小値算出
    minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - 8;               // 垂直幅の最小値算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    ptrB = (BYTE*)pb->adr;                                          // B配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    incB = pb->inc;                                                 // B配列:増加幅
    if( x >= 0 && x < minH && y >= 0 && y < minV ){                 // 有効範囲内ならば
        return( Corr88( ptrA + x + y * incA,                        // 8×8画素の正規相関を
                            ptrB + x + y * incB, incA, incB ) );    // 演算
    }else{                                                          // 範囲外ならば
        return( 0.0 );                                              // 0.0を返す
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         incB;                                               // B配列:増加幅
    int         minH;                                               // ABの最小値:水平幅
    int         minV;                                               // ABの最小値:垂直幅

「BYTE* ptrA;」は、A画像用始点処理ポインタ
「BYTE* ptrB;」は、B画像用始点処理ポインタ
「int incA;」は、A画像増加幅
「int incB;」は、B画像増加幅
「int minH;」は、有効水平幅(8×8升枠考慮)
「int minV;」は、有効垂直幅(8×8升枠考慮)

(D-2)アルゴリズムコード

    minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - 8;               // 水平幅の最小値算出
    minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - 8;               // 垂直幅の最小値算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    ptrB = (BYTE*)pb->adr;                                          // B配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    incB = pb->inc;                                                 // B配列:増加幅
    if( x >= 0 && x < minH && y >= 0 && y < minV ){                 // 有効範囲内ならば
        return( Corr88( ptrA + x + y * incA,                        // 8×8画素の正規相関を
                            ptrB + x + y * incB, incA, incB ) );    // 演算
    }else{                                                          // 範囲外ならば
        return( 0.0 );                                              // 0.0を返す
    }                                                               // 
}

「minH=((pa->h<pb->h)?pa->h:pb->h)-8;」は、水平画素数
の有効(最小で8×8升枠考慮)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v)-8;」は、垂直画素数の
有効(最小で8×8升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「ptrB=(BYTE*)pb->adr;」は、B画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「incB=pb->inc;」は、B画像増加幅をセット!
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立中身・・}」は、条件「x>=0&&x<minH&&y>=0&&y<minV」で有効サイズで「N×M」升枠が、XY座標設定時に有効な場合、成立「return(Corr88(ptrA+x+yincA,ptrB+x+yincB,
incA,incB));」とサブルーチン関数「Corr88()」で処理し
関数終了!
不成立「else{return(0.0);}」で関数辺値として「0.0」を
返し関数終了!

(4-14-167)関数「void CorrImage88XY(
TypeArray* pa,
TypeArray* pb,TypeXY* xy,
double* buf,int size,int offX,
int offY){・・・}」

/************************************************************************************/
/*****      8×8画素正規化相関画像適応                                        *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

void            CopyClear::CorrImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         incB;                                               // B配列:増加幅
    int         minH;                                               // ABの最小値:水平幅
    int         minV;                                               // ABの最小値:垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - 8;               // 水平幅の最小値算出
    minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - 8;               // 垂直幅の最小値算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    ptrB = (BYTE*)pb->adr;                                          // B配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    incB = pb->inc;                                                 // B配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88( ptrA + x + y * incA,                     // 8×8画素の正規相関を
                                ptrB + x + y * incB, incA, incB );  // 演算
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88XY()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の相関値算出関数です!

(B)関数「void CorrImage88XY()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「CorrImage88XY()」の【仮引数】

void            CopyClear::CorrImage88XY(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){

「TypeArray* pa,」は、比較対象画像A
「TypeArray* pb,」は、比較対象画像B
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標

(D)関数「CorrImage88XY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         incB;                                               // B配列:増加幅
    int         minH;                                               // ABの最小値:水平幅
    int         minV;                                               // ABの最小値:垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - 8;               // 水平幅の最小値算出
    minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - 8;               // 垂直幅の最小値算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    ptrB = (BYTE*)pb->adr;                                          // B配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    incB = pb->inc;                                                 // B配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88( ptrA + x + y * incA,                     // 8×8画素の正規相関を
                                ptrB + x + y * incB, incA, incB );  // 演算
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         incB;                                               // B配列:増加幅
    int         minH;                                               // ABの最小値:水平幅
    int         minV;                                               // ABの最小値:垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

「BYTE* ptrA;」は、A画像用始点処理ポインタ
「BYTE* ptrB;」は、B画像用始点処理ポインタ
「int incA;」は、A画像増加幅
「int incB;」は、B画像増加幅
「int minH;」は、有効水平幅(8×8升枠考慮)
「int minV;」は、有効垂直幅(8×8升枠考慮)
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - 8;               // 水平幅の最小値算出
    minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - 8;               // 垂直幅の最小値算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    ptrB = (BYTE*)pb->adr;                                          // B配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    incB = pb->inc;                                                 // B配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88( ptrA + x + y * incA,                     // 8×8画素の正規相関を
                                ptrB + x + y * incB, incA, incB );  // 演算
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

「minH=((pa->h<pb->h)?pa->h:pb->h)-8;」は、水平画素数
の有効(最小で8×8升枠考慮)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v)-8;」は、垂直画素数の
有効(最小で8×8升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「ptrB=(BYTE*)pb->adr;」は、B画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「incB=pb->inc;」は、B画像増加幅をセット!
「for(i=0;i<size;i++,xy++,buf++){・・ループ本体・・}」
は、ループ初期値「i=0;」ループ条件「i<size;」ループ
終了後処理「i++,xy++,buf++」と教科書的for構文での
アップカウンタ「i=0;」を条件「i<size;」増分「i++,」と
「0からsize未満」まで繰り返し同時に「xy++,buf++」と
バッファを示すポインタ増加でループ本体で
「x=xy->x+offX;y=xy->y+offY;」は、XY座標バッファー
からローカル変数「int x;int y;」に取り出しオフセット
座標を加え、
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立・・}」は、
if条件「x>=0&&x<minH&&y>=0&&y<minV」でXY座標が
範囲内ならば、成立「buf=Corr88(ptrA+x+yincA,
ptrB+x+y*incB,incA,incB);」でサブルーチン関数
「Corr88()」で処理しバッファー格納★そしてif
不成立「else{*buf = 0.0;}」は、「0.0」をバッファー格納

(4-14-168)関数「double CorrImage88MyselfXY(
TypeArray* pa,int x,int y){・・・}」

/************************************************************************************/
/*****      8×8画素自己相関画像適応:個別                                    *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

double          CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    int         x,                                                  // X座標値
    int         y                                                   // Y座標値
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    if( x >= 0 && x < minH && y >= 0 && y < minV ){                 // 有効範囲内ならば
        return( Corr88Myself( ptrA + x + y * incA, incA ) );        // 8×8画素自己相関算出
    }else{                                                          // 範囲外ならば
        return( 0.0 );                                              // 0.0を返す
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88MyselfXY()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の相関値算出関数です!

(B)関数「double CorrImage88MyselfXY()」の【返値】

関数返値として算出し相関値(一致率)を返す関数です!
★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!

(C)関数「CorrImage88MyselfXY()」の【仮引数】

double          CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    int         x,                                                  // X座標値
    int         y                                                   // Y座標値
){

「TypeArray* pa,」は、画像情報
「int x」は、X座標
「int y」は、Y座標

(D)関数「CorrImage88MyselfXY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    if( x >= 0 && x < minH && y >= 0 && y < minV ){                 // 有効範囲内ならば
        return( Corr88Myself( ptrA + x + y * incA, incA ) );        // 8×8画素自己相関算出
    }else{                                                          // 範囲外ならば
        return( 0.0 );                                              // 0.0を返す
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅

「BYTE* ptrA;」は、A画像用始点処理ポインタ
「int incA;」は、A画像増加幅★備考★「int inc;」の
方が相応しいと思われるでしょう、この記載に成ったのは、
単にコピペで他の部分から流用したからです!同じ様に
処理ポインタも「BYTE* ptr;」の方が相応しいが、同じ
理由から、この変数名に成ったのです!
「int minH;」は、有効水平幅(8×8升枠考慮)
「int minV;」は、有効垂直幅(8×8升枠考慮)

(D-2)アルゴリズムコード

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    if( x >= 0 && x < minH && y >= 0 && y < minV ){                 // 有効範囲内ならば
        return( Corr88Myself( ptrA + x + y * incA, incA ) );        // 8×8画素自己相関算出
    }else{                                                          // 範囲外ならば
        return( 0.0 );                                              // 0.0を返す
    }                                                               // 
}

「minH=((pa->h<pb->h)?pa->h:pb->h)-8;」は、水平画素数
の有効(最小で8×8升枠考慮)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v)-8;」は、垂直画素数の
有効(最小で8×8升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立・・}」は、if条件「x>=0&&x<minH&&y>=0&&y<minV」で
XY座標が範囲内ならば、成立「return(Corr88Myself(
ptrA+x+yincA,incA));」でサブルーチン関数「Corr88Myself()」で処理、★備考★実引数「ptrA+x+yincA,」でXY座標がポインタ演算で画像
ピンポイントで算出している事に注意!
そしてif不成立「else{return(0.0);}」は、「0.0」を
関数辺値とし返し関数終了!

(4-14-169)関数「void CorrImage88MyselfXY(
TypeArray* pa,TypeXY* xy,
double* buf,int size,int offX=0,
int offY=0){・・・}」

/************************************************************************************/
/*****      8×8画素自己相関画像適応                                          *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88Myself( ptrA + x + y * incA, incA );       // 8×8画素自己相関算出
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88MyselfXY()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の相関値算出関数です!

(B)関数「void CorrImage88MyselfXY()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「CorrImage88MyselfXY()」の【仮引数】

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){

「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標

(D)関数「CorrImage88MyselfXY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88Myself( ptrA + x + y * incA, incA );       // 8×8画素自己相関算出
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

「BYTE* ptrA;」は、A画像用始点処理ポインタ
「int incA;」は、A画像増加幅★備考★「int inc;」の
方が相応しいと思われるでしょう、この記載に成ったのは、
単にコピペで他の部分から流用したからです!同じ様に
処理ポインタも「BYTE* ptr;」の方が相応しいが、同じ
理由から、この変数名に成ったのです!
「int minH;」は、有効水平幅(8×8升枠考慮)
「int minV;」は、有効垂直幅(8×8升枠考慮)
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88Myself( ptrA + x + y * incA, incA );       // 8×8画素自己相関算出
        }else{                                                      // 範囲外ならば
            *buf = 0.0;                                             // 0.0をセット
        }                                                           // 
    }                                                               // 
}

「minH=((pa->h<pb->h)?pa->h:pb->h)-8;」は、水平画素数
の有効(最小で8×8升枠考慮)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v)-8;」は、垂直画素数の
有効(最小で8×8升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「for(i=0;i<size;i++,xy++,buf++){・・ループ本体・・}」
は、ループ初期値「i=0;」ループ条件「i<size;」ループ
終了後処理「i++,xy++,buf++」と教科書的for構文での
アップカウンタ「i=0;」を条件「i<size;」増分「i++,」と
「0からsize未満」まで繰り返し同時に「xy++,buf++」と
バッファを示すポインタ増加でループ本体で
「x=xy->x+offX;y=xy->y+offY;」は、XY座標バッファー
からローカル変数「int x;int y;」に取り出しオフセット
座標を加え、
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立・・}」は、if条件「x>=0&&x<minH&&y>=0&&y<minV」で
XY座標が範囲内ならば、成立「buf=Corr88Myself(ptrA+x+yincA,incA);」でサブルーチン
関数「Corr88Myself()」で処理しバッファー格納!
そしてif不成立「else{*buf=0.0;}」は「0.0」を
バッファー格納!

(4-14-170)関数「void CorrImage88MyselfXY(
TypeArray* pa,TypeXY* xy,
double* buf,BYTE* bufAve,
int size,int offX=0,int offY=0){・・・}」

/************************************************************************************/
/*****      8×8画素自己相関画像適応+画像平均                                *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    BYTE*       bufAve,                                             // 結果バッファー:平均
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         ave;                                                // 平均値
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++, bufAve++ ){             // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf    = Corr88Myself( ptrA + x + y * incA, incA,      // 8×8画素自己相関算出
                                                            ave );  // (平均値も算出)
            *bufAve = ave;                                          // 平均値を格納
        }else{                                                      // 範囲外ならば
            *buf    = 0.0;                                          // 0.0をセット
            *bufAve = 0;                                            // 0をセット
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88MyselfXY()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の相関値算出関数です!

(B)関数「void CorrImage88MyselfXY()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「CorrImage88MyselfXY()」の【仮引数】

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    double*     buf,                                                // 結果バッファー
    BYTE*       bufAve,                                             // 結果バッファー:平均
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){

「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果(分散値)格納バッファー!
「BYTE* bufAve,」は、結果(平均値)格納バッファー!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
★備考★「BYTE* bufAve,」が有る事で多重定義(オーバー
ロード)関数の識別が出来ます!分散値だけで無く平均値
も必要な場合を考えた関数ですが、関数名を新規に考えるの
が面倒に成った(適切な名前より得られる引数追加の方が
簡単)のでコノ状態に成りました!平均値を使わない場合は
引数を記載しなければ良いとの考えです!多重定義の使い方
としてコレも有りなのだ!

(D)関数「CorrImage88MyselfXY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         ave;                                                // 平均値
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++, bufAve++ ){             // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf    = Corr88Myself( ptrA + x + y * incA, incA,      // 8×8画素自己相関算出
                                                            ave );  // (平均値も算出)
            *bufAve = ave;                                          // 平均値を格納
        }else{                                                      // 範囲外ならば
            *buf    = 0.0;                                          // 0.0をセット
            *bufAve = 0;                                            // 0をセット
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         ave;                                                // 平均値
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

「BYTE* ptrA;」は、A画像用始点処理ポインタ
「int incA;」は、A画像増加幅★備考★「int inc;」の
方が相応しいと思われるでしょう、この記載に成ったのは、
単にコピペで他の部分から流用したからです!同じ様に
処理ポインタも「BYTE* ptr;」の方が相応しいが、同じ
理由から、この変数名に成ったのです!
「int minH;」は、有効水平幅(8×8升枠考慮)
「int minV;」は、有効垂直幅(8×8升枠考慮)
「int ave;」は、個別の平均値
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++, bufAve++ ){             // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf    = Corr88Myself( ptrA + x + y * incA, incA,      // 8×8画素自己相関算出
                                                            ave );  // (平均値も算出)
            *bufAve = ave;                                          // 平均値を格納
        }else{                                                      // 範囲外ならば
            *buf    = 0.0;                                          // 0.0をセット
            *bufAve = 0;                                            // 0をセット
        }                                                           // 
    }                                                               // 
}

「minH=((pa->h<pb->h)?pa->h:pb->h)-8;」は、水平画素数
の有効(最小で8×8升枠考慮)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v)-8;」は、垂直画素数の
有効(最小で8×8升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「ptrB=(BYTE*)pb->adr;」は、B画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「incB=pb->inc;」は、B画像増加幅をセット!
「for(i=0;i<size;i++,xy++,buf++){・・ループ本体・・}」
は、ループ初期値「i=0;」ループ条件「i<size;」ループ
終了後処理「i++,xy++,buf++」と教科書的for構文での
アップカウンタ「i=0;」を条件「i<size;」増分「i++,」と
「0からsize未満」まで繰り返し同時に「xy++,buf++」と
バッファを示すポインタ増加でループ本体で
「x=xy->x+offX;y=xy->y+offY;」は、XY座標バッファー
からローカル変数「int x;int y;」に取り出しオフセット
座標を加え、
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立・・}」は、if条件「x>=0&&x<minH&&y>=0&&y<minV」で
XY座標が範囲内ならば、成立「buf=Corr88Myself(ptrA+x+yincA,incA,ave);*bufAve=ave;」でサブルーチン関数「Corr88Myself()」で処理しバッファー
格納!更に
★注意★
サブルーチン関数「Corr88Myself(・・ave・・)」と多重定
義(オーバーロード)関数として「ave」を指定して平均値
算出と指定し無い関数が存在し、ココでは指定する関数を
使用、「*bufAve=ave;」は、平均値格納バッファー平均値を
格納!
そしてif不成立「else{*buf=0.0;*bufAve=0;}」は、
「0.0」を分散値、「0」を平均値とし引数辺値とし返し
関数終了!

(4-14-171)関数「void CorrImage88MyselfXY(
TypeArray* pa,TypeXY* xy,
int* buf,int size,int offX=0,
int offY=0){・・・}」

/************************************************************************************/
/*****      8×8画素自己相関画像適応                                          *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    int*        buf,                                                // 結果バッファー:整数値
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88Myself( ptrA + x + y * incA, incA );       // 8×8画素自己相関算出
        }else{                                                      // 範囲外ならば
            *buf = 0;                                               // 0をセット
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88MyselfXY()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の相関値算出関数です!

(B)関数「void CorrImage88MyselfXY()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「CorrImage88MyselfXY()」の【仮引数】

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    int*        buf,                                                // 結果バッファー:整数値
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){

「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「int* buf,」は、結果格納バッファー!★備考★ここが、
多重定義(オーバーロード)で格納する型が違う事に留意
して下さい!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標

(D)関数「CorrImage88MyselfXY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88Myself( ptrA + x + y * incA, incA );       // 8×8画素自己相関算出
        }else{                                                      // 範囲外ならば
            *buf = 0;                                               // 0をセット
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

「BYTE* ptrA;」は、A画像用始点処理ポインタ
「int incA;」は、A画像増加幅★備考★「int inc;」の
方が相応しいと思われるでしょう、この記載に成ったのは、
単にコピペで他の部分から流用したからです!同じ様に
処理ポインタも「BYTE* ptr;」の方が相応しいが、同じ
理由から、この変数名に成ったのです!
「int minH;」は、有効水平幅(8×8升枠考慮)
「int minV;」は、有効垂直幅(8×8升枠考慮)
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++ ){                       // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf = Corr88Myself( ptrA + x + y * incA, incA );       // 8×8画素自己相関算出
        }else{                                                      // 範囲外ならば
            *buf = 0;                                               // 0をセット
        }                                                           // 
    }                                                               // 
}

「minH=pa->h-8;」は、水平画素数
の有効(最小で8×8升枠考慮)サイズ算出!
「minV=pb->v-8;」は、垂直画素数の
有効(最小で8×8升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「for(i=0;i<size;i++,xy++,buf++){・・ループ本体・・}」
は、ループ初期値「i=0;」ループ条件「i<size;」ループ
終了後処理「i++,xy++,buf++」と教科書的for構文での
アップカウンタ「i=0;」を条件「i<size;」増分「i++,」と
「0からsize未満」まで繰り返し同時に「xy++,buf++」と
バッファを示すポインタ増加でループ本体で
「x=xy->x+offX;y=xy->y+offY;」は、XY座標バッファー
からローカル変数「int x;int y;」に取り出しオフセット
座標を加え、
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立・・}」は、if条件「x>=0&&x<minH&&y>=0&&y<minV」で
XY座標が範囲内ならば、
成立「buf=Corr88Myself(ptrA+x+yincA,incA);」で
サブルーチン関数「Corr88Myself()」で処理しバッファー格納
そしてif不成立「else{*buf=0;}」は、「0」を分散値
とし返し関数終了!

(4-14-172)関数「void CorrImage88MyselfXY(
TypeArray* pa,TypeXY* xy,
int* buf,BYTE* bufAve,
int size,int offX=0,int offY=0){・・・}」

/************************************************************************************/
/*****      8×8画素自己相関画像適応+画像平均                                *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    int*        buf,                                                // 結果バッファー:整数値
    BYTE*       bufAve,                                             // 結果バッファー:平均
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         ave;                                                // 平均値
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++, bufAve++ ){             // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf    = Corr88Myself( ptrA + x + y * incA, incA,      // 8×8画素自己相関算出
                                                            ave );  // (平均値も算出)
            *bufAve = ave;                                          // 平均値を格納
        }else{                                                      // 範囲外ならば
            *buf    = 0;                                            // 0をセット
            *bufAve = 0;                                            // 0をセット
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88MyselfXY()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所の8×8升枠の相関値算出関数です!

(B)関数「void CorrImage88MyselfXY()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「CorrImage88MyselfXY()」の【仮引数】

void            CopyClear::CorrImage88MyselfXY(
    TypeArray*  pa,                                                 // A配列
    TypeXY*     xy,                                                 // 探索座標列
    int*        buf,                                                // 結果バッファー:整数値
    BYTE*       bufAve,                                             // 結果バッファー:平均
    int         size,                                               // バッファーサイズ
    int         offX,                                               // X座標オフセット(省略時0)
    int         offY                                                // Y座標オフセット(省略時0)
){

「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「int* buf,」は、結果格納バッファー!★備考★ここが、
多重定義(オーバーロード)で格納する型が違う事に留意
して下さい!
「BYTE* bufAve,」は、結果(平均値)格納バッファー!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
★備考★「BYTE* bufAve,」が有る事で多重定義(オーバー
ロード)関数の識別が出来ます!分散値だけで無く平均値
も必要な場合を考えた関数ですが、関数名を新規に考えるの
が面倒に成った(適切な名前より得られる引数追加の方が
簡単)のでコノ状態に成りました!平均値を使わない場合は
引数を記載しなければ良いとの考えです!多重定義の使い方
としてコレも有りなのだ!

(D)関数「CorrImage88MyselfXY()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         ave;                                                // 平均値
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++, bufAve++ ){             // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf    = Corr88Myself( ptrA + x + y * incA, incA,      // 8×8画素自己相関算出
                                                            ave );  // (平均値も算出)
            *bufAve = ave;                                          // 平均値を格納
        }else{                                                      // 範囲外ならば
            *buf    = 0;                                            // 0をセット
            *bufAve = 0;                                            // 0をセット
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    int         incA;                                               // A配列:増加幅
    int         minH;                                               // Aの有効水平幅
    int         minV;                                               // Aの有効垂直幅
    int         ave;                                                // 平均値
    int         x;                                                  // X座標値
    int         y;                                                  // Y座標値
    int         i;                                                  // カウンタ

「BYTE* ptrA;」は、A画像用始点処理ポインタ
「int incA;」は、A画像増加幅★備考★「int inc;」の
方が相応しいと思われるでしょう、この記載に成ったのは、
単にコピペで他の部分から流用したからです!同じ様に
処理ポインタも「BYTE* ptr;」の方が相応しいが、同じ
理由から、この変数名に成ったのです!
「int minH;」は、有効水平幅(8×8升枠考慮)
「int minV;」は、有効垂直幅(8×8升枠考慮)
「int ave;」は、個別の平均値
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = pa->h - 8;                                               // 水平幅の有効範囲算出
    minV = pa->v - 8;                                               // 垂直幅の有効範囲算出
    ptrA = (BYTE*)pa->adr;                                          // A配列:処理ポインタ
    incA = pa->inc;                                                 // A配列:増加幅
    for( i = 0; i < size; i++, xy++, buf++, bufAve++ ){             // 個数分
        x = xy->x + offX;                                           // 座標値を算出し
        y = xy->y + offY;                                           // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            *buf    = Corr88Myself( ptrA + x + y * incA, incA,      // 8×8画素自己相関算出
                                                            ave );  // (平均値も算出)
            *bufAve = ave;                                          // 平均値を格納
        }else{                                                      // 範囲外ならば
            *buf    = 0;                                            // 0をセット
            *bufAve = 0;                                            // 0をセット
        }                                                           // 
    }                                                               // 
}

「minH=((pa->h<pb->h)?pa->h:pb->h)-8;」は、水平画素数
の有効(最小で8×8升枠考慮)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v)-8;」は、垂直画素数の
有効(最小で8×8升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「for(i=0;i<size;i++,xy++,buf++){・・ループ本体・・}」
は、ループ初期値「i=0;」ループ条件「i<size;」ループ
終了後処理「i++,xy++,buf++」と教科書的for構文での
アップカウンタ「i=0;」を条件「i<size;」増分「i++,」と
「0からsize未満」まで繰り返し同時に「xy++,buf++」と
バッファを示すポインタ増加でループ本体で
「x=xy->x+offX;y=xy->y+offY;」は、XY座標バッファー
からローカル変数「int x;int y;」に取り出しオフセット
座標を加え、
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立・・}」は、if条件「x>=0&&x<minH&&y>=0&&y<minV」で
XY座標が範囲内ならば、成立「buf=Corr88Myself(ptrA+x+yincA,incA,ave);bufAve=ave;」でサブルーチン関数「Corr88Myself()」で処理しバッファー格納★備考★
実引数「ptrA+x+yincA,」でXY座標がポインタ演算で
画像ピンポイントで算出している事に注意!更に
★注意★サブルーチン関数「Corr88Myself(・・ave・・)」と多重定義(オーバーロード)関数として「ave」を指定して
平均値算出と指定し無い関数が存在し、ココでは指定する
関数を使用、「*bufAve=ave;」は、平均値格納バッファー
平均値を格納!
そしてif不成立「else{*buf=0;*bufAve=0;}」は、
「0」を分散値、「0」を平均値としバッファー格納!

(4-14-173)関数「void CorrImage88MyselfExtend(
TypeArray* image,
TypeXY* bufXY,double* buf,
int maxN,int nStepH,
int nStepV,double tA,double tB){・・・}」

/************************************************************************************/
/*****      8×8画素自己相関画像適応:拡張                                    *****/
/*****      ☆8×8の基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/*****      (1)概要でステップ毎に演算                                        *****/
/*****      (2)詳細で座標に従い細かく演算                                    *****/
/************************************************************************************/

int             CopyClear::CorrImage88MyselfExtend(
    TypeArray*  image,                                              // 画像
    TypeXY*     bufXY,                                              // 結果座標バッファー
    double*     buf,                                                // 結果バッファー
    int         maxN,                                               // 最大結果数
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    double      tA,                                                 // 最小概要しきい値
    double      tB                                                  // 最大概要しきい値
){
    int*        bufL;                                               // 結果バッファー:概要
    int         nH;                                                 // 水平方向個数
    int         nV;                                                 // 垂直方向個数
    int         nHV;                                                // 個数(nH*nV)
    int         n;                                                  // 計測個数

    GetHVCorrImage88Myself( image, nStepH, nStepV, nH, nV );        // 自己相関升目個数
    nHV  = nH * nV;                                                 // 個数(nH*nV)算出
    bufL = (int*)malloc( sizeof(int) * nHV );                       // 座標バッファーをメモリ確保
    if( bufL == 0 ){                                                // 確保失敗時
        return( STI_MEM );                                          // 左記を返す
    }                                                               // 
    CorrImage88Myself( image, bufL, nStepH, nStepV, nH, nV );       // 自己相関作成
    tA  = tA * tA * 64.0;                                           // 偏差値→判定値
    tB  = tB * tB * 64.0;                                           // 偏差値→判定値
    n   = makeCorrImageMyselfExtend( image, bufXY, bufL, maxN,      // 座標作成
                                nStepH, nStepV, tA, tB, 4, 4 );     // 
    CorrImage88MyselfXY( image, bufXY, buf, n, -4, -4 );            // 詳細自己相関作成
    free( bufL );                                                   // メモリ解放
    return( n );                                                    // 有効個数を返す
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「CorrImage88MyselfExtend()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「88」は、比較する画像の範囲として「縦×横=8×8=
64画素」のサイズを意味します
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* image,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「Extend」は、英単語「extend」、「拡張」を意味します!
詰り、前記した関数「CorrImage88Myself()」の機能を拡張
した関数です!

(B)関数「int CorrImage88MyselfExtend()」の【返値】

実行エラーコードとしては、「STI_MEM」を内部でメモリ
確保失敗した時に返します!正常動作した場合は、処理した
8×8升枠の数を返します!

(C)関数「CorrImage88MyselfExtend()」の【仮引数】

int             CopyClear::CorrImage88MyselfExtend(
    TypeArray*  image,                                              // 画像
    TypeXY*     bufXY,                                              // 結果座標バッファー
    double*     buf,                                                // 結果バッファー
    int         maxN,                                               // 最大結果数
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    double      tA,                                                 // 最小概要しきい値
    double      tB                                                  // 最大概要しきい値
){

「TypeArray* image,」は、対象画像情報
「TypeXY* bufXY,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int maxN,」は、処理する8×8升枠の個数最大の数制限
「int nStepH,」は、8×8升枠の次への水平方向ステップ
「int nStepV,」は、8×8升枠の次への垂直方向ステップ
「double tA,」は、8×8升枠の相関値(分散値)下限で
「double tB」は、上限値で算出した相関値(分散値)が
下限から上限の間に有る様に調整する範囲です!

(D)関数「CorrImage88MyselfExtend()」の【アルゴリズム】

){
    int*        bufL;                                               // 結果バッファー:概要
    int         nH;                                                 // 水平方向個数
    int         nV;                                                 // 垂直方向個数
    int         nHV;                                                // 個数(nH*nV)
    int         n;                                                  // 計測個数

    GetHVCorrImage88Myself( image, nStepH, nStepV, nH, nV );        // 自己相関升目個数
    nHV  = nH * nV;                                                 // 個数(nH*nV)算出
    bufL = (int*)malloc( sizeof(int) * nHV );                       // 座標バッファーをメモリ確保
    if( bufL == 0 ){                                                // 確保失敗時
        return( STI_MEM );                                          // 左記を返す
    }                                                               // 
    CorrImage88Myself( image, bufL, nStepH, nStepV, nH, nV );       // 自己相関作成
    tA  = tA * tA * 64.0;                                           // 偏差値→判定値
    tB  = tB * tB * 64.0;                                           // 偏差値→判定値
    n   = makeCorrImageMyselfExtend( image, bufXY, bufL, maxN,      // 座標作成
                                nStepH, nStepV, tA, tB, 4, 4 );     // 
    CorrImage88MyselfXY( image, bufXY, buf, n, -4, -4 );            // 詳細自己相関作成
    free( bufL );                                                   // メモリ解放
    return( n );                                                    // 有効個数を返す
}

(D-1)ローカル変数

){
    int*        bufL;                                               // 結果バッファー:概要
    int         nH;                                                 // 水平方向個数
    int         nV;                                                 // 垂直方向個数
    int         nHV;                                                // 個数(nH*nV)
    int         n;                                                  // 計測個数

「int* bufL;」は、8×8升枠の相関値(分散値)内部算出
バッファー!
「int nH;」は、8×8升枠の水平方向個数
「int nV;」は、8×8升枠の垂直方向個数
「int nHV;」は、8×8升枠の垂直×方向個数
「int n;」は、結果として計測した8×8升枠の個数!

(D-2)アルゴリズムコード

    GetHVCorrImage88Myself( image, nStepH, nStepV, nH, nV );        // 自己相関升目個数
    nHV  = nH * nV;                                                 // 個数(nH*nV)算出
    bufL = (int*)malloc( sizeof(int) * nHV );                       // 座標バッファーをメモリ確保
    if( bufL == 0 ){                                                // 確保失敗時
        return( STI_MEM );                                          // 左記を返す
    }                                                               // 
    CorrImage88Myself( image, bufL, nStepH, nStepV, nH, nV );       // 自己相関作成
    tA  = tA * tA * 64.0;                                           // 偏差値→判定値
    tB  = tB * tB * 64.0;                                           // 偏差値→判定値
    n   = makeCorrImageMyselfExtend( image, bufXY, bufL, maxN,      // 座標作成
                                nStepH, nStepV, tA, tB, 4, 4 );     // 
    CorrImage88MyselfXY( image, bufXY, buf, n, -4, -4 );            // 詳細自己相関作成
    free( bufL );                                                   // メモリ解放
    return( n );                                                    // 有効個数を返す
}

「GetHVCorrImage88Myself(image,nStepH,nStepV,nH,nV);」
は、サブルーチン関数「GetHVCorrImage88Myself()」で
画像のサイズと水平垂直のステップ数で処理する水平垂直の
8×8升枠の個数算出!
「nHV=nHnV;」は、8×8升枠の垂直×方向個数算出!
「bufL=(int)malloc(sizeof(int)nHV);」は、8×8升枠
の自己相関値(分散値)内部算出用バッファーメモリ確保
「if(bufL==0){return(STI_MEM);}」は、バッファーメモリ
確保に失敗したらエラーコード「STI_MEM」を辺値とし返し
関数終了!
「CorrImage88Myself(image,bufL,nStepH,nStepV,nH,nV);」
は、サブルーチン関数「CorrImage88Myself()」で自己相関
算出!
「tA=tAtA64.0;tB=tBtB64.0;」は、8×8升枠なので
64画素、「tAtA」と自乗しているのは、分散値だから、
仮引数「double tA,double tB」と上下限の値を内部で使用
し易く変換した計算式です!
「n=makeCorrImageMyselfExtend(image,bufXY,bufL,maxN,
nStepH,nStepV,tA,tB,4,4);」は、サブルーチン関数「
makeCorrImageMyselfExtend()」で上下限の値等で自己相関
処理結果を加工し、仮引数「TypeXY* bufXY,」に座標の値を
セットし、有効な個数算出し「n」にセット!
「CorrImage88MyselfXY(image,bufXY,buf,n,-4,-4);」は、
サブルーチン関数「CorrImage88MyselfXY()」で座標指定の
自己相関処理を行い!
「free(bufL);」は、内部で確保したメモリを解放する関数
の後始末!
「return(n);」は、個数を関数辺値とし返し関数終了!

(4-14-174)関数「void CorrImageNM(
TypeArray* pa,
TypeArray* pb,double* buf,
int n,int m,int nStepH,
int nStepV,int& resH,int& resV){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関画像適応                            *****/
/*****      ☆n×mの基本単位毎に画像全体を演算しバッファーに格納☆*****/
/*****      引数返値:水平個数                                      *****/
/*****      引数返値:垂直個数                                      *****/
/************************************************************************/

void            CopyClear::CorrImageNM(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    double*     buf,                                                // 結果バッファー
    int         n,                                                  // n×mのn
    int         m,                                                  // n×mのm
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){
    BYTE*       ptrAX;                                              // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrAY;                                              // A配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅(nStepV単位)
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         minH;                                               // 水平幅の最小値
    int         minV;                                               // 垂直幅の最小値
    int         i;                                                  // カウンタ

    minH = ( pa->h < pb->h ) ? pa->h : pb->h;                       // 水平幅の最小値算出
    minV = ( pa->v < pb->v ) ? pa->v : pb->v;                       // 垂直幅の最小値算出
    if( minH < n || minV < m ){                                     // サイズがn×m未満なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        CorrImageNMLarge( pa, pb, buf, n, m,                        // 左記で処理する
                                    nStepH, nStepV, resH, resV );   // 
        return;                                                     // 
    }                                                               // 
    h     = ( minH - n ) / nStepH;                                  // 水平個数を算出
    v     = ( minV - m ) / nStepV;                                  // 垂直個数を算出
    resH  = h;                                                      // 返値:水平個数
    resV  = v;                                                      // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                         // A配列:処理ポインタ
    ptrBY = (BYTE*)pb->adr;                                         // B配列:処理ポインタ
    incA  = pa->inc * nStepV;                                       // A配列:増加幅(nStepV単位)
    incB  = pb->inc * nStepV;                                       // B配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA, ptrBY += incB ){                // 垂直個数分
        ptrAX = ptrAY;                                              // A配列:水平始点
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH, ptrBX += nStepH ){   // 水平個数分
            *buf++ = CorrNM( ptrAX, ptrBX, pa->inc, pb->inc,        // n×m画素の正規相関を
                                                         n, m );    // 算出しバッファーに格納
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「CorrImageNM()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=N×M画素
」のサイズを意味します★備考★この「NM」は、仮引数「
int n,int m,」で指定した値です!更に★備考★少し前の
方で「CorrImage44()」とか「CorrImage88()」と「NM」で
無く、「44」・「88」が名称に入った関数を解説しました
何故、この様に「NM」で指定すれば同じ機能の関数が使え
るのに専用の「CorrImage44()」・「CorrImage88()」が、
存在するかと言うと使用頻度が多い関数だからです!頻度
が高いと言う事は、高性能化(高速化)する必要が有り、
特化したのです!では、「CorrImageNM()」は、何故、存在
するかと言うと、依り、汎用に使用したり、「44」・「88」
の関数を作成する前にテスト的に色々な組み合わせを研究
に使用したからです!

(B)関数「void CorrImageNM()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「CorrImageNM()」の【仮引数】

void            CopyClear::CorrImageNM(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    double*     buf,                                                // 結果バッファー
    int         n,                                                  // n×mのn
    int         m,                                                  // n×mのm
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){

「TypeArray* pa,」は、比較対象画像A
「TypeArray* pb,」は、比較対象画像B
「double* buf,」は、結果相関値格納バッファー
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「CorrImageNM()」の【アルゴリズム】

){
    BYTE*       ptrAX;                                              // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrAY;                                              // A配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅(nStepV単位)
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         minH;                                               // 水平幅の最小値
    int         minV;                                               // 垂直幅の最小値
    int         i;                                                  // カウンタ

    minH = ( pa->h < pb->h ) ? pa->h : pb->h;                       // 水平幅の最小値算出
    minV = ( pa->v < pb->v ) ? pa->v : pb->v;                       // 垂直幅の最小値算出
    if( minH < n || minV < m ){                                     // サイズがn×m未満なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        CorrImageNMLarge( pa, pb, buf, n, m,                        // 左記で処理する
                                    nStepH, nStepV, resH, resV );   // 
        return;                                                     // 
    }                                                               // 
    h     = ( minH - n ) / nStepH;                                  // 水平個数を算出
    v     = ( minV - m ) / nStepV;                                  // 垂直個数を算出
    resH  = h;                                                      // 返値:水平個数
    resV  = v;                                                      // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                         // A配列:処理ポインタ
    ptrBY = (BYTE*)pb->adr;                                         // B配列:処理ポインタ
    incA  = pa->inc * nStepV;                                       // A配列:増加幅(nStepV単位)
    incB  = pb->inc * nStepV;                                       // B配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA, ptrBY += incB ){                // 垂直個数分
        ptrAX = ptrAY;                                              // A配列:水平始点
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH, ptrBX += nStepH ){   // 水平個数分
            *buf++ = CorrNM( ptrAX, ptrBX, pa->inc, pb->inc,        // n×m画素の正規相関を
                                                         n, m );    // 算出しバッファーに格納
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrAX;                                              // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrAY;                                              // A配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incA;                                               // A配列:増加幅(nStepV単位)
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         minH;                                               // 水平幅の最小値
    int         minV;                                               // 垂直幅の最小値
    int         i;                                                  // カウンタ

「BYTE* ptrAX;」は、A画像用X座標方向処理ポインタ
「BYTE* ptrBX;」は、B画像用X座標方向処理ポインタ
「BYTE* ptrAY;」は、A画像用Y座標方向処理ポインタ
「BYTE* ptrBY;」は、B画像用Y座標方向処理ポインタ
「int incA;」は、A画像増加幅
「int incB;」は、B画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい
「int minH;」は、水平幅の最小値
「int minV;」は、垂直幅の最小値
★備考★上記「int minH;int minV;」は画像自体の
水平垂直幅で、「N×M升枠」を単位とした処理が可能な最小
(有効)画素サイズの算出です!
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    minH = ( pa->h < pb->h ) ? pa->h : pb->h;                       // 水平幅の最小値算出
    minV = ( pa->v < pb->v ) ? pa->v : pb->v;                       // 垂直幅の最小値算出
    if( minH < n || minV < m ){                                     // サイズがn×m未満なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        CorrImageNMLarge( pa, pb, buf, n, m,                        // 左記で処理する
                                    nStepH, nStepV, resH, resV );   // 
        return;                                                     // 
    }                                                               // 
    h     = ( minH - n ) / nStepH;                                  // 水平個数を算出
    v     = ( minV - m ) / nStepV;                                  // 垂直個数を算出
    resH  = h;                                                      // 返値:水平個数
    resV  = v;                                                      // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                         // A配列:処理ポインタ
    ptrBY = (BYTE*)pb->adr;                                         // B配列:処理ポインタ
    incA  = pa->inc * nStepV;                                       // A配列:増加幅(nStepV単位)
    incB  = pb->inc * nStepV;                                       // B配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA, ptrBY += incB ){                // 垂直個数分
        ptrAX = ptrAY;                                              // A配列:水平始点
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH, ptrBX += nStepH ){   // 水平個数分
            *buf++ = CorrNM( ptrAX, ptrBX, pa->inc, pb->inc,        // n×m画素の正規相関を
                                                         n, m );    // 算出しバッファーに格納
        }                                                           // 
    }                                                               // 
}

「minH=((pa->h<pb->h)?pa->h:pb->h);」は、水平画素数の
有効(最小)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v);」は、垂直画素数の
有効(最小)サイズ算出!
「if(minH<n||minV<m){resH=0;resV=0;return;}」は、if
条件「minH<n||minV<m」有効サイズが「N×M」升枠が、
出来無いで「resH=0;resV=0;return;」と水平垂直の処理個
数が0に仮引数辺値にセットし、関数終了!
「if(nm>=65536){CorrImageNMLarge(pa,pb,buf,n,m,
nStepH,nStepV,resH,resV);return;}」は、if条件
「nm>=65536」とN×M升枠のサイズが65536と大き
なサイズで処理時間が掛かる為に対応するサブルーチン関数
「CorrImageNMLarge();」で処理し「return;」で関数終了!
「h=(minH-n)/nStepH;v=(minV-m)/nStepV;resH=h;resV=v;」
は、「N×M」升枠が水平垂直に何個有るか「h・v」に算出
し仮引数「int &resH,int &resV」に辺値としセット!
「ptrAY=(BYTE*)pa->adr;ptrBY=(BYTE*)pb->adr;」は、処理
し易い様にY座標方向始点をポインタ変数にセット!
「incA=pa->incnStepV;incB=pb->incnStepV;」は、画素
単位の「N×M」升枠でのポインタ増加幅を算出しセット!
次は、処理する二重ループで
「for(;--v>=0;ptrAY+=incA,ptrBY+=incB){・・外側ループ
本体・・}」は、ループ条件「--v>=0;」と良くこの解説で
説明して居る≪「--v」と値が変っても良い変数をダウンカ
ウンタに使用する事で教科書的な記述よりも現実のコンパイ
ラ環境で依り高速な機械コード(アセンブラ出力で確認)が
生成されるので私のソースコードでは多く採用≫とループ
本体終了後の処理「ptrAY+=incA,ptrBY+=incB」が、次の
X座標方向始点へ渡す為のY座標方向ポインタを垂直方向に
増加している!そして外側ループ本体
「ptrAX=ptrAY;ptrBX=ptrBY;」は、X座標方向始点を
ポインタ変数にセット!
「for(i=h;--i>=0;ptrAX+=nStepH,ptrBX+=nStepH){・・内側
ループ本体・・}」は、for構文の初期化「i=h;」で
ループカウンタ「i」をダウンカウンタとしセットし、ルー
プ条件「--i>=0;」と良くこの解説で説明して居る≪「--i」
と値が変っても良い変数をダウンカウンタに使用する事で
教科書的な記述よりも現実のコンパイラ環境で依り高速な
機械コード(アセンブラ出力で確認)が生成されるので私の
ソースコードでは多く採用≫とループ本体終了後の処理
「ptrAX+=nStepH,ptrBX+=nStepH」が、X座標方向ポインタ
を水平方向に増加している!そして内側ループ本体
「*buf++=CorrNM(ptrAX,ptrBX,pa->inc,pb->inc,n, m);」
は、サブルーチン関数「CorrNM()」で「N×M」升枠で
相関値を算出し「*buf++=・・」とバッファーに追加格納!
★備考★往々にして二次元の画像を二重ループで処理する
極標準的なループの組み合わせですので良く他の処理でも
基本的な処理として使用しています!

(4-14-175)関数「void GetHVCorrImageNM(
TypeArray* pa,TypeArray* pb,
int n,int m,int nStepH,
int nStepV,int& resH,int& resV){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関画像適応用升目の個数取得            *****/
/*****      引数返値:水平個数                                      *****/
/*****      引数返値:垂直個数                                      *****/
/************************************************************************/

void            CopyClear::GetHVCorrImageNM(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    int         n,                                                  // n×mのn
    int         m,                                                  // n×mのm
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         minH;                                               // 水平幅の最小値
    int         minV;                                               // 垂直幅の最小値

    minH = ( pa->h < pb->h ) ? pa->h : pb->h;                       // 水平幅の最小値算出
    minV = ( pa->v < pb->v ) ? pa->v : pb->v;                       // 垂直幅の最小値算出
    if( minH < n || minV < m ){                                     // サイズがn×m未満なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    h    = ( minH - n ) / nStepH;                                   // 水平個数を算出
    v    = ( minV - m ) / nStepV;                                   // 垂直個数を算出
    resH = h;                                                       // 返値:水平個数
    resV = v;                                                       // 返値:垂直個数
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「GetHVCorrImageNM()」の【関数名】

「Get」は、カタカナ語でもゲット、詰り取得するで
「HV」は、水平・垂直方向の個数を意味します!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対してを算出する関数「CorrImageNM()」を意味≫し、
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=N×M画素
」のサイズを意味します★備考★この「NM」は、仮引数「
int n,int m,」で指定した値です!更に★備考★少し前の
方で「GetHVCorrImage44()」とか「GetHVCorrImage88()」と
「NM」で無く、「44」・「88」が名称に入った関数を解説
しました、何故、この様に「NM」で指定すれば同じ機能の
関数が使えるのに専用の「GetHVCorrImage44()」・
「GetHVCorrImage88()」が、存在するかと言うと使用頻度が
多い関数だからです!頻度が高いと言う事は、高性能化(
高速化)する必要が有り、特化したのです!では、
「GetHVCorrImageNM()」は、何故、存在するかと言うと、
依り、汎用に使用したり、「44」・「88」の関数を作成する
前にテスト的に色々な組み合わせを研究に使用したからで
す!この関数「GetHVCorrImageNM()」は、その補助関数として関数「CorrImageNM()」の前に仮引数「int &resH,
int &resV」で水平垂直方向の結果個数を事前算出する事を
行います!

(B)関数「void GetHVCorrImageNM()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「GetHVCorrImageNM()」の【仮引数】

void            CopyClear::GetHVCorrImageNM(
    TypeArray*  pa,                                                 // A配列
    TypeArray*  pb,                                                 // B配列
    int         n,                                                  // n×mのn
    int         m,                                                  // n×mのm
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){

「TypeArray* pa,」は、比較対象画像A
「TypeArray* pb,」は、比較対象画像B
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「GetHVCorrImageNM()」の【アルゴリズム】

){
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         minH;                                               // 水平幅の最小値
    int         minV;                                               // 垂直幅の最小値

    minH = ( pa->h < pb->h ) ? pa->h : pb->h;                       // 水平幅の最小値算出
    minV = ( pa->v < pb->v ) ? pa->v : pb->v;                       // 垂直幅の最小値算出
    if( minH < n || minV < m ){                                     // サイズがn×m未満なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    h    = ( minH - n ) / nStepH;                                   // 水平個数を算出
    v    = ( minV - m ) / nStepV;                                   // 垂直個数を算出
    resH = h;                                                       // 返値:水平個数
    resV = v;                                                       // 返値:垂直個数
}

(D-1)ローカル変数

){
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         minH;                                               // 水平幅の最小値
    int         minV;                                               // 垂直幅の最小値

「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい
「int minH;」は、水平幅の最小値
「int minV;」は、垂直幅の最小値
★備考★上記「int minH;int minV;」は画像自体の
水平垂直幅で、「N×M升枠」を単位とした処理が可能な最小
(有効)画素サイズの算出です!

(D-2)アルゴリズムコード

    minH = ( pa->h < pb->h ) ? pa->h : pb->h;                       // 水平幅の最小値算出
    minV = ( pa->v < pb->v ) ? pa->v : pb->v;                       // 垂直幅の最小値算出
    if( minH < n || minV < m ){                                     // サイズがn×m未満なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    h    = ( minH - n ) / nStepH;                                   // 水平個数を算出
    v    = ( minV - m ) / nStepV;                                   // 垂直個数を算出
    resH = h;                                                       // 返値:水平個数
    resV = v;                                                       // 返値:垂直個数
}

「minH=((pa->h<pb->h)?pa->h:pb->h);」は、水平画素数の
有効(最小)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v);」は、垂直画素数の
有効(最小)サイズ算出!
「if(minH<n||minV<m){resH=0;resV=0;return;}」は、if
条件「minH<n||minV<m」有効サイズが「N×M」升枠が、
出来無いで「resH=0;resV=0;return;」と水平垂直の処理個
数が0に仮引数辺値にセットし、関数終了!
「h=(minH-n)/nStepH;v=(minV-m)/nStepV;resH=h;resV=v;」
は、「N×M」升枠が水平垂直に何個有るか「h・v」に算出
し仮引数「int &resH,int &resV」に辺値としセット!
★備考★関数「CorrImageNM()」で仮引数「double* buf,」
とバッファーを動的に必要なサイズ用意する必要が有るの
で、この関数で仮引数「int &resH,int &resV」で水平垂直
方向の結果個数を算出する事で用意しする事にしています!

(4-14-176)関数「void AverageImageNM(
TypeArray* pa,BYTE* buf,
int n,int m,int nStepH,
int nStepV,int& resH,int& resV){・・・}」

/************************************************************************/
/*****      n×m画素画像平均                                      *****/
/*****      ☆n×mの基本単位毎に画像全体を演算しバッファーに格納☆*****/
/*****      引数返値:水平個数                                      *****/
/*****      引数返値:垂直個数                                      *****/
/************************************************************************/

void            CopyClear::AverageImageNM(
    TypeArray*  pa,                                         // A配列
    BYTE*       buf,                                        // 結果バッファー
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         i;                                          // カウンタ

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = (int)AveNM( ptrAX, pa->inc, n, m );    // n×m画素平均算出
        }                                                   // 
    }                                                       // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「AverageImageNM()」の【関数名】

「Average」は、英単語「Average」で「平均値」を意味
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として
「縦×横=N×M画素」のサイズを意味します

(B)関数「void AverageImageNM()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「AverageImageNM()」の【仮引数】

void            CopyClear::AverageImageNM(
    TypeArray*  pa,                                         // A配列
    BYTE*       buf,                                        // 結果バッファー
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){

「TypeArray* pa,」は、処理対象画像
「BYTE* buf,」は、平均値格納バッファー
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「AverageImageNM()」の【アルゴリズム】

){
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         i;                                          // カウンタ

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = (int)AveNM( ptrAX, pa->inc, n, m );    // n×m画素平均算出
        }                                                   // 
    }                                                       // 
}

(D-1)ローカル変数

){
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         i;                                          // カウンタ

「BYTE* ptrAX;」は、画像用X座標方向処理ポインタ
「BYTE* ptrAY;」は、画像用Y座標方向処理ポインタ
「int incA;」は、画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = (int)AveNM( ptrAX, pa->inc, n, m );    // n×m画素平均算出
        }                                                   // 
    }                                                       // 
}

「if(pa->h<n||pa->v<m){resH=0;resV=0;return;}」は、
if条件「pa->h<n||pa->v<m」有効サイズが「N×M」升枠
が、出来無いで「resH=0;resV=0;return;」と
水平垂直の処理個数が0に仮引数辺値にセットし、
関数終了!
「h=(pa->h-n)/nStepH;v=(pa->v-m)/nStepV;」
は、「N×M」升枠が水平垂直に何個有るか「h・v」に算出
し仮引数「int &resH,int &resV」に辺値としセット!
「ptrAY=(BYTE*)pa->adr;」は、処理し易い様にY座標方向
始点をポインタ変数にセット!
「incA=pa->inc*nStepV;」は、画素単位の「N×M」升枠
でのポインタ増加幅を算出しセット!
次は、処理する二重ループで
「for(;--v>=0;ptrAY+=incA){・・外側ループ本体・・}」は
ループ条件「--v>=0;」と良くこの解説で説明して居る≪
「--v」と値が変っても良い変数をダウンカウンタに使用
する事で教科書的な記述よりも現実のコンパイラ環境で依り
高速な機械コード(アセンブラ出力で確認)が生成されるの
で私のソースコードでは多く採用≫とループ本体終了後の
処理「ptrAY+=incA」が、次のX座標方向始点へ渡す為の
Y座標方向ポインタを垂直方向に増加している!そして外側
ループ本体「ptrAX=ptrAY;」は、X座標方向始点をポインタ
変数にセット!
「for(i=h;--i>=0;ptrAX+=nStepH){・・内側ループ本体・・
}」は、for構文の初期化「i=h;」でループカウンタ「i」
をダウンカウンタとしセットし、ループ条件「--i>=0;」と
良くこの解説で説明して居る≪「--i」と値が変っても良い
変数をダウンカウンタに使用する事で教科書的な記述よりも
現実のコンパイラ環境で依り高速な機械コード(アセンブラ
出力で確認)が生成されるので私のソースコードでは多く
採用≫とループ本体終了後の処理「ptrAX+=nStepH」が、
X座標方向ポインタを水平方向に増加している!そして内側
ループ本体
「*buf++=(int)AveNM(ptrAX,pa->inc,n,m);」は、サブルー
チン関数「AveNM(・・,n,m)」で「N×M」升枠で平均値を
算出し「*buf++=・・」とバッファーに「(int)」と整数型に
型変換≪小数点以下は切り捨て≫追加格納!
★備考★往々にして二次元の画像を二重ループで処理する
極標準的なループの組み合わせですので良く他の処理でも
基本的な処理として使用しています!

(4-14-177)関数「void AverageImageNM(
TypeArray* pa,double* buf,
int n,int m,int nStepH,
int nStepV,int& resH,int& resV){・・・}」

/************************************************************************/
/*****      n×m画素画像平均                                      *****/
/*****      ☆n×mの基本単位毎に画像全体を演算しバッファーに格納☆*****/
/*****      引数返値:水平個数                                      *****/
/*****      引数返値:垂直個数                                      *****/
/************************************************************************/

void            CopyClear::AverageImageNM(
    TypeArray*  pa,                                         // A配列
    double*     buf,                                        // 結果バッファー
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         i;                                          // カウンタ

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = AveNM( ptrAX, pa->inc, n, m );         // n×m画素平均算出
        }                                                   // 
    }                                                       // 
}

☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「AverageImageNM()」の【関数名】

「Average」は、英単語「Average」で「平均値」を意味
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×M=
64画素」のサイズを意味します

(B)関数「void AverageImageNM()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「AverageImageNM()」の【仮引数】

void            CopyClear::AverageImageNM(
    TypeArray*  pa,                                         // A配列
    double*     buf,                                        // 結果バッファー
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){

「TypeArray* pa,」は、処理対象画像
「double* buf,」は、平均値格納バッファー
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「AverageImageNM()」の【アルゴリズム】

){
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         i;                                          // カウンタ

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = AveNM( ptrAX, pa->inc, n, m );         // n×m画素平均算出
        }                                                   // 
    }                                                       // 
}

(D-1)ローカル変数

){
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         i;                                          // カウンタ

「BYTE* ptrAX;」は、画像用X座標方向処理ポインタ
「BYTE* ptrAY;」は、画像用Y座標方向処理ポインタ
「int incA;」は、画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = AveNM( ptrAX, pa->inc, n, m );         // n×m画素平均算出
        }                                                   // 
    }                                                       // 
}

「if(pa->h<n||pa->v<m){resH=0;resV=0;return;}」は、
if条件「pa->h<n||pa->v<m」有効サイズが「N×M」升枠
が、出来無いで「resH=0;resV=0;return;resH=h;resV=v;」と
水平垂直の処理個数が0に仮引数辺値にセットし、
関数終了!
「h=(pa->h-n)/nStepH;v=(pa->v-m)/nStepV;」
は、「N×M」升枠が水平垂直に何個有るか「h・v」に算出
し仮引数「int &resH,int &resV」に辺値としセット!
「ptrAY=(BYTE*)pa->adr;」は、処理し易い様にY座標方向
始点をポインタ変数にセット!
「incA=pa->inc*nStepV;」は、画素単位の「N×M」升枠
でのポインタ増加幅を算出しセット!
次は、処理する二重ループで
「for(;--v>=0;ptrAY+=incA){・・外側ループ本体・・}」は
ループ条件「--v>=0;」と良くこの解説で説明して居る≪
「--v」と値が変っても良い変数をダウンカウンタに使用
する事で教科書的な記述よりも現実のコンパイラ環境で依り
高速な機械コード(アセンブラ出力で確認)が生成されるの
で私のソースコードでは多く採用≫とループ本体終了後の
処理「ptrAY+=incA」が、次のX座標方向始点へ渡す為の
Y座標方向ポインタを垂直方向に増加している!そして外側
ループ本体「ptrAX=ptrAY;」は、X座標方向始点をポインタ
変数にセット!
「for(i=h;--i>=0;ptrAX+=nStepH){・・内側ループ本体・・
}」は、for構文の初期化「i=h;」でループカウンタ「i」
をダウンカウンタとしセットし、ループ条件「--i>=0;」と
良くこの解説で説明して居る≪「--i」と値が変っても良い
変数をダウンカウンタに使用する事で教科書的な記述よりも
現実のコンパイラ環境で依り高速な機械コード(アセンブラ
出力で確認)が生成されるので私のソースコードでは多く
採用≫とループ本体終了後の処理「ptrAX+=nStepH」が、
X座標方向ポインタを水平方向に増加している!そして内側
ループ本体「*buf++=AveNM(ptrAX,pa->inc,n,m);」は、
サブルーチン関数「AveNM(・・,n,m)」で「N×M」升枠で
平均値を算出し「*buf++=・・」とバッファーに追加格納!
★備考★往々にして二次元の画像を二重ループで処理する
極標準的なループの組み合わせですので良く他の処理でも
基本的な処理として使用しています!

(4-14-178)関数「void CorrImageNMMyself(
TypeArray* pa,int* buf,
int n,int m,int nStepH,
int nStepV,int &resH,int &resV){・・・}」

/************************************************************************/
/*****      n×m画素自己相関画像適応                              *****/
/*****      ☆n×mの基本単位毎に画像全体を演算しバッファーに格納☆*****/
/*****      引数返値:水平個数                                      *****/
/*****      引数返値:垂直個数                                      *****/
/************************************************************************/

void            CopyClear::CorrImageNMMyself(
    TypeArray*  pa,                                         // A配列
    int*        buf,                                        // 結果バッファー
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){
    double*     temp;                                       // 一時バッファー
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         nm;                                         // n×mの値
    double      d;                                          // データ
    int         i;                                          // カウンタ

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    nm = n * m;                                             // n×m算出
    if( nm >= 65536 ){                                      // n×mが整数での内部演算を超える時
        temp = (double*)malloc( sizeof(double) * nm );      // 一時バッファー確保
        if( temp == 0 ){                                    // 確保失敗時は
            return;                                         // 終了
        }                                                   //
        CorrImageNMLargeMyself( pa, temp, n, m,             // 左記で処理する
                            nStepH, nStepV, resH, resV );   //
        for( i = 0; i < nm; i++ ){                          // 結果全体を
            d = *temp++;                                    // 値を取り出し
            if( d > 2147483647.0 ){                         // 整数で格納限度なら
                d = 2147483647;                             // 限度内に補正し
            }                                               //
            *buf++ = (int)d;                                // ここでの結果にする
        }                                                   //
        free( temp );                                       // 一時バッファー解放
        return;                                             // 
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = CorrNMMyself( ptrAX, pa->inc, n, m );  // n×m画素自己相関算出
        }                                                   // 
    }                                                       // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「CorrImageNMMyself()」の【関数名】

「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を整数型で算出しますのでモット大きな整数値に成ります!
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=N×M画素」のサイズを意味します
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!

(B)関数「void CorrImageNMMyself()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「CorrImageNMMyself()」の【仮引数】

void            CopyClear::CorrImageNMMyself(
    TypeArray*  pa,                                         // A配列
    int*        buf,                                        // 結果バッファー
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){

「TypeArray* pa,」は、処理対象画像
「int* buf,」は、自己相関値格納バッファー
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「CorrImageNMMyself()」の【アルゴリズム】

){
    double*     temp;                                       // 一時バッファー
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         nm;                                         // n×mの値
    double      d;                                          // データ
    int         i;                                          // カウンタ

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    nm = n * m;                                             // n×m算出
    if( nm >= 65536 ){                                      // n×mが整数での内部演算を超える時
        temp = (double*)malloc( sizeof(double) * nm );      // 一時バッファー確保
        if( temp == 0 ){                                    // 確保失敗時は
            return;                                         // 終了
        }                                                   //
        CorrImageNMLargeMyself( pa, temp, n, m,             // 左記で処理する
                            nStepH, nStepV, resH, resV );   //
        for( i = 0; i < nm; i++ ){                          // 結果全体を
            d = *temp++;                                    // 値を取り出し
            if( d > 2147483647.0 ){                         // 整数で格納限度なら
                d = 2147483647;                             // 限度内に補正し
            }                                               //
            *buf++ = (int)d;                                // ここでの結果にする
        }                                                   //
        free( temp );                                       // 一時バッファー解放
        return;                                             // 
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = CorrNMMyself( ptrAX, pa->inc, n, m );  // n×m画素自己相関算出
        }                                                   // 
    }                                                       // 
}

(D-1)ローカル変数

){
    double*     temp;                                       // 一時バッファー
    BYTE*       ptrAX;                                      // A配列:処理ポインタ
    BYTE*       ptrAY;                                      // A配列:処理ポインタ
    int         incA;                                       // A配列:増加幅(nStepV単位)
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)
    int         nm;                                         // n×mの値
    double      d;                                          // データ
    int         i;                                          // カウンタ

「double* temp;」は、一時的に使用するバッファー
「BYTE* ptrAX;」は、画像用X座標方向処理ポインタ
「BYTE* ptrAY;」は、画像用Y座標方向処理ポインタ
「int incA;」は、画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい
「int nm;」は、「n×m」の計算値!
「double d;」は、個別のバッファー格納からの取出し値
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    nm = n * m;                                             // n×m算出
    if( nm >= 65536 ){                                      // n×mが整数での内部演算を超える時
        temp = (double*)malloc( sizeof(double) * nm );      // 一時バッファー確保
        if( temp == 0 ){                                    // 確保失敗時は
            return;                                         // 終了
        }                                                   //
        CorrImageNMLargeMyself( pa, temp, n, m,             // 左記で処理する
                            nStepH, nStepV, resH, resV );   //
        for( i = 0; i < nm; i++ ){                          // 結果全体を
            d = *temp++;                                    // 値を取り出し
            if( d > 2147483647.0 ){                         // 整数で格納限度なら
                d = 2147483647;                             // 限度内に補正し
            }                                               //
            *buf++ = (int)d;                                // ここでの結果にする
        }                                                   //
        free( temp );                                       // 一時バッファー解放
        return;                                             // 
    }                                                       // 
    h     = ( pa->h - n ) / nStepH;                         // 水平個数を算出
    v     = ( pa->v - m ) / nStepV;                         // 垂直個数を算出
    resH  = h;                                              // 返値:水平個数
    resV  = v;                                              // 返値:垂直個数
    ptrAY = (BYTE*)pa->adr;                                 // A配列:処理ポインタ
    incA  = pa->inc * nStepV;                               // A配列:増加幅(nStepV単位)
    for( ; --v >= 0; ptrAY += incA ){                       // 垂直個数分
        ptrAX = ptrAY;                                      // A配列:水平始点
        for( i = h; --i >= 0; ptrAX += nStepH ){            // 水平個数分
            *buf++ = CorrNMMyself( ptrAX, pa->inc, n, m );  // n×m画素自己相関算出
        }                                                   // 
    }                                                       // 
}

「if(pa->h<n||pa->v<m){resH=0;resV=0;return;}」は、
if条件「pa->h<n||pa->v<m」で画像サイズがN×M升枠
未満の場合、引数辺値「resH=0;resV=0」と枠の数が0を
返し!関数終了!
「nm=nm;」は、N×Mの値算出、
「if(nm>=65536){・・成立中身・・}」は、if条件
「nm>=65536」でN×Mサイズが大きい場合の専用処理とし
「temp=(double)malloc(sizeof(double)*nm);」で
バッファーをメモリ確保し、「if(temp==0){return;}」で
メモリ確保に失敗したら、関数終了!成功したら続けて
「CorrImageNMLargeMyself(pa,temp,n,m,nStepH,nStepV,
resH,resV);」とサブルーチン関数
「CorrImageNMLargeMyself()」で処理し、
「for(i=0;i<nm;i++){・・ループ中身・・}」で
forループ「i=0;i<nm;i++」と極、教科書的な繰り返し
で「nm」回繰り返し、ループ中身「d=*temp++;
if(d>2147483647.0){d=2147483647;}buf++=(int)d;」と
まず、「d=temp++;」でバッファーの値を一単位取出し、
「if(d>2147483647.0){d=2147483647;}」で「2147483647=
int型(符号付32ビット整数)の自然数最大値」を越えた
時は、「d=2147483647;」と「2147483647」に抑える!
「buf++=(int)d;」で仮引数「int buf,」へ自己相関値
格納バッファーに格納!
「free(temp);return;」で一時バッファーを後片付け
解放し、関数終了!
「h=(pa->h-n)/nStepH;v=(pa->v-m)/nStepV;
resH=h;resV=v;」は、「N×M」升枠が水平垂直に何個有る
か「h・v」に算出し仮引数「int &resH,int &resV」に辺値
としセット!
「ptrAY=(BYTE)pa->adr;」は、画像用Y座標方向処理
ポインタをセットし、
「incA=pa->incnStepV;」は、垂直方向の増加幅をセット「for(;--v>=0;ptrAY+=incA){・・外側ループ本体・・}」は
ループ条件「--v>=0;」と良くこの解説で説明して居る≪
「--v」と値が変っても良い変数をダウンカウンタに使用
する事で教科書的な記述よりも現実のコンパイラ環境で依り
高速な機械コード(アセンブラ出力で確認)が生成されるの
で私のソースコードでは多く採用≫とループ本体終了後の
処理「ptrAY+=incA」が、次のX座標方向始点へ渡す為の
Y座標方向ポインタを垂直方向に増加している!そして外側
ループ本体「ptrAX=ptrAY;」は、X座標方向始点をポインタ
変数にセット!
「for(i=h;--i>=0;ptrAX+=nStepH){・・内側ループ本体・・
}」は、for構文の初期化「i=h;」でループカウンタ「i」
をダウンカウンタとしセットし、ループ条件「--i>=0;」と
良くこの解説で説明して居る≪「--i」と値が変っても良い
変数をダウンカウンタに使用する事で教科書的な記述よりも
現実のコンパイラ環境で依り高速な機械コード(アセンブラ
出力で確認)が生成されるので私のソースコードでは多く
採用≫とループ本体終了後の処理「ptrAX+=nStepH」が、
X座標方向ポインタを水平方向に増加している!そして内側
ループ本体
「*buf++=CorrNMMyself(ptrAX,pa->inc,n,m);」は、サブ
ルーチン関数「CorrNMMyself()」で「N×M」升枠で分散値を
算出し「*buf++=・・」とバッファーに追加格納!
★備考★往々にして二次元の画像を二重ループで処理する
極標準的なループの組み合わせですので良く他の処理でも
基本的な処理として使用しています!

(4-14-179)関数「void GetHVCorrImageNMMyself(TypeArray* pa,int n,int m,int nStepH,int nStepV,int &resH,int &resV){・・・}」

/************************************************************************/
/*****      n×m画素自己相関画像適応用升目の個数取得              *****/
/*****      引数返値:水平個数                                      *****/
/*****      引数返値:垂直個数                                      *****/
/************************************************************************/

void            CopyClear::GetHVCorrImageNMMyself(
    TypeArray*  pa,                                         // A配列
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h    = ( pa->h - n ) / nStepH;                          // 水平個数を算出
    v    = ( pa->v - m ) / nStepV;                          // 垂直個数を算出
    resH = h;                                               // 返値:水平個数
    resV = v;                                               // 返値:垂直個数
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「GetHVCorrImageNMMyself()」の【関数名】

「Get」は、カタカナ語でもゲット、詰り取得するで
「HV」は、水平・垂直方向の個数を意味します!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★この「NM」は、仮引数「
int n,int m,」で指定した値です!更に★備考★少し前の
方で「GetHVCorrImage44Myself()」とか
「GetHVCorrImage88Myself()」と「NM」で無く、
「44」・「88」が名称に入った関数を解説しました、
何故、この様に「NM」で指定すれば同じ機能の関数が
使えるのに専用の「GetHVCorrImage44Myself()」・
「GetHVCorrImage88Myself()」が、存在するかと言うと
使用頻度が多い関数だからです!頻度が高いと言う事は、
高性能化(高速化)する必要が有り、特化したのです!
では、「GetHVCorrImageNMMyself()」は、何故、存在する
かと言うと、依り、汎用に使用したり、「44」・「88」の
関数を作成する前にテスト的に色々な組み合わせを研究に
使用したからです!この関数「GetHVCorrImageNMMyself()」
は、その補助関数として関数「CorrImageNMMyself()」の
前に仮引数「int &resH,int &resV」で水平垂直方向の結果
個数を事前算出する事を行います!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!

(B)関数「void GetHVCorrImageNMMyself()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「GetHVCorrImageNMMyself()」の【仮引数】

void            CopyClear::GetHVCorrImageNMMyself(
    TypeArray*  pa,                                         // A配列
    int         n,                                          // n×mのn
    int         m,                                          // n×mのm
    int         nStepH,                                     // 水平方向次点ステップ数
    int         nStepV,                                     // 垂直方向次点ステップ数
    int&        resH,                                       // 返値:取得する水平個数
    int&        resV                                        // 返値:取得する垂直個数
){

「TypeArray* pa,」は、処理対象画像
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「GetHVCorrImageNMMyself()」の【アルゴリズム】

){
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h    = ( pa->h - n ) / nStepH;                          // 水平個数を算出
    v    = ( pa->v - m ) / nStepV;                          // 垂直個数を算出
    resH = h;                                               // 返値:水平個数
    resV = v;                                               // 返値:垂直個数
}

(D-1)ローカル変数

){
    int         h;                                          // 水平幅(n×mの個数)
    int         v;                                          // 垂直幅(n×mの個数)

「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい

(D-2)アルゴリズムコード

    if( pa->h < n || pa->v < m ){                           // サイズがn×m未満なら
        resH = 0;                                           // 個数の返事を0にして
        resV = 0;                                           // 
        return;                                             // 終了
    }                                                       // 
    h    = ( pa->h - n ) / nStepH;                          // 水平個数を算出
    v    = ( pa->v - m ) / nStepV;                          // 垂直個数を算出
    resH = h;                                               // 返値:水平個数
    resV = v;                                               // 返値:垂直個数
}

「if(pa->h<n||pa->v<m){resH=0;resV=0;return;}」は、
if条件「pa->h<n||pa->v<m」で画像サイズがN×M升枠
未満の場合、引数辺値「resH=0;resV=0」と枠の数が0を
返し!関数終了!
「h=(pa->h-n)/nStepH;v=(pa->v-m)/nStepV;
resH=h;resV=v;」は、「N×M」升枠が水平垂直に何個有る
か「h・v」に算出し仮引数「int &resH,int &resV」に辺値
としセット!

(4-14-180)関数「void SearchCorrImageNM(
TypeArray* pa,
TypeArray* pb,double* buf,
int n,int m,int nStepH,
int nStepV,int &resH,int &resV){・・・}

/****************************************************************************/
/*****      n×m画素正規化相関サーチ画像適応                          *****/
/*****      ☆n×mの基本単位毎に画像をサーチし結果をバッファーに格納☆*****/
/*****      引数返値:水平個数                                          *****/
/*****      引数返値:垂直個数                                          *****/
/****************************************************************************/

void            CopyClear::SearchCorrImageNM(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    double*     buf,                                                // 結果バッファー
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    int         i;                                                  // カウンタ
    int         j;                                                  // カウンタ

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        SearchCorrImageNMLarge( pa, pb, buf, n, m,                  // 左記で処理する
                                    nStepH, nStepV, resH, resV );   // 
        return;                                                     // 
    }                                                               // 
    h      = ( pb->h - n ) / nStepH;                                // 水平個数を算出
    v      = ( pb->v - m ) / nStepV;                                // 垂直個数を算出
    resH   = h;                                                     // 返値:水平個数
    resV   = v;                                                     // 返値:垂直個数
    ptrA   = (BYTE*)pa->adr;                                        // A配列:処理ポインタ
    ptrBY  = (BYTE*)pb->adr;                                        // B配列:処理ポインタ
    incB   = pb->inc * nStepV;                                      // B配列:増加幅(nStepV単位)
    *buf++ = CorrNMFirst( ptrA, ptrBY, pa->inc, pb->inc, n, m,      // 先頭の時の相関値算出
                                                avA, avB, sumA );   // 
    for( i = 0; i < v; i++, ptrBY += incB ){                        // 垂直個数分
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( j = 0; j < h; j++, ptrBX += nStepH ){                  // 水平個数分
            if( !( i == 0 && j == 0 ) ){                            // 先頭以外ならば
                *buf++ = CorrNMSecond( ptrA, ptrBX,                 // n×m画素の正規相関を
                                            pa->inc, pb->inc,       // 算出しバッファーに格納
                                            n, m, avA, avB, sumA ); // 
            }                                                       // 
        }                                                           // 
    }                                                               // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「SearchCorrImageNM()」の【関数名】

「Search」は、英単語「Search」で「探す・探索」です!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=
N×M画素」のサイズを意味します!

(B)関数「void SearchCorrImageNM()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「SearchCorrImageNM()」の【仮引数】

void            CopyClear::SearchCorrImageNM(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    double*     buf,                                                // 結果バッファー
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){

「TypeArray* pa,」は、比較対象画像A≪テンプレート画像≫
「TypeArray* pb,」は、比較対象画像B≪サーチ対象画像≫
「double* buf,」は、結果格納バッファー
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「SearchCorrImageNM()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    int         i;                                                  // カウンタ
    int         j;                                                  // カウンタ

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        SearchCorrImageNMLarge( pa, pb, buf, n, m,                  // 左記で処理する
                                    nStepH, nStepV, resH, resV );   // 
        return;                                                     // 
    }                                                               // 
    h      = ( pb->h - n ) / nStepH;                                // 水平個数を算出
    v      = ( pb->v - m ) / nStepV;                                // 垂直個数を算出
    resH   = h;                                                     // 返値:水平個数
    resV   = v;                                                     // 返値:垂直個数
    ptrA   = (BYTE*)pa->adr;                                        // A配列:処理ポインタ
    ptrBY  = (BYTE*)pb->adr;                                        // B配列:処理ポインタ
    incB   = pb->inc * nStepV;                                      // B配列:増加幅(nStepV単位)
    *buf++ = CorrNMFirst( ptrA, ptrBY, pa->inc, pb->inc, n, m,      // 先頭の時の相関値算出
                                                avA, avB, sumA );   // 
    for( i = 0; i < v; i++, ptrBY += incB ){                        // 垂直個数分
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( j = 0; j < h; j++, ptrBX += nStepH ){                  // 水平個数分
            if( !( i == 0 && j == 0 ) ){                            // 先頭以外ならば
                *buf++ = CorrNMSecond( ptrA, ptrBX,                 // n×m画素の正規相関を
                                            pa->inc, pb->inc,       // 算出しバッファーに格納
                                            n, m, avA, avB, sumA ); // 
            }                                                       // 
        }                                                           // 
    }                                                               // 
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    int         i;                                                  // カウンタ
    int         j;                                                  // カウンタ

「BYTE* ptrA;」は、A画像用処理ポインタ
「BYTE* ptrBX;」は、B画像用X座標方向処理ポインタ
「BYTE* ptrBY;」は、B画像用Y座標方向処理ポインタ
「int incB;」は、B画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int sumA;」は、A画像用合計値、及び分散値算出用
「int avA;」は、A画像平均値
「int avB;」は、B画像平均値
「int i;」は、ループカウンタ外側
「int j;」は、ループカウンタ内側
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい

(D-2)アルゴリズムコード

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        SearchCorrImageNMLarge( pa, pb, buf, n, m,                  // 左記で処理する
                                    nStepH, nStepV, resH, resV );   // 
        return;                                                     // 
    }                                                               // 
    h      = ( pb->h - n ) / nStepH;                                // 水平個数を算出
    v      = ( pb->v - m ) / nStepV;                                // 垂直個数を算出
    resH   = h;                                                     // 返値:水平個数
    resV   = v;                                                     // 返値:垂直個数
    ptrA   = (BYTE*)pa->adr;                                        // A配列:処理ポインタ
    ptrBY  = (BYTE*)pb->adr;                                        // B配列:処理ポインタ
    incB   = pb->inc * nStepV;                                      // B配列:増加幅(nStepV単位)
    *buf++ = CorrNMFirst( ptrA, ptrBY, pa->inc, pb->inc, n, m,      // 先頭の時の相関値算出
                                                avA, avB, sumA );   // 
    for( i = 0; i < v; i++, ptrBY += incB ){                        // 垂直個数分
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( j = 0; j < h; j++, ptrBX += nStepH ){                  // 水平個数分
            if( !( i == 0 && j == 0 ) ){                            // 先頭以外ならば
                *buf++ = CorrNMSecond( ptrA, ptrBX,                 // n×m画素の正規相関を
                                            pa->inc, pb->inc,       // 算出しバッファーに格納
                                            n, m, avA, avB, sumA ); // 
            }                                                       // 
        }                                                           // 
    }                                                               // 
}

「n=(n<pa->h)?n:pa->h;m=(m<pa->v)?m:pa->v;」は、
A画像(テンプレート画像)のサイズと仮引数
「int n;int m;」の小さい方をN×Mとする様に調整!
「if(pb->h<n||pb->v<m){resH=0;resV=0;return;}」は、
B画像(サーチ対象画像)の画像サイズがN×Mより小さい
場合「resH=0;resV=0;return;」結果個数を0にして
関数終了!
「if(nm>=65536){・・成立中身・・}」は、if条件
「nm>=65536」でN×Mサイズが大きい場合の専用処理
とし「SearchCorrImageNMLarge(pa,pb,buf,n,m,nStepH,
nStepV,resH,resV);」とサブルーチン関数
「SearchCorrImageNMLarge()」で専用関数で処理し、
「return;」で関数終了!
「h=(pb->h-n)/nStepH;v=(pb->v-m)/nStepV;」は、
B画像の中にN×M升枠の個数を「int h;int v;」に算出
し格納!
「resH=h;resV=v;」は、引数辺値としてN×M升枠の
個数を返す!
「ptrA=(BYTE*)pa->adr;ptrBY=(BYTE*)pb->adr;」は、
処理ポインタをセット!
「incB=pb->inc*nStepV;」は、B画像のN×M升枠毎の
垂直増加幅をセット!
「*buf++=CorrNMFirst(ptrA,ptrBY,pa->inc,pb->inc,n,m,
avA,avB,sumA);」は、最初の一つ目のN×M升枠の処理と
してサブルーチン関数「CorrNMFirst()」と名前に
「First」が有る関数を使用します!★備考★この様に
初っ端だけを特別に「First」、2番目以降を「Second」と
サブルーチン関数で処理する関数は他の処理でも多く存在
しますので覚えて置いて下さい!
次は、処理する二重ループで
「for(i=0;i<v;i++,ptrBY+=incB){・・外側ループ本体・・}
」は、ループ初期値「i=0;」ループ条件「i<v;」ループ終了
後処理「i++,ptrBY+=incB」と教科書的for構文でのアッ
プカウンタ「i=0;」を条件「i<v;」増分「i++,」と「0から
v未満」まで繰り返し同時に「ptrBY+=incB」と垂直方向に
「ptrBX=ptrBY;」は、B画像用X座標方向処理ポインタを
セットし、内側ループ「for(j=0;j<h;j++,ptrBX+=nStepH){
・・内側ループ本体・・}」とし繰り返します!そのfor
構文「for(j=0;j<h;j++,ptrBX+=nStepH)」は、ループ初期
値「j=0;」ループ条件「j<h;」ループ終了後処理
「j++,ptrBX+=nStepH」と教科書的for構文でのアップカ
ウンタ「j=0;」を条件「j<h;」増分「j++,」と「0から
h未満」まで繰り返し同時に「ptrBX+=nStepH」と水平方向にポインタ増加でif構文「if(!(i==0&&j==0)){
*buf++=CorrNMSecond(ptrA,ptrBX,pa->inc,pb->inc,avA,
avB,sumA);}」とif条件「!(i==0&&j==0)」詰り
、ループカウンタ「i,j」が同時に「0」最初以外で成立中身「*buf++=
CorrNMSecond(ptrA,ptrBX,pa->inc,pb->inc,avA,avB,sumA);
」とサブルーチン関数「CorrNMSecond()」で処理します!

(4-14-181)関数「void GetHVSearchCorrImageNM(
TypeArray* pa,TypeArray* pb,
int n,int m,int nStepH,
int nStepV,int &resH,int &resV){・・・}

/************************************************************************/
/*****      n×m画素正規化相関サーチ画像適応用升目の個数取得      *****/
/*****      引数返値:水平個数                                      *****/
/*****      引数返値:垂直個数                                      *****/
/************************************************************************/

void            CopyClear::GetHVSearchCorrImageNM(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    h    = ( pb->h - n ) / nStepH;                                  // 水平個数を算出
    v    = ( pb->v - m ) / nStepV;                                  // 垂直個数を算出
    resH = h;                                                       // 返値:水平個数
    resV = v;                                                       // 返値:垂直個数
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「GetHVSearchCorrImageNM()」の【関数名】

「Get」は、カタカナ語でもゲット、詰り取得するで
「HV」は、水平・垂直方向の個数を意味します!
英単語「Search」で「探す・探索」です!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=
N×M画素」のサイズを意味します!
この関数「GetHVSearchCorrImageNM()」は、その補助関数
として関数「SearchCorrImageNM()」の前に
仮引数「int &resH,int &resV」で水平垂直方向の結果
個数を事前算出する事を行います!

(B)関数「void GetHVSearchCorrImageNM()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「GetHVSearchCorrImageNM()」の【仮引数】

void            CopyClear::GetHVSearchCorrImageNM(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    int&        resH,                                               // 返値:取得する水平個数
    int&        resV                                                // 返値:取得する垂直個数
){

「TypeArray* pa,」は、比較対象画像A≪テンプレート画像≫
「TypeArray* pb,」は、比較対象画像B≪サーチ対象画像≫
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数

(D)関数「GetHVSearchCorrImageNM()」の【アルゴリズム】

){
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    h    = ( pb->h - n ) / nStepH;                                  // 水平個数を算出
    v    = ( pb->v - m ) / nStepV;                                  // 垂直個数を算出
    resH = h;                                                       // 返値:水平個数
    resV = v;                                                       // 返値:垂直個数
}

(D-1)ローカル変数

){
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)

「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい

(D-2)アルゴリズムコード

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        resH = 0;                                                   // 個数の返事を0にして
        resV = 0;                                                   // 
        return;                                                     // 終了
    }                                                               // 
    h    = ( pb->h - n ) / nStepH;                                  // 水平個数を算出
    v    = ( pb->v - m ) / nStepV;                                  // 垂直個数を算出
    resH = h;                                                       // 返値:水平個数
    resV = v;                                                       // 返値:垂直個数
}

「n=(n<pa->h)?n:pa->h;m=(m<pa->v)?m:pa->v;」は、
A画像(テンプレート画像)のサイズと仮引数
「int n;int m;」の小さい方をN×Mとする様に調整!
「if(pb->h<n||pb->v<m){resH=0;resV=0;return;}」は、
B画像(サーチ対象画像)の画像サイズがN×Mより小さい
場合「resH=0;resV=0;return;」結果個数を0にして
関数終了!
「h=(pb->h-n)/nStepH;v=(pb->v-m)/nStepV;」は、
B画像の中にN×M升枠の個数を「int h;int v;」に算出
し格納!
「resH=h;resV=v;」は、引数辺値としてN×M升枠の
個数を返す!

(4-14-182)関数「int SearchCorrImageSort(
TypeArray* pa,
TypeArray* pb,TypeCorr *buf,
int size,int n,int m,int nStepH,
int nStepV,double t,
double rate=0.0,
double minAv=0.0,double maxAv){・・・}

/****************************************************************************/
/*****      n×m画素正規化相関サーチ画像適応&データ整理              *****/
/*****      ☆n×mの基本単位毎に画像をサーチ☆                        *****/
/*****      ☆サーチ後、有効相関値以上のデータとその座標を降順に☆      *****/
/*****      ☆大きい方からソートし有効数を返す☆                        *****/
/*****      ☆結果数がサイズより大きい場合は、サイズ内でデータを更新☆  *****/
/*****      ★水平/垂直ステップ数×2以内の近接範囲で重複除去を行う★  *****/
/*****      返値:有効個数、負→エラーステータス                        *****/
/****************************************************************************/

int             CopyClear::SearchCorrImageSort(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    TypeCorr*   buf,                                                // 結果Buffer(相関値+座標)
    int         size,                                               // 結果サイズ
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    double      t,                                                  // 有効相関値
    double      rate,                                               // 0.0:無(省略時)、他:正/反転割合
    double      minAv,                                              // 0.0:無(省略時)、他:平均範囲最小割合
    double      maxAv                                               // 0.0:無(省略時)、他:平均範囲最大割合
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    double      d;                                                  // 相関値
    int         x;                                                  // X座標
    int         y;                                                  // Y座標
    double      r;                                                  // 正/反転の割合
    int         i;                                                  // カウンタ
    int         j;                                                  // カウンタ
    int         n1;                                                 // 有効個数
    int         n2;                                                 // 有効個数:重複整理
    int         ixD;                                                // 重複排除開始Index
    int         nD;                                                 // 重複排除対象個数
    int         firstSw;                                            // 真→先頭処理済み
    int         sw;                                                 // 0:通常、1:サイズOver発生

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        return( 0 );                                                // 0を返し終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        return( SearchCorrImageSortLarge( pa, pb, buf, size, n, m,  // 左記で処理する
                        nStepH, nStepV, t, rate, minAv, maxAv ) );  // 
    }                                                               // 
    sw      = 0;                                                    // 0:通常に初期化
    n1      = 0;                                                    // 有効個数初期化
    ixD     = 0;                                                    // 重複排除開始Index初期化
    nD      = 0;                                                    // 重複排除対象個数初期化
    h       = ( pb->h - n ) / nStepH;                               // 水平個数を算出
    v       = ( pb->v - m ) / nStepV;                               // 垂直個数を算出
    ptrA    = (BYTE*)pa->adr;                                       // A配列:処理ポインタ
    ptrBY   = (BYTE*)pb->adr;                                       // B配列:処理ポインタ
    incB    = pb->inc * nStepV;                                     // B配列:増加幅(nStepV単位)
    firstSw = FALSE;                                                // 偽→先頭処理未実行
    for( i = 0; i < v; i++, ptrBY += incB ){                        // 垂直個数分
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( j = 0; j < h; j++, ptrBX += nStepH ){                  // 水平個数分
            if( !firstSw ){                                         // 先頭ならば
                firstSw = TRUE;                                     // 先頭処理済みをセット
                d       = CorrNMFirst( ptrA, ptrBX,                 // 先頭の時の相関値算出
                                            pa->inc, pb->inc,       // 
                                            n, m, avA, avB, sumA ); // 
            }else{                                                  // 先頭以外ならば
                d = CorrNMSecond( ptrA, ptrBX, pa->inc, pb->inc,    // n×m画素の正規相関を
                                            n, m, avA, avB, sumA ); // 算出
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( minAv > 0.0 ){                                  // 範囲最小割合有効時
                    if( avB < avA * minAv ){                        // 対象の平均が範囲未満なら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
                if( maxAv > 0.0 && minAv < maxAv ){                 // 範囲最大割合有効時
                    if( avB > avA * maxAv ){                        // 対象の平均が範囲Overなら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( rate > 0.0 ){                                   // 正/反転検査時
                    r = CorrNMCheck( ptrA, ptrBX,                   // 正/反転の割合を
                                pa->inc, pb->inc, n, m, avA, avB ); // 算出
                    if( r < rate ){                                 // 割合未満の時
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                x  = j * nStepH;                                    // X座標算出
                y  = i * nStepV;                                    // Y座標算出
                if( sw == 0 ){                                      // 通常状態で
                    buf[n1].d = d;                                  // 正規化相関値と
                    buf[n1].x = x;                                  // 座標を
                    buf[n1].y = y;                                  // 格納
                    n1++;                                           // 有効個数UP
                    nD++;                                           // 重複排除対象個数UP
                    if( n1 >= size ){                               // 有効数が最大に成ったら
                        sw = 1;                                     // 1:Over状態をセット
                        Sort( 1, buf, n1 );                         // 降順にソート
                        n1 = ExcludeOverlapXY( buf, n1,             // 近接座標の排除
                                        nStepH * 2, nStepV * 2 );   // 
                        if( n1 < 0 ){                               // 排除失敗時
                            return( n1 );                           // ステータスを返す
                        }else if( n1 < size ){                      // 排除後、有効数が最大未満
                            sw  = 0;                                // 0:通常に初期化
                            nD  = 0;                                // 重複排除対象個数初期化
                            ixD = n1;                               // 重複排除開始Indexセット
                        }                                           // 
                    }                                               // 
                }else{                                              // Over状態時
                    SortUpdate( 1, buf, n1, d, x, y );              // データ更新
                }                                                   // 
            }                                                       //
        }                                                           // 
        if( sw == 0 && nD > size / 2 ){                             // 水平処理終了後、個数が半分超なら
            Sort( 1, &buf[ixD], nD );                               // 対象部分を降順にソート
            n2 = ExcludeOverlapXY( &buf[ixD], nD,                   // 近接座標の排除
                                        nStepH * 2, nStepV * 2 );   // 
            if( n2 < 0 ){                                           // 排除失敗時
                return( n2 );                                       // ステータスを返す
            }                                                       // 
            n1  = ixD + n2;                                         // 有効個数算出
            nD  = 0;                                                // 重複排除対象個数初期化
            ixD = n1;                                               // 重複排除開始Indexセット
        }                                                           // 
    }                                                               // 
    if( sw == 0 ){                                                  // 通常状態なら
        Sort( 1, buf, n1 );                                         // 降順にソート
    }                                                               // 
    n1 = ExcludeOverlapXY( buf, n1, nStepH * 2, nStepV * 2 );       // 近接座標の排除
    return( n1 );                                                   // 有効個数を返す
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「SearchCorrImageSort()」の【関数名】

「Search」は、英単語「Search」で「探す・探索」です!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです、ココでは、サーチした
画像の相関値の大きい方から順にソートする事を示します!

(B)関数「void SearchCorrImageSort()」の【返値】

返値としてサーチした有効個数を返す関数です!

(C)関数「SearchCorrImageSort()」の【仮引数】

int             CopyClear::SearchCorrImageSort(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    TypeCorr*   buf,                                                // 結果Buffer(相関値+座標)
    int         size,                                               // 結果サイズ
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    int         nStepH,                                             // 水平方向次点ステップ数
    int         nStepV,                                             // 垂直方向次点ステップ数
    double      t,                                                  // 有効相関値
    double      rate,                                               // 0.0:無(省略時)、他:正/反転割合
    double      minAv,                                              // 0.0:無(省略時)、他:平均範囲最小割合
    double      maxAv                                               // 0.0:無(省略時)、他:平均範囲最大割合
){

「TypeArray* pa,」は、比較対象画像A≪テンプレート画像≫
「TypeArray* pb,」は、比較対象画像B≪サーチ対象画像≫
「TypeCorr* buf,」は、結果(相関値)格納バッファー
「int size,」は、上記のサイズ
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「double t,」は、相関値の有効(この値以上が格納対象)
「double rate.」は、サーチ条件の一つ(正負割合)
「double minAv,」は、「maxAv」と一緒にサーチ条件と
します、詳細は、アルゴリズム解説で解説!
「double maxAv」は、「minAv」と一緒にサーチ条件と
します、詳細は、アルゴリズム解説で解説!

(D)関数「SearchCorrImageSort()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    double      d;                                                  // 相関値
    int         x;                                                  // X座標
    int         y;                                                  // Y座標
    double      r;                                                  // 正/反転の割合
    int         i;                                                  // カウンタ
    int         j;                                                  // カウンタ
    int         n1;                                                 // 有効個数
    int         n2;                                                 // 有効個数:重複整理
    int         ixD;                                                // 重複排除開始Index
    int         nD;                                                 // 重複排除対象個数
    int         firstSw;                                            // 真→先頭処理済み
    int         sw;                                                 // 0:通常、1:サイズOver発生

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        return( 0 );                                                // 0を返し終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        return( SearchCorrImageSortLarge( pa, pb, buf, size, n, m,  // 左記で処理する
                        nStepH, nStepV, t, rate, minAv, maxAv ) );  // 
    }                                                               // 
    sw      = 0;                                                    // 0:通常に初期化
    n1      = 0;                                                    // 有効個数初期化
    ixD     = 0;                                                    // 重複排除開始Index初期化
    nD      = 0;                                                    // 重複排除対象個数初期化
    h       = ( pb->h - n ) / nStepH;                               // 水平個数を算出
    v       = ( pb->v - m ) / nStepV;                               // 垂直個数を算出
    ptrA    = (BYTE*)pa->adr;                                       // A配列:処理ポインタ
    ptrBY   = (BYTE*)pb->adr;                                       // B配列:処理ポインタ
    incB    = pb->inc * nStepV;                                     // B配列:増加幅(nStepV単位)
    firstSw = FALSE;                                                // 偽→先頭処理未実行
    for( i = 0; i < v; i++, ptrBY += incB ){                        // 垂直個数分
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( j = 0; j < h; j++, ptrBX += nStepH ){                  // 水平個数分
            if( !firstSw ){                                         // 先頭ならば
                firstSw = TRUE;                                     // 先頭処理済みをセット
                d       = CorrNMFirst( ptrA, ptrBX,                 // 先頭の時の相関値算出
                                            pa->inc, pb->inc,       // 
                                            n, m, avA, avB, sumA ); // 
            }else{                                                  // 先頭以外ならば
                d = CorrNMSecond( ptrA, ptrBX, pa->inc, pb->inc,    // n×m画素の正規相関を
                                            n, m, avA, avB, sumA ); // 算出
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( minAv > 0.0 ){                                  // 範囲最小割合有効時
                    if( avB < avA * minAv ){                        // 対象の平均が範囲未満なら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
                if( maxAv > 0.0 && minAv < maxAv ){                 // 範囲最大割合有効時
                    if( avB > avA * maxAv ){                        // 対象の平均が範囲Overなら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( rate > 0.0 ){                                   // 正/反転検査時
                    r = CorrNMCheck( ptrA, ptrBX,                   // 正/反転の割合を
                                pa->inc, pb->inc, n, m, avA, avB ); // 算出
                    if( r < rate ){                                 // 割合未満の時
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                x  = j * nStepH;                                    // X座標算出
                y  = i * nStepV;                                    // Y座標算出
                if( sw == 0 ){                                      // 通常状態で
                    buf[n1].d = d;                                  // 正規化相関値と
                    buf[n1].x = x;                                  // 座標を
                    buf[n1].y = y;                                  // 格納
                    n1++;                                           // 有効個数UP
                    nD++;                                           // 重複排除対象個数UP
                    if( n1 >= size ){                               // 有効数が最大に成ったら
                        sw = 1;                                     // 1:Over状態をセット
                        Sort( 1, buf, n1 );                         // 降順にソート
                        n1 = ExcludeOverlapXY( buf, n1,             // 近接座標の排除
                                        nStepH * 2, nStepV * 2 );   // 
                        if( n1 < 0 ){                               // 排除失敗時
                            return( n1 );                           // ステータスを返す
                        }else if( n1 < size ){                      // 排除後、有効数が最大未満
                            sw  = 0;                                // 0:通常に初期化
                            nD  = 0;                                // 重複排除対象個数初期化
                            ixD = n1;                               // 重複排除開始Indexセット
                        }                                           // 
                    }                                               // 
                }else{                                              // Over状態時
                    SortUpdate( 1, buf, n1, d, x, y );              // データ更新
                }                                                   // 
            }                                                       //
        }                                                           // 
        if( sw == 0 && nD > size / 2 ){                             // 水平処理終了後、個数が半分超なら
            Sort( 1, &buf[ixD], nD );                               // 対象部分を降順にソート
            n2 = ExcludeOverlapXY( &buf[ixD], nD,                   // 近接座標の排除
                                        nStepH * 2, nStepV * 2 );   // 
            if( n2 < 0 ){                                           // 排除失敗時
                return( n2 );                                       // ステータスを返す
            }                                                       // 
            n1  = ixD + n2;                                         // 有効個数算出
            nD  = 0;                                                // 重複排除対象個数初期化
            ixD = n1;                                               // 重複排除開始Indexセット
        }                                                           // 
    }                                                               // 
    if( sw == 0 ){                                                  // 通常状態なら
        Sort( 1, buf, n1 );                                         // 降順にソート
    }                                                               // 
    n1 = ExcludeOverlapXY( buf, n1, nStepH * 2, nStepV * 2 );       // 近接座標の排除
    return( n1 );                                                   // 有効個数を返す
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrBX;                                              // B配列:処理ポインタ
    BYTE*       ptrBY;                                              // B配列:処理ポインタ
    int         incB;                                               // B配列:増加幅(nStepV単位)
    int         h;                                                  // 水平幅(n×mの個数)
    int         v;                                                  // 垂直幅(n×mの個数)
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    double      d;                                                  // 相関値
    int         x;                                                  // X座標
    int         y;                                                  // Y座標
    double      r;                                                  // 正/反転の割合
    int         i;                                                  // カウンタ
    int         j;                                                  // カウンタ
    int         n1;                                                 // 有効個数
    int         n2;                                                 // 有効個数:重複整理
    int         ixD;                                                // 重複排除開始Index
    int         nD;                                                 // 重複排除対象個数
    int         firstSw;                                            // 真→先頭処理済み
    int         sw;                                                 // 0:通常、1:サイズOver発生

「BYTE* ptrA;」は、A画像用処理ポインタ
「BYTE* ptrBX;」は、B画像用X座標方向処理ポインタ
「BYTE* ptrBY;」は、B画像用Y座標方向処理ポインタ
「int incB;」は、B画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int sumA;」は、A画像用合計値、及び分散値算出用
「int avA;」は、A画像平均値
「int avB;」は、B画像平均値
「double d;」は、相関値
「int x;」は、X座標
「int y;」は、Y座標
「double r;」は、正/反転の割合
「int i;」は、ループカウンタ外側
「int j;」は、ループカウンタ内側
「int n1;」は、有効個数
「int n2;」は、有効個数:重複整理用
「int ixD;」は、重複排除開始添え字(インデックス)
「int nD;」は、重複排除対象個数
「int firstSw;」は、スィッチ:先頭処理済み(真)
「int sw;」は、バッファー格納制御用スィッチ
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい

(D-2)アルゴリズムコード

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        return( 0 );                                                // 0を返し終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        return( SearchCorrImageSortLarge( pa, pb, buf, size, n, m,  // 左記で処理する
                        nStepH, nStepV, t, rate, minAv, maxAv ) );  // 
    }                                                               // 
    sw      = 0;                                                    // 0:通常に初期化
    n1      = 0;                                                    // 有効個数初期化
    ixD     = 0;                                                    // 重複排除開始Index初期化
    nD      = 0;                                                    // 重複排除対象個数初期化
    h       = ( pb->h - n ) / nStepH;                               // 水平個数を算出
    v       = ( pb->v - m ) / nStepV;                               // 垂直個数を算出
    ptrA    = (BYTE*)pa->adr;                                       // A配列:処理ポインタ
    ptrBY   = (BYTE*)pb->adr;                                       // B配列:処理ポインタ
    incB    = pb->inc * nStepV;                                     // B配列:増加幅(nStepV単位)
    firstSw = FALSE;                                                // 偽→先頭処理未実行
    for( i = 0; i < v; i++, ptrBY += incB ){                        // 垂直個数分
        ptrBX = ptrBY;                                              // B配列:水平始点
        for( j = 0; j < h; j++, ptrBX += nStepH ){                  // 水平個数分
            if( !firstSw ){                                         // 先頭ならば
                firstSw = TRUE;                                     // 先頭処理済みをセット
                d       = CorrNMFirst( ptrA, ptrBX,                 // 先頭の時の相関値算出
                                            pa->inc, pb->inc,       // 
                                            n, m, avA, avB, sumA ); // 
            }else{                                                  // 先頭以外ならば
                d = CorrNMSecond( ptrA, ptrBX, pa->inc, pb->inc,    // n×m画素の正規相関を
                                            n, m, avA, avB, sumA ); // 算出
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( minAv > 0.0 ){                                  // 範囲最小割合有効時
                    if( avB < avA * minAv ){                        // 対象の平均が範囲未満なら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
                if( maxAv > 0.0 && minAv < maxAv ){                 // 範囲最大割合有効時
                    if( avB > avA * maxAv ){                        // 対象の平均が範囲Overなら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( rate > 0.0 ){                                   // 正/反転検査時
                    r = CorrNMCheck( ptrA, ptrBX,                   // 正/反転の割合を
                                pa->inc, pb->inc, n, m, avA, avB ); // 算出
                    if( r < rate ){                                 // 割合未満の時
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                x  = j * nStepH;                                    // X座標算出
                y  = i * nStepV;                                    // Y座標算出
                if( sw == 0 ){                                      // 通常状態で
                    buf[n1].d = d;                                  // 正規化相関値と
                    buf[n1].x = x;                                  // 座標を
                    buf[n1].y = y;                                  // 格納
                    n1++;                                           // 有効個数UP
                    nD++;                                           // 重複排除対象個数UP
                    if( n1 >= size ){                               // 有効数が最大に成ったら
                        sw = 1;                                     // 1:Over状態をセット
                        Sort( 1, buf, n1 );                         // 降順にソート
                        n1 = ExcludeOverlapXY( buf, n1,             // 近接座標の排除
                                        nStepH * 2, nStepV * 2 );   // 
                        if( n1 < 0 ){                               // 排除失敗時
                            return( n1 );                           // ステータスを返す
                        }else if( n1 < size ){                      // 排除後、有効数が最大未満
                            sw  = 0;                                // 0:通常に初期化
                            nD  = 0;                                // 重複排除対象個数初期化
                            ixD = n1;                               // 重複排除開始Indexセット
                        }                                           // 
                    }                                               // 
                }else{                                              // Over状態時
                    SortUpdate( 1, buf, n1, d, x, y );              // データ更新
                }                                                   // 
            }                                                       //
        }                                                           // 
        if( sw == 0 && nD > size / 2 ){                             // 水平処理終了後、個数が半分超なら
            Sort( 1, &buf[ixD], nD );                               // 対象部分を降順にソート
            n2 = ExcludeOverlapXY( &buf[ixD], nD,                   // 近接座標の排除
                                        nStepH * 2, nStepV * 2 );   // 
            if( n2 < 0 ){                                           // 排除失敗時
                return( n2 );                                       // ステータスを返す
            }                                                       // 
            n1  = ixD + n2;                                         // 有効個数算出
            nD  = 0;                                                // 重複排除対象個数初期化
            ixD = n1;                                               // 重複排除開始Indexセット
        }                                                           // 
    }                                                               // 
    if( sw == 0 ){                                                  // 通常状態なら
        Sort( 1, buf, n1 );                                         // 降順にソート
    }                                                               // 
    n1 = ExcludeOverlapXY( buf, n1, nStepH * 2, nStepV * 2 );       // 近接座標の排除
    return( n1 );                                                   // 有効個数を返す
}

「n=(n<pa->h)?n:pa->h;m=(m<pa->v)?m:pa->v;」は、
A画像(テンプレート画像)のサイズと仮引数
「int n;int m;」の小さい方をN×Mとする様に調整!
「if(pb->h<n||pb->v<m){return(0);}」は、
B画像(サーチ対象画像)の画像サイズがN×Mより小さい
場合「return(0);」結果個数を0にして関数終了!
「if(nm>=65536){・・成立中身・・}」は、if条件
「nm>=65536」でN×Mサイズが大きい場合の専用処理
とし「SearchCorrImageSortLarge(pa,pb,buf,size,n,m,
nStepH,nStepV,t,rate,minAv,maxAv)」とサブルーチン関数
「SearchCorrImageSortLarge()」で専用関数で処理し、
その関数辺値を「return(・・・);」で返し関数終了!
「sw=0;」は、バッファー格納で格納した数がオーバー
したかか否かのスイッチを「否か」に初期化
「n1=0;」は、有効個数初期化
「ixD=0;」は、重複排除開始ンデックスの初期化
「nD=0;」は、重複排除対象個数の初期化
「h=(pb->h-n)/nStepH;v=(pb->v-m)/nStepV;」は、
B画像の中にN×M升枠の個数を「int h;int v;」に算出
し格納!
「ptrA=(BYTE*)pa->adr;ptrBY=(BYTE*)pb->adr;」は、
処理ポインタをセット!
「incB=pb->incnStepV;」は、B画像のN×M升枠毎の
垂直増加幅をセット!
「firstSw=FALSE;」は、先頭処理済み(真)スィッチを
初期化!
次は、処理する二重ループで
「for(i=0;i<v;i++,ptrBY+=incB){・・外側ループ本体・・}
」は、ループ初期値「i=0;」ループ条件「i<v;」ループ終了
後処理「i++,ptrBY+=incB」と教科書的for構文でのアッ
プカウンタ「i=0;」を条件「i<v;」増分「i++,」と「0から
v未満」まで繰り返し同時に「ptrBY+=incB」と垂直方向に
「ptrBX=ptrBY;」は、B画像用X座標方向処理ポインタを
セットし、内側ループ「for(j=0;j<h;j++,ptrBX+=nStepH){
・・内側ループ本体・・}」とし繰り返します!そのfor
構文「for(j=0;j<h;j++,ptrBX+=nStepH)」は、ループ初期
値「j=0;」ループ条件「j<h;」ループ終了後処理
「j++,ptrBX+=nStepH」と教科書的for構文でのアップカ
ウンタ「j=0;」を条件「j<h;」増分「j++,」と「0から
h未満」まで繰り返し同時に「ptrBX+=nStepH」と水平方向に
ポインタ増加で「内側ループ本体」で
「if(!firstSw){firstSw=TRUE;d=CorrNMFirst(ptrA,ptrBX,
pa->inc,pb->inc,n,m,avA,avB,sumA);}」は、if条件「
!firstSw」と初回「first」のサブルーチン関数「
CorrNMFirst()」が処理されて無ければ、「firstSw=TRUE;」
と処理済みにスィッチをセット、そしてサブルーチン関数
「CorrNMFirst()」で一升N×M升枠の相関値算出処理し、
「}else{d=CorrNMSecond(ptrA,ptrBX,pa->inc,pb->inc,
n,m,avA,avB,sumA);}」で条件不成立「既に初回firstの
サブルーチン関数「CorrNMFirst()」が処理済みならば、
「d=CorrNMSecond(ptrA,ptrBX,pa->inc,pb->inc,n,m,
avA,avB,sumA);}」とサブルーチン関数「CorrNMSecond()」
で一升N×M升枠の相関値算出処理!
「if(d>=t){if(minAv>0.0){if(avB<avAminAv){d=0.0;}}
if(maxAv>0.0&&minAv<maxAv){if(avB>avAmaxAv){d=0.0;
}}}」は、条件「d>=t」詰り相関値算出成功時に成立中身の
各種条件で「d=0.0;」と相関値を無効化≪サーチする意味が
無いと判断して無効化≫
「if(d>=t){if(rate>0.0){・・成立・・}}」は、if条件
「d>=t・rate>0.0」と相関値が有効で正/反転割合指定が
ある場合の条件を「r=CorrNMCheck(ptrA,ptrBX,pa->inc,
pb->inc,n,m,avA,avB);」とサブルーチン関数「
CorrNMCheck()」で精査して「r」に格納!その値で
if条件「r<rate」成立時「d=0.0;」で無効化≪サーチ
する意味が無いと判断して無効化≫、ここまでで相関値を
有効か無効に判別!
if条件「d>=t」で相関値が指定値を越ていたら、成立
中身を処理します!
「x=jnStepH;y=inStepV;」は、N×M升枠のXY座標を
セット!if条件「sw==0」でバッファー格納OKなので
「buf[n1].d=d;buf[n1].x=x;buf[n1].y=y;」と相関値と
XY座標を仮引数「TypeCorr buf,」と型「TypeCorr*」の
バッファー格納します!
「n1++;nD++;」は、有効個数と重複排除対象個数のカウント
アップ!
if条件「n1>=size」、詰り、格納サイズ満杯に成れば
「sw=1;」とバッファー格納が満杯スィッチをセット!
「Sort(1,buf,n1);n1=ExcludeOverlapXY(buf,n1,nStepH2,
nStepV2);」は、サブルーチン関数「Sort(1,buf,n1);」と
降順(大⇒小)ソートを相関値をキーとしてソートした後で
サブルーチン関数「ExcludeOverlapXY()」でN×M升枠の
XY座標が重なる(Overlap)データ配列を整理し整理した
個数算出で「n1=・・・」と有効個数も整理、
「if(n1<0){return(n1);}」は、エラー発生としてエラー
コードを関数辺値とし返し関数終了!
「else if(n1<size){sw=0;nD=0;ixD=n1;}」は、正常に処理
出来て居てif条件「n1<size」と更にバッファー格納可能
ならば、「sw=0;nD=0;ixD=n1;」スィッチや個数を再初期化
「}else{」≪if条件「sw==0」の不成立=詰り、バッフ
ァー格納満杯の時は≫「SortUpdate(1,buf,n1,d,x,y);」と
サブルーチン関数「SortUpdate()」でバッファーのデータを
1単位だけ更新します!
ココまででfor構文「for(j=0;j<h;j++,ptrBX+=nStepH)」
のループ本体の説明です!と言う事は、水平方向処理が終
わったと言い換えられます!そして外側ループ本体の続き
として、if条件「sw==0&&nD>size/2」で更にバッファー
格納が可能で重複排除対象個数がバッファー格納サイズの
半分を超えている場合、条件成立で、まず、
「Sort(1,&buf[ixD],nD);」と重複排除対象バッファーを
降順にソート、「n2=ExcludeOverlapXY(&buf[ixD],nD,
nStepH2,nStepV2);」とXY座標が重複排除!
「if(n2<0){return(n2);}」は、エラー発生としてエラー
コードを関数辺値とし返し関数終了!
「n1=ixD+n2;nD=0;ixD=n1;」は、バッファー個数等を整理
ココまででfor構文「for(i=0;i<v;i++,ptrBY+=incB)」
のループ本体の説明です!と言う事は、外側の垂直方向処理
まで終わったと言い換えられます!
「if(sw==0){Sort(1,buf,n1);}」は、バッファー格納に
余裕が有る場合、「Sort()」で相関値降順にソート!
「n1=ExcludeOverlapXY(buf,n1,nStepH2,nStepV2);」は、
全体のXY座標が重複排除!
「return(n1);」、で有効個数(或いはエラーコード)を
関数辺値とし返し、関数終了!

(4-14-183)関数「int SearchCorrImageXYSort(
TypeArray* pa,
TypeArray* pb,TypeCorr *buf,
int size,int n,int m,double t,
double rate,double minAv,
double maxAv){・・・}

/****************************************************************************/
/*****      n×m画素正規化相関サーチ画像適応&データ整理:座標指定    *****/
/*****      ☆n×mの基本単位毎に画像を指定座標毎にサーチ☆            *****/
/*****      ☆サーチ後、有効相関値以上のデータとその座標を降順に☆      *****/
/*****      ☆大きい方からソートし有効数を返す☆                        *****/
/*****      返値:有効個数                                              *****/
/****************************************************************************/

int             CopyClear::SearchCorrImageXYSort(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    TypeCorr*   buf,                                                // 結果Buffer(相関値+座標)
    int         size,                                               // 結果サイズ
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    double      t,                                                  // 有効相関値
    double      rate,                                               // 0.0:無(省略時)、他:正/反転割合
    double      minAv,                                              // 0.0:無(省略時)、他:平均範囲最小割合
    double      maxAv                                               // 0.0:無(省略時)、他:平均範囲最大割合
){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    BYTE*       ptrBXY;                                             // B配列:処理ポインタ
    int         minH;                                               // B配列:水平幅最小値
    int         minV;                                               // B配列:垂直幅最小値
    int         incB;                                               // B配列:増加幅
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    double      d;                                                  // 相関値
    int         x;                                                  // X座標
    int         y;                                                  // Y座標
    double      r;                                                  // 正/反転の割合
    int         i;                                                  // カウンタ
    int         firstSw;                                            // 真→先頭処理済み
    int         n1;                                                 // 有効個数

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        return( 0 );                                                // 0を返し終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        return( SearchCorrImageXYSortLarge( pa, pb, buf, size,      // 左記で処理する
                                n, m, t, rate, minAv, maxAv ) );    // 
    }                                                               // 
    minH    = pb->h - n;                                            // 水平幅の最小値算出
    minV    = pb->v - m;                                            // 垂直幅の最小値算出
    n1      = 0;                                                    // 有効個数初期化
    ptrA    = (BYTE*)pa->adr;                                       // A配列:処理ポインタ
    ptrB    = (BYTE*)pb->adr;                                       // B配列:処理ポインタ
    incB    = pb->inc;                                              // B配列:増加幅
    firstSw = FALSE;                                                // 偽→先頭処理未実行
    for( i = 0; i < size; i++ ){                                    // 最初から最後まで
        x = buf[i].x;                                               // 座標値を取り出し
        y = buf[i].y;                                               // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            ptrBXY = ptrB + x + y * incB;                           // ポインタを算出
            if( !firstSw ){                                         // 先頭ならば
                firstSw = TRUE;                                     // 先頭処理済みをセット
                d       = CorrNMFirst( ptrA, ptrBXY,                // 先頭の時の相関値算出
                                            pa->inc, pb->inc,       //
                                            n, m, avA, avB, sumA ); // 
            }else{                                                  // 2番目以降ならば
                d = CorrNMSecond( ptrA, ptrBXY, pa->inc, pb->inc,   // n×m画素の正規相関を
                                            n, m, avA, avB, sumA ); // 算出
            }                                                       //
            if( d >= t ){                                           // 有効な値ならば
                if( minAv > 0.0 ){                                  // 範囲最小割合有効時
                    if( avB < avA * minAv ){                        // 対象の平均が範囲未満なら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
                if( maxAv > 0.0 && minAv < maxAv ){                 // 範囲最大割合有効時
                    if( avB > avA * maxAv ){                        // 対象の平均が範囲Overなら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( rate > 0.0 ){                                   // 正/反転検査時
                    r = CorrNMCheck( ptrA, ptrBXY,                  // 正/反転の割合を
                                pa->inc, pb->inc, n, m, avA, avB ); // 算出
                    if( r < rate ){                                 // 割合未満の時
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                buf[n1].d = d;                                      // 正規化相関値と
                buf[n1].x = x;                                      // 座標を
                buf[n1].y = y;                                      // 格納
                n1++;                                               // 有効個数UP
            }                                                       //
        }                                                           // 
    }                                                               // 
    Sort( 1, buf, n1 );                                             // 降順にソート
    return( n1 );                                                   // 有効個数を返す
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「SearchCorrImageXYSort()」の【関数名】

「Search」は、英単語「Search」で「探す・探索」です!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「XY」は、XY座標を意味します!
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです、ココでは、他の関数
「SearchCorrImageSort()」で算出した相関値+座標「
TypeCorr* buf,」データを相関値降順(大⇒小)に改めて
ソートする事を示します!

(B)関数「int SearchCorrImageXYSort()」の【返値】

返値としてサーチした有効個数を返す関数です!

(C)関数「SearchCorrImageXYSort()」の【仮引数】

int             CopyClear::SearchCorrImageXYSort(
    TypeArray*  pa,                                                 // A配列:サーチ対象
    TypeArray*  pb,                                                 // B配列:サーチ範囲
    TypeCorr*   buf,                                                // 結果Buffer(相関値+座標)
    int         size,                                               // 結果サイズ
    int         n,                                                  // n×mのn:対象物サイズ
    int         m,                                                  // n×mのm:対象物サイズ
    double      t,                                                  // 有効相関値
    double      rate,                                               // 0.0:無(省略時)、他:正/反転割合
    double      minAv,                                              // 0.0:無(省略時)、他:平均範囲最小割合
    double      maxAv                                               // 0.0:無(省略時)、他:平均範囲最大割合
){

「TypeArray* pa,」は、比較対象画像A≪テンプレート画像≫
「TypeArray* pb,」は、比較対象画像B≪サーチ対象画像≫
「TypeCorr* buf,」は、結果(相関値)格納バッファー
「int size,」は、上記のサイズ
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「double t,」は、相関値の有効(この値以上が格納対象)
「double rate,」は、サーチ条件の一つ(正負割合)
「double minAv,」は、「maxAv」と一緒にサーチ条件と
します、詳細は、アルゴリズム解説で解説!
「double maxAv」は、「minAv」と一緒にサーチ条件と
します、詳細は、アルゴリズム解説で解説!

(D)関数「SearchCorrImageXYSort()」の【アルゴリズム】

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    BYTE*       ptrBXY;                                             // B配列:処理ポインタ
    int         minH;                                               // B配列:水平幅最小値
    int         minV;                                               // B配列:垂直幅最小値
    int         incB;                                               // B配列:増加幅
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    double      d;                                                  // 相関値
    int         x;                                                  // X座標
    int         y;                                                  // Y座標
    double      r;                                                  // 正/反転の割合
    int         i;                                                  // カウンタ
    int         firstSw;                                            // 真→先頭処理済み
    int         n1;                                                 // 有効個数

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        return( 0 );                                                // 0を返し終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        return( SearchCorrImageXYSortLarge( pa, pb, buf, size,      // 左記で処理する
                                n, m, t, rate, minAv, maxAv ) );    // 
    }                                                               // 
    minH    = pb->h - n;                                            // 水平幅の最小値算出
    minV    = pb->v - m;                                            // 垂直幅の最小値算出
    n1      = 0;                                                    // 有効個数初期化
    ptrA    = (BYTE*)pa->adr;                                       // A配列:処理ポインタ
    ptrB    = (BYTE*)pb->adr;                                       // B配列:処理ポインタ
    incB    = pb->inc;                                              // B配列:増加幅
    firstSw = FALSE;                                                // 偽→先頭処理未実行
    for( i = 0; i < size; i++ ){                                    // 最初から最後まで
        x = buf[i].x;                                               // 座標値を取り出し
        y = buf[i].y;                                               // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            ptrBXY = ptrB + x + y * incB;                           // ポインタを算出
            if( !firstSw ){                                         // 先頭ならば
                firstSw = TRUE;                                     // 先頭処理済みをセット
                d       = CorrNMFirst( ptrA, ptrBXY,                // 先頭の時の相関値算出
                                            pa->inc, pb->inc,       //
                                            n, m, avA, avB, sumA ); // 
            }else{                                                  // 2番目以降ならば
                d = CorrNMSecond( ptrA, ptrBXY, pa->inc, pb->inc,   // n×m画素の正規相関を
                                            n, m, avA, avB, sumA ); // 算出
            }                                                       //
            if( d >= t ){                                           // 有効な値ならば
                if( minAv > 0.0 ){                                  // 範囲最小割合有効時
                    if( avB < avA * minAv ){                        // 対象の平均が範囲未満なら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
                if( maxAv > 0.0 && minAv < maxAv ){                 // 範囲最大割合有効時
                    if( avB > avA * maxAv ){                        // 対象の平均が範囲Overなら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( rate > 0.0 ){                                   // 正/反転検査時
                    r = CorrNMCheck( ptrA, ptrBXY,                  // 正/反転の割合を
                                pa->inc, pb->inc, n, m, avA, avB ); // 算出
                    if( r < rate ){                                 // 割合未満の時
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                buf[n1].d = d;                                      // 正規化相関値と
                buf[n1].x = x;                                      // 座標を
                buf[n1].y = y;                                      // 格納
                n1++;                                               // 有効個数UP
            }                                                       //
        }                                                           // 
    }                                                               // 
    Sort( 1, buf, n1 );                                             // 降順にソート
    return( n1 );                                                   // 有効個数を返す
}

(D-1)ローカル変数

){
    BYTE*       ptrA;                                               // A配列:処理ポインタ
    BYTE*       ptrB;                                               // B配列:処理ポインタ
    BYTE*       ptrBXY;                                             // B配列:処理ポインタ
    int         minH;                                               // B配列:水平幅最小値
    int         minV;                                               // B配列:垂直幅最小値
    int         incB;                                               // B配列:増加幅
    int         sumA;                                               // 合計A(及び自己相関)
    int         avA;                                                // 平均A
    int         avB;                                                // 平均B
    double      d;                                                  // 相関値
    int         x;                                                  // X座標
    int         y;                                                  // Y座標
    double      r;                                                  // 正/反転の割合
    int         i;                                                  // カウンタ
    int         firstSw;                                            // 真→先頭処理済み
    int         n1;                                                 // 有効個数

「BYTE* ptrA;」は、A画像用処理ポインタ
「BYTE* ptrBX;」は、B画像用X座標方向処理ポインタ
「BYTE* ptrBY;」は、B画像用Y座標方向処理ポインタ
「int minH;」は、B画像の水平幅最小値
「int minV;」は、B画像の垂直幅最小値
「int incB;」は、B画像増加幅
「int sumA;」は、A画像用合計値、及び分散値算出用
「int avA;」は、A画像平均値
「int avB;」は、B画像平均値
「double d;」は、相関値
「int x;」は、X座標
「int y;」は、Y座標
「double r;」は、正/反転の割合
「int i;」は、ループカウンタ外側
「int firstSw;」は、スィッチ:先頭処理済み(真)
「int n1;」は、有効個数

(D-2)アルゴリズムコード

    n = ( n < pa->h ) ? n : pa->h;                                  // 対象物のサイズを
    m = ( m < pa->v ) ? m : pa->v;                                  // 対象画像内に補正
    if( pb->h < n || pb->v < m ){                                   // サーチ範囲が不適合なら
        return( 0 );                                                // 0を返し終了
    }                                                               // 
    if( n * m >= 65536 ){                                           // n×mが整数での内部演算を超える時
        return( SearchCorrImageXYSortLarge( pa, pb, buf, size,      // 左記で処理する
                                n, m, t, rate, minAv, maxAv ) );    // 
    }                                                               // 
    minH    = pb->h - n;                                            // 水平幅の最小値算出
    minV    = pb->v - m;                                            // 垂直幅の最小値算出
    n1      = 0;                                                    // 有効個数初期化
    ptrA    = (BYTE*)pa->adr;                                       // A配列:処理ポインタ
    ptrB    = (BYTE*)pb->adr;                                       // B配列:処理ポインタ
    incB    = pb->inc;                                              // B配列:増加幅
    firstSw = FALSE;                                                // 偽→先頭処理未実行
    for( i = 0; i < size; i++ ){                                    // 最初から最後まで
        x = buf[i].x;                                               // 座標値を取り出し
        y = buf[i].y;                                               // 
        if( x >= 0 && x < minH && y >= 0 && y < minV ){             // 有効範囲内ならば
            ptrBXY = ptrB + x + y * incB;                           // ポインタを算出
            if( !firstSw ){                                         // 先頭ならば
                firstSw = TRUE;                                     // 先頭処理済みをセット
                d       = CorrNMFirst( ptrA, ptrBXY,                // 先頭の時の相関値算出
                                            pa->inc, pb->inc,       //
                                            n, m, avA, avB, sumA ); // 
            }else{                                                  // 2番目以降ならば
                d = CorrNMSecond( ptrA, ptrBXY, pa->inc, pb->inc,   // n×m画素の正規相関を
                                            n, m, avA, avB, sumA ); // 算出
            }                                                       //
            if( d >= t ){                                           // 有効な値ならば
                if( minAv > 0.0 ){                                  // 範囲最小割合有効時
                    if( avB < avA * minAv ){                        // 対象の平均が範囲未満なら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
                if( maxAv > 0.0 && minAv < maxAv ){                 // 範囲最大割合有効時
                    if( avB > avA * maxAv ){                        // 対象の平均が範囲Overなら
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                if( rate > 0.0 ){                                   // 正/反転検査時
                    r = CorrNMCheck( ptrA, ptrBXY,                  // 正/反転の割合を
                                pa->inc, pb->inc, n, m, avA, avB ); // 算出
                    if( r < rate ){                                 // 割合未満の時
                        d = 0.0;                                    // 相関値を無効化
                    }                                               // 
                }                                                   // 
            }                                                       // 
            if( d >= t ){                                           // 有効な値ならば
                buf[n1].d = d;                                      // 正規化相関値と
                buf[n1].x = x;                                      // 座標を
                buf[n1].y = y;                                      // 格納
                n1++;                                               // 有効個数UP
            }                                                       //
        }                                                           // 
    }                                                               // 
    Sort( 1, buf, n1 );                                             // 降順にソート
    return( n1 );                                                   // 有効個数を返す
}

「n=(n<pa->h)?n:pa->h;m=(m<pa->v)?m:pa->v;」は、
A画像(テンプレート画像)のサイズと仮引数
「int n;int m;」の小さい方をN×Mとする様に調整!
「if(pb->h<n||pb->v<m){return(0);}」は、
B画像(サーチ対象画像)の画像サイズがN×Mより小さい
場合「return(0);」結果個数を0にして関数終了!
「if(nm>=65536){・・成立中身・・}」は、if条件
「nm>=65536」でN×Mサイズが大きい場合の専用処理
とし「SearchCorrImageXYSortLarge(pa,pb,buf,size,n,m,
t,rate,minAv,maxAv)」とサブルーチン関数
「SearchCorrImageXYSortLarge()」で専用関数で処理し、
その関数辺値を「return(・・・);」で返し関数終了!
「minH=pb->h-n;minV=pb->v-m;」は、画像Bの有効水平
垂直幅を算出!
「n1=0;」は、有効個数の初期化
「ptrA=(BYTE*)pa->adr;ptrB=(BYTE*)pb->adr;」は、
処理ポインタをセット!
「incB=pb->inc;」は、画像Bの垂直幅を扱いやすい変数に
セットで高速化!
「firstSw=FALSE;」は、先頭処理済み(真)スィッチを
初期化!
次は、処理するループで
「for(i=0;i<size;i++){・・ループ本体・・}」は、
ループ初期値「i=0;」ループ条件「i<size;」ループ終了
後処理「i++」と教科書的for構文でのアップカウンタ
「i=0;」を条件「i<size;」増分「i++,」と「0からsize未満」
まで繰り返しバッファー格納のデータを取り出し操作する
構文です!ループ本体は、
「x=buf[i].x;y=buf[i].y;」は、XY座標を取り出し、
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立本
体・・」は、条件「x>=0&&x<minH&&y>=0&&y<minV」で
XY座標が範囲内の場合、成立本体≪★注意★成立ブロック
だけ存在し不成立ブロックは有りません≫として
「ptrBXY=ptrB+x+yincB;」は、XY座標から操作ポインタ
を算出、
「if(!firstSw){」は、if条件「!firstSw」と成立時に
初回「first」を意味するスイッチを「firstSw=TRUE;」と
セットした直後に「d=CorrNMFirst(ptrA,ptrBXY,
pa->inc,pb->inc,n,m,avA,avB,sumA);」とサブルーチン
関数「CorrNMFirst()」で相関値を再算出し、
「else{d=CorrNMSecond(ptrA,ptrBXY,pa->inc,pb->inc,
n,m,avA,avB,sumA);}」と「else{」と不成立時=初回「
first」以外=2回目以降としてサブルーチン
関数「CorrNMSecond()」で相関値を再算出!★注意★ここ
だけ「else{・・}」と不成立ブロックが存在し、1回目か
2回目以降の処理かをサブルーチン関数で再算出処理を分け
て居る事に留意して下さい!この関数では他に「else」は
存在しません!
「if(d>=t){if(minAv>0.0){if(avB<avAminAv){d=0.0;}}」
は、if条件「d>=t」で相関値が有効な時にブロック
「{・・}」を処理で更にif条件「minAv>0.0」で仮引数
「double minAv,double maxAv」が条件として有効な場合と
して、更にif条件「maxAv>0.0&&minAv<maxAv」を満足
したら、「if(avB>avA*maxAv){d=0.0;}}}」で相関値を
無効化!其れを通過した後で、また、if条件「d>=t」で
相関値が有効な時に条件「rate>0.0」と仮引数
「double rate,」は、サーチ条件の一つ(正負割合)が
有効な場合としての操作で「r=CorrNMCheck(ptrA,ptrBXY,
pa->inc,pb->inc,n,m,avA,avB);」でサブルーチン関数
「CorrNMCheck()」で割合「r」を算出し、これで判断で
「if(r<rate){d=0.0;}」で相関値を無効化!
そしてココまでif条件「d>=t」で相関値が有効な時に
「buf[n1].d=d;buf[n1].x=x;buf[n1].y=y;n1++;」で
バッファーへ格納≪相関値、XY座標≫、
forループを終えると「Sort(1,buf,n1);return(n1);」
で相関値で降順(大⇒小)にソートし、個数「n1」を
関数辺値とし返し関数終了!

(4-14-184)関数「void ReductImage(
TypeArray* ps,TypeArray* pd,
int mode){・・・}」

/************************************************************************/
/*****      画像圧縮                                                *****/
/************************************************************************/

void            CopyClear::ReductImage(
    TypeArray*  ps,                                     // S配列
    TypeArray*  pd,                                     // D配列
    int         mode                                    // モード 0:間引,1:平均,
                                                        // 2:最大,3:最小,4:2番,5:3番
){
    BYTE*       ptrS;                                   // S配列:処理ポインタ
    BYTE*       ptrD;                                   // D配列:処理ポインタ
    int         incS;                                   // S配列:増加幅
    int         incD;                                   // D配列:増加幅
    int         n;                                      // n×mのn
    int         m;                                      // n×mのm

    ptrS = (BYTE*)ps->adr;                              // S配列:処理ポインタ
    ptrD = (BYTE*)pd->adr;                              // D配列:処理ポインタ
    incS = ps->inc;                                     // S配列:増加幅
    incD = pd->inc;                                     // D配列:増加幅
    n    = ps->h / 2;                                   // n×mのn算出
    n    = ( n <= pd->h ) ? n : pd->h;                  // (Sの1/2かDの小さい方)
    m    = ps->v / 2;                                   // n×mのm算出
    m    = ( m <= pd->v ) ? m : pd->v;                  // (Sの1/2かDの小さい方)
    if( mode == 0 ){                                    // 間引き時
        ReductNMSkip( ptrS, ptrD, incS, incD, n, m );   // 画像1/2縮尺:間引
    }else if( mode == 1 ){                              // 平均時
        ReductNMAve( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:平均
    }else if( mode == 2 ){                              // 最大時
        ReductNMMax( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:最大
    }else if( mode == 3 ){                              // 最小時
        ReductNMMin( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:最小
    }else if( mode == 4 ){                              // 2番時
        ReductNMTwo( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:2番
    }else if( mode == 5 ){                              // 3番時
        ReductNMThree( ptrS, ptrD, incS, incD, n, m );  // 画像1/2縮尺:3番
    }                                                   // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「void ReductImage()」の【関数名】


「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像、ここでは、画像を縮小≪4画素
(左上・右上・左下・右下)を1画素に加工≫する事を示し
ます!

(B)関数「void ReductImage()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「ReductImage()」の【仮引数】

void            CopyClear::ReductImage(
    TypeArray*  ps,                                     // S配列
    TypeArray*  pd,                                     // D配列
    int         mode                                    // モード 0:間引,1:平均,
                                                        // 2:最大,3:最小,4:2番,5:3番
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd」は、D(結果)画像情報
「int mode」は、画像を縮小するモード(方法)で
0⇒間引き、1⇒平均値、2⇒最大値、3⇒最小値間引き、
4⇒昇順に2番目、5⇒昇順に3番目

(D)関数「ReductImage()」の【アルゴリズム】

){
    BYTE*       ptrS;                                   // S配列:処理ポインタ
    BYTE*       ptrD;                                   // D配列:処理ポインタ
    int         incS;                                   // S配列:増加幅
    int         incD;                                   // D配列:増加幅
    int         n;                                      // n×mのn
    int         m;                                      // n×mのm

    ptrS = (BYTE*)ps->adr;                              // S配列:処理ポインタ
    ptrD = (BYTE*)pd->adr;                              // D配列:処理ポインタ
    incS = ps->inc;                                     // S配列:増加幅
    incD = pd->inc;                                     // D配列:増加幅
    n    = ps->h / 2;                                   // n×mのn算出
    n    = ( n <= pd->h ) ? n : pd->h;                  // (Sの1/2かDの小さい方)
    m    = ps->v / 2;                                   // n×mのm算出
    m    = ( m <= pd->v ) ? m : pd->v;                  // (Sの1/2かDの小さい方)
    if( mode == 0 ){                                    // 間引き時
        ReductNMSkip( ptrS, ptrD, incS, incD, n, m );   // 画像1/2縮尺:間引
    }else if( mode == 1 ){                              // 平均時
        ReductNMAve( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:平均
    }else if( mode == 2 ){                              // 最大時
        ReductNMMax( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:最大
    }else if( mode == 3 ){                              // 最小時
        ReductNMMin( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:最小
    }else if( mode == 4 ){                              // 2番時
        ReductNMTwo( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:2番
    }else if( mode == 5 ){                              // 3番時
        ReductNMThree( ptrS, ptrD, incS, incD, n, m );  // 画像1/2縮尺:3番
    }                                                   // 
}

(D-1)ローカル変数

){
    BYTE*       ptrS;                                   // S配列:処理ポインタ
    BYTE*       ptrD;                                   // D配列:処理ポインタ
    int         incS;                                   // S配列:増加幅
    int         incD;                                   // D配列:増加幅
    int         n;                                      // n×mのn
    int         m;                                      // n×mのm

「BYTE* ptrS;」は、S画像処理ポインタ
「BYTE* ptrD;」は、D画像処理ポインタ
「int incS;」は、S画像増加幅
「int incD;」は、D画像増加幅
「int n;」は、N×M升枠の「N」のサイズ
「int m;」は、N×M升枠の「M」のサイズ

(D-2)アルゴリズムコード

    ptrS = (BYTE*)ps->adr;                              // S配列:処理ポインタ
    ptrD = (BYTE*)pd->adr;                              // D配列:処理ポインタ
    incS = ps->inc;                                     // S配列:増加幅
    incD = pd->inc;                                     // D配列:増加幅
    n    = ps->h / 2;                                   // n×mのn算出
    n    = ( n <= pd->h ) ? n : pd->h;                  // (Sの1/2かDの小さい方)
    m    = ps->v / 2;                                   // n×mのm算出
    m    = ( m <= pd->v ) ? m : pd->v;                  // (Sの1/2かDの小さい方)
    if( mode == 0 ){                                    // 間引き時
        ReductNMSkip( ptrS, ptrD, incS, incD, n, m );   // 画像1/2縮尺:間引
    }else if( mode == 1 ){                              // 平均時
        ReductNMAve( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:平均
    }else if( mode == 2 ){                              // 最大時
        ReductNMMax( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:最大
    }else if( mode == 3 ){                              // 最小時
        ReductNMMin( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:最小
    }else if( mode == 4 ){                              // 2番時
        ReductNMTwo( ptrS, ptrD, incS, incD, n, m );    // 画像1/2縮尺:2番
    }else if( mode == 5 ){                              // 3番時
        ReductNMThree( ptrS, ptrD, incS, incD, n, m );  // 画像1/2縮尺:3番
    }                                                   // 
}

「ptrS=(BYTE*)ps->adr;」は、S画像実操作ポインタセット
「ptrD=(BYTE*)pd->adr;」は、D画像実操作ポインタセット
「incS=ps->inc;incD=pd->inc;」は、SD画像増加幅を使い
易い(高速化)様にセット
「n=ps->h/2;n=(n<=pd->h)?n:pd->h;」は、SD画像サイズ
からN×M升枠の「N」のサイズ算出!
「m=ps->v/2;m=(m<=pd->v)?m:pd->v;」は、SD画像
サイズからN×M升枠の「M」のサイズ算出!
多重分岐if構文「if(mode==0){・・対応中身・・}else
if(mode==1){・・対応中身・・}else if(mode==2){
・・対応中身・・}elseif(mode==3){・・対応中身・・
}else if(mode==4){・・対応中身・・}else if(mode==5){
・・対応中身・・}」とC言語のif構文にお馴染みの
多重分岐で仮引数「int mode」の値に依って、
0の場合は「ReductNMSkip(ptrS,ptrD,incS,incD,n,m);」
1の場合は「ReductNMAve(ptrS,ptrD,incS,incD,n,m);」
2の場合は「ReductNMMax(ptrS,ptrD,incS,incD,n,m);」
3の場合は「ReductNMMin(ptrS,ptrD,incS,incD,n,m);」
4の場合は「ReductNMTwo(ptrS,ptrD,incS,incD,n,m);」
5の場合は「ReductNMThree(ptrS,ptrD,incS,incD,n,m);」
と分岐してサブルーチン関数で処理します!
★注意★「mode」が0・・5以外の場合は、何もシマセン
只、処理時間が掛かるだけです!

(4-14-185)関数「void ReductImageNMAve(
TypeArray* ps,TypeArray* pd,
int n,int m){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関用画像圧縮(平均値)                *****/
/*****      ☆任意のn×m×4画素で構成される画像を                *****/
/*****      ☆n×mの基本単位毎に圧縮:平均☆                      *****/
/************************************************************************/

void            CopyClear::ReductImageNMAve(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMAve( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                    n, m );     // (平均値圧縮)
        }                                                       // 
    }                                                           // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「void ReductImageNMAve()」の【関数名】

「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像、ここでは、画像を縮小≪4画素
(左上・右上・左下・右下)を1画素に加工≫する事を示し
ます!
「NM」は、画像の範囲として「縦×横=N×M画素」の
サイズを意味します!
「Ave」は、英単語「Average」省略形で「平均値」を意味
し、ここでは、縮小する時、平均値で縮小する事を示しま
す!

(B)関数「void ReductImageNMAve()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「ReductImageNMAve()」の【仮引数】

void            CopyClear::ReductImageNMAve(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd」は、D(結果)画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!

(D)関数「ReductImageNMAve()」の【アルゴリズム】

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMAve( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                    n, m );     // (平均値圧縮)
        }                                                       // 
    }                                                           // 
}

(D-1)ローカル変数

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

「BYTE* ptrSX;」は、S画像X座標方向処理ポインタ
「BYTE* ptrDX;」は、D画像X座標方向処理ポインタ
「BYTE* ptrSY;」は、S画像Y座標方向処理ポインタ
「BYTE* ptrDY;」は、D画像Y座標方向処理ポインタ
「int incS;」は、S画像増加幅
「int incD;」は、D画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMAve( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                    n, m );     // (平均値圧縮)
        }                                                       // 
    }                                                           // 
}

「h=ps->h/2;h=((h<pd->h)?h:pd->h)/n;」は、SD画像
サイズから水平幅(N×Mの個数)算出!
「v=ps->v/2;v=((v<pd->v)?v:pd->v)/m;」は、SD画像
サイズから垂直幅(N×Mの個数)算出!
「ptrSY=(BYTE*)ps->adr;ptrDY=(BYTE*)pd->adr;」は、
SD画像の処理ポインタをセット!
「incS=ps->incm2;」は、S画像をN×M升枠単位垂直
増加幅算出!
「incD=pd->incm;」は、D画像をN×M升枠単位垂直
増加幅算出!
「for(;--v>=0;ptrSY+=incS,ptrDY+=incD){・・外側ループ
本体・・}」は、forループ構文で良くこの解説で紹介
するループ条件「--v>=0;」で垂直個数繰り返し、中身で
垂直方向の処理を行い、ループ後置「ptrSY+=incS,
ptrDY+=incD」でSD両者の垂直方向処理ポインタを進行!
外側ループ本体「ptrSX=ptrSY;ptrDX=ptrDY;」は、SD両者
の水平方向処理ポインタの始点をセット、
「for(i=h;--i>=0;ptrSX+=n2,ptrDX+=n){
ReductNMAve(ptrSX,ptrDX,ps->inc,pd->inc,n,m);}」は、
forループ構文で内側のループ初期化「i=h;」で一旦、
ループカウンタをセット!ループ条件「--i>=0;」水平方向
繰り返し、中身でサブルーチン関数「ReductNMAve()」で
S画像を(N×2)×(M×2)升枠単位から
D画像をN×M升枠単位に縮小します!

(4-14-186)関数「void ReductImageNMMin(
TypeArray* ps,TypeArray* pd,
int n,int m){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関用画像圧縮(最小値)                *****/
/*****      ☆任意のn×m×4画素で構成される画像を                *****/
/*****      ☆n×mの基本単位毎に圧縮:最小☆                      *****/
/************************************************************************/

void            CopyClear::ReductImageNMMin(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMMin( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (最小値圧縮)
        }                                                       // 
    }                                                           // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「void ReductImageNMMin()」の【関数名】

「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像、ここでは、画像を縮小≪4画素
(左上・右上・左下・右下)を1画素に加工≫する事を示し
ます!
「NM」は、画像の範囲として「縦×横=N×M画素」の
サイズを意味します!
「Min」は、英単語「minimum」の省略形で色抽出方法が、
「最小値」を意味し、ここでは、縮小する時、最小値で
縮小する事を示します!

(B)関数「void ReductImageNMMin()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「ReductImageNMMin()」の【仮引数】

void            CopyClear::ReductImageNMMin(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd」は、D(結果)画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!

(D)関数「ReductImageNMMin()」の【アルゴリズム】

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMMin( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (最小値圧縮)
        }                                                       // 
    }                                                           // 
}

(D-1)ローカル変数

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

「BYTE* ptrSX;」は、S画像X座標方向処理ポインタ
「BYTE* ptrDX;」は、D画像X座標方向処理ポインタ
「BYTE* ptrSY;」は、S画像Y座標方向処理ポインタ
「BYTE* ptrDY;」は、D画像Y座標方向処理ポインタ
「int incS;」は、S画像増加幅
「int incD;」は、D画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMMin( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (最小値圧縮)
        }                                                       // 
    }                                                           // 
}

「h=ps->h/2;h=((h<pd->h)?h:pd->h)/n;」は、SD画像
サイズから水平幅(N×Mの個数)算出!
「v=ps->v/2;v=((v<pd->v)?v:pd->v)/m;」は、SD画像
サイズから垂直幅(N×Mの個数)算出!
「ptrSY=(BYTE*)ps->adr;ptrDY=(BYTE*)pd->adr;」は、
SD画像の処理ポインタをセット!
「incS=ps->incm2;」は、S画像をN×M升枠単位垂直
増加幅算出!
「incD=pd->incm;」は、D画像をN×M升枠単位垂直
増加幅算出!
「for(;--v>=0;ptrSY+=incS,ptrDY+=incD){・・外側ループ
本体・・}」は、forループ構文で良くこの解説で紹介
するループ条件「--v>=0;」で垂直個数繰り返し、中身で
垂直方向の処理を行い、ループ後置「ptrSY+=incS,
ptrDY+=incD」でSD両者の垂直方向処理ポインタを進行!
外側ループ本体「ptrSX=ptrSY;ptrDX=ptrDY;」は、SD両者
の水平方向処理ポインタの始点をセット、
「for(i=h;--i>=0;ptrSX+=n2,ptrDX+=n){
ReductNMMin(ptrSX,ptrDX,ps->inc,pd->inc,n,m);}」は、
forループ構文で内側のループ初期化「i=h;」で一旦、
ループカウンタをセット!ループ条件「--i>=0;」水平方向
繰り返し、中身でサブルーチン関数「ReductNMMin()」で
S画像を(N×2)×(M×2)升枠単位から
D画像をN×M升枠単位に縮小します!

(4-14-187)関数「void ReductImageNMMax(
TypeArray* ps,TypeArray* pd,
int n,int m){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関用画像圧縮(最大値)                *****/
/*****      ☆任意のn×m×4画素で構成される画像を                *****/
/*****      ☆n×mの基本単位毎に圧縮:最大☆                      *****/
/************************************************************************/

void            CopyClear::ReductImageNMMax(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMMax( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (最大値圧縮)
        }                                                       // 
    }                                                           // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「void ReductImageNMMax()」の【関数名】

「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像、ここでは、画像を縮小≪4画素
(左上・右上・左下・右下)を1画素に加工≫する事を示し
ます!
「NM」は、画像の範囲として「縦×横=N×M画素」の
サイズを意味します!
「Max」は、英単語「Maximum」の省略形で色抽出方法が、
「最大値」を意味し、ここでは、縮小する時、最大値で
縮小する事を示します!

(B)関数「void ReductImageNMMax()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「ReductImageNMMax()」の【仮引数】

void            CopyClear::ReductImageNMMax(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd」は、D(結果)画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!

(D)関数「ReductImageNMMax()」の【アルゴリズム】

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMMax( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (最大値圧縮)
        }                                                       // 
    }                                                           // 
}

(D-1)ローカル変数

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

「BYTE* ptrSX;」は、S画像X座標方向処理ポインタ
「BYTE* ptrDX;」は、D画像X座標方向処理ポインタ
「BYTE* ptrSY;」は、S画像Y座標方向処理ポインタ
「BYTE* ptrDY;」は、D画像Y座標方向処理ポインタ
「int incS;」は、S画像増加幅
「int incD;」は、D画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMMax( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (最大値圧縮)
        }                                                       // 
    }                                                           // 
}

「h=ps->h/2;h=((h<pd->h)?h:pd->h)/n;」は、SD画像
サイズから水平幅(N×Mの個数)算出!
「v=ps->v/2;v=((v<pd->v)?v:pd->v)/m;」は、SD画像
サイズから垂直幅(N×Mの個数)算出!
「ptrSY=(BYTE*)ps->adr;ptrDY=(BYTE*)pd->adr;」は、
SD画像の処理ポインタをセット!
「incS=ps->incm2;」は、S画像をN×M升枠単位垂直
増加幅算出!
「incD=pd->incm;」は、D画像をN×M升枠単位垂直
増加幅算出!
「for(;--v>=0;ptrSY+=incS,ptrDY+=incD){・・外側ループ
本体・・}」は、forループ構文で良くこの解説で紹介
するループ条件「--v>=0;」で垂直個数繰り返し、中身で
垂直方向の処理を行い、ループ後置「ptrSY+=incS,
ptrDY+=incD」でSD両者の垂直方向処理ポインタを進行!
外側ループ本体「ptrSX=ptrSY;ptrDX=ptrDY;」は、SD両者
の水平方向処理ポインタの始点をセット、
「for(i=h;--i>=0;ptrSX+=n2,ptrDX+=n){
ReductNMMax(ptrSX,ptrDX,ps->inc,pd->inc,n,m);}」は、
forループ構文で内側のループ初期化「i=h;」で一旦、
ループカウンタをセット!ループ条件「--i>=0;」水平方向
繰り返し、中身でサブルーチン関数「ReductNMMax()」で
S画像を(N×2)×(M×2)升枠単位から
D画像をN×M升枠単位に縮小します!

(4-14-188)関数「void ReductImageNMTwo(
TypeArray* ps,TypeArray* pd,
int n,int m){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関用画像圧縮(昇順に2番目の値)      *****/
/*****      ☆任意のn×m×4画素で構成される画像を                *****/
/*****      ☆n×mの基本単位毎に圧縮:2番目☆                    *****/
/************************************************************************/

void            CopyClear::ReductImageNMTwo(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMTwo( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (2番目の値で圧縮)
        }                                                       // 
    }                                                           // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「void ReductImageNMTwo()」の【関数名】

「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像、ここでは、画像を縮小≪4画素
(左上・右上・左下・右下)を1画素に加工≫する事を示し
ます!
「NM」は、画像の範囲として「縦×横=N×M画素」の
サイズを意味します!
「Two」は、英単語「Two」、勿論、数値「2」の事
「二番目」です!ここでは、縮小する時、昇順(小⇒大)
二番目の値で縮小する事を示します!

(B)関数「void ReductImageNMTwo()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「ReductImageNMTwo()」の【仮引数】

void            CopyClear::ReductImageNMTwo(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd」は、D(結果)画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!

(D)関数「ReductImageNMTwo()」の【アルゴリズム】

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMTwo( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (2番目の値で圧縮)
        }                                                       // 
    }                                                           // 
}

(D-1)ローカル変数

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

「BYTE* ptrSX;」は、S画像X座標方向処理ポインタ
「BYTE* ptrDX;」は、D画像X座標方向処理ポインタ
「BYTE* ptrSY;」は、S画像Y座標方向処理ポインタ
「BYTE* ptrDY;」は、D画像Y座標方向処理ポインタ
「int incS;」は、S画像増加幅
「int incD;」は、D画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMTwo( ptrSX, ptrDX, ps->inc, pd->inc,        // n×m×4→n×mに縮小
                                                        n, m ); // (2番目の値で圧縮)
        }                                                       // 
    }                                                           // 
}

「h=ps->h/2;h=((h<pd->h)?h:pd->h)/n;」は、SD画像
サイズから水平幅(N×Mの個数)算出!
「v=ps->v/2;v=((v<pd->v)?v:pd->v)/m;」は、SD画像
サイズから垂直幅(N×Mの個数)算出!
「ptrSY=(BYTE*)ps->adr;ptrDY=(BYTE*)pd->adr;」は、
SD画像の処理ポインタをセット!
「incS=ps->incm2;」は、S画像をN×M升枠単位垂直
増加幅算出!
「incD=pd->incm;」は、D画像をN×M升枠単位垂直
増加幅算出!
「for(;--v>=0;ptrSY+=incS,ptrDY+=incD){・・外側ループ
本体・・}」は、forループ構文で良くこの解説で紹介
するループ条件「--v>=0;」で垂直個数繰り返し、中身で
垂直方向の処理を行い、ループ後置「ptrSY+=incS,
ptrDY+=incD」でSD両者の垂直方向処理ポインタを進行!
外側ループ本体「ptrSX=ptrSY;ptrDX=ptrDY;」は、SD両者
の水平方向処理ポインタの始点をセット、
「for(i=h;--i>=0;ptrSX+=n2,ptrDX+=n){
ReductNMTwo(ptrSX,ptrDX,ps->inc,pd->inc,n,m);}」は、
forループ構文で内側のループ初期化「i=h;」で一旦、
ループカウンタをセット!ループ条件「--i>=0;」水平方向
繰り返し、中身でサブルーチン関数「ReductNMTwo()」で
S画像を(N×2)×(M×2)升枠単位から
D画像をN×M升枠単位に縮小します!

(4-14-189)関数「void ReductImageNMThree(
TypeArray* ps,TypeArray* pd,
int n,int m){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関用画像圧縮(昇順に3番目の値)      *****/
/*****      ☆任意のn×m×4画素で構成される画像を                *****/
/*****      ☆n×mの基本単位毎に圧縮:3番目☆                    *****/
/************************************************************************/

void            CopyClear::ReductImageNMThree(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMThree( ptrSX, ptrDX, ps->inc, pd->inc,      // n×m×4→n×mに縮小
                                                        n, m ); // (3番目の値で圧縮)
        }                                                       // 
    }                                                           // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「void ReductImageNMThree()」の【関数名】

「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像、ここでは、画像を縮小≪4画素
(左上・右上・左下・右下)を1画素に加工≫する事を示し
ます!
「NM」は、画像の範囲として「縦×横=N×M画素」の
サイズを意味します!
「Three」は、英単語「Three」、勿論、数値「3」の事
で「三番目」です!ここでは、縮小する時、昇順(小⇒大)
三番目の値で縮小する事を示します!

(B)関数「void ReductImageNMThree()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「ReductImageNMThree()」の【仮引数】

void            CopyClear::ReductImageNMThree(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd」は、D(結果)画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!

(D)関数「ReductImageNMThree()」の【アルゴリズム】

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMThree( ptrSX, ptrDX, ps->inc, pd->inc,      // n×m×4→n×mに縮小
                                                        n, m ); // (3番目の値で圧縮)
        }                                                       // 
    }                                                           // 
}

(D-1)ローカル変数

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

「BYTE* ptrSX;」は、S画像X座標方向処理ポインタ
「BYTE* ptrDX;」は、D画像X座標方向処理ポインタ
「BYTE* ptrSY;」は、S画像Y座標方向処理ポインタ
「BYTE* ptrDY;」は、D画像Y座標方向処理ポインタ
「int incS;」は、S画像増加幅
「int incD;」は、D画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMThree( ptrSX, ptrDX, ps->inc, pd->inc,      // n×m×4→n×mに縮小
                                                        n, m ); // (3番目の値で圧縮)
        }                                                       // 
    }                                                           // 
}

「h=ps->h/2;h=((h<pd->h)?h:pd->h)/n;」は、SD画像
サイズから水平幅(N×Mの個数)算出!
「v=ps->v/2;v=((v<pd->v)?v:pd->v)/m;」は、SD画像
サイズから垂直幅(N×Mの個数)算出!
「ptrSY=(BYTE*)ps->adr;ptrDY=(BYTE*)pd->adr;」は、
SD画像の処理ポインタをセット!
「incS=ps->incm2;」は、S画像をN×M升枠単位垂直
増加幅算出!
「incD=pd->incm;」は、D画像をN×M升枠単位垂直
増加幅算出!
「for(;--v>=0;ptrSY+=incS,ptrDY+=incD){・・外側ループ
本体・・}」は、forループ構文で良くこの解説で紹介
するループ条件「--v>=0;」で垂直個数繰り返し、中身で
垂直方向の処理を行い、ループ後置「ptrSY+=incS,
ptrDY+=incD」でSD両者の垂直方向処理ポインタを進行!
外側ループ本体「ptrSX=ptrSY;ptrDX=ptrDY;」は、SD両者
の水平方向処理ポインタの始点をセット、
「for(i=h;--i>=0;ptrSX+=n2,ptrDX+=n){
ReductNMThree(ptrSX,ptrDX,ps->inc,pd->inc,n,m);}」は、
forループ構文で内側のループ初期化「i=h;」で一旦、
ループカウンタをセット!ループ条件「--i>=0;」水平方向
繰り返し、中身でサブルーチン関数「ReductNMThree()」で
S画像を(N×2)×(M×2)升枠単位から
D画像をN×M升枠単位に縮小します!

(4-14-190)関数「void ReductImageNMSkip(
TypeArray* ps,TypeArray* pd,
int n,int m){・・・}」

/************************************************************************/
/*****      n×m画素正規化相関用画像圧縮(間引き:左上の画素の値)*****/
/*****      ☆任意のn×m×4画素で構成される画像を                *****/
/*****      ☆n×mの基本単位毎に圧縮:間引き☆                    *****/
/************************************************************************/

void            CopyClear::ReductImageNMSkip(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMSkip( ptrSX, ptrDX, ps->inc, pd->inc,       // n×m×4→n×mに縮小
                                                        n, m ); // (間引き圧縮)
        }                                                       // 
    }                                                           // 
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「void ReductImageNMSkip()」の【関数名】

「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像、ここでは、画像を縮小≪4画素
(左上・右上・左下・右下)を1画素に加工≫する事を示し
ます!
「NM」は、画像の範囲として「縦×横=N×M画素」の
サイズを意味します!
「Skip」は、英単語「Skip」、カタカナ語でスキップ!
ここでは、縮小する時、縮小対象の元画像≪左上・右上・
左下・右下≫の内「左上」を代表として縮小する事を示し
ます!

(B)関数「void ReductImageNMSkip()」の【返値】

関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「ReductImageNMSkip()」の【仮引数】

void            CopyClear::ReductImageNMSkip(
    TypeArray*  ps,                                             // S配列
    TypeArray*  pd,                                             // D配列
    int         n,                                              // n×mのn
    int         m                                               // n×mのm
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd」は、D(結果)画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!

(D)関数「ReductImageNMSkip()」の【アルゴリズム】

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMSkip( ptrSX, ptrDX, ps->inc, pd->inc,       // n×m×4→n×mに縮小
                                                        n, m ); // (間引き圧縮)
        }                                                       // 
    }                                                           // 
}

(D-1)ローカル変数

){
    BYTE*       ptrSX;                                          // S配列:処理ポインタ
    BYTE*       ptrDX;                                          // D配列:処理ポインタ
    BYTE*       ptrSY;                                          // S配列:処理ポインタ
    BYTE*       ptrDY;                                          // D配列:処理ポインタ
    int         incS;                                           // S配列:増加幅(n×m×4単位)
    int         incD;                                           // D配列:増加幅(n×m単位)
    int         h;                                              // 水平幅(n×mの個数)
    int         v;                                              // 垂直幅(n×mの個数)
    int         i;                                              // カウンタ

「BYTE* ptrSX;」は、S画像X座標方向処理ポインタ
「BYTE* ptrDX;」は、D画像X座標方向処理ポインタ
「BYTE* ptrSY;」は、S画像Y座標方向処理ポインタ
「BYTE* ptrDY;」は、D画像Y座標方向処理ポインタ
「int incS;」は、S画像増加幅
「int incD;」は、D画像増加幅
「int h;」は、水平幅(N×Mの個数)
「int v;」は、垂直幅(N×Mの個数)
「int i;」は、ループカウンタ

(D-2)アルゴリズムコード

    h     = ps->h / 2;                                          // 水平個数を
    h     = ( ( h < pd->h ) ? h : pd->h ) / n;                  // 算出
    v     = ps->v / 2;                                          // 垂直個数を
    v     = ( ( v < pd->v ) ? v : pd->v ) / m;                  // 算出
    ptrSY = (BYTE*)ps->adr;                                     // S配列:処理ポインタ
    ptrDY = (BYTE*)pd->adr;                                     // D配列:処理ポインタ
    incS  = ps->inc * m * 2;                                    // S配列:増加幅(n×m×4単位)
    incD  = pd->inc * m;                                        // D配列:増加幅(n×m単位)
    for( ; --v >= 0; ptrSY += incS, ptrDY += incD ){            // 垂直個数分
        ptrSX = ptrSY;                                          // S配列:水平始点
        ptrDX = ptrDY;                                          // D配列:水平始点
        for( i = h; --i >= 0; ptrSX += n * 2, ptrDX += n ){     // 水平個数分
            ReductNMSkip( ptrSX, ptrDX, ps->inc, pd->inc,       // n×m×4→n×mに縮小
                                                        n, m ); // (間引き圧縮)
        }                                                       // 
    }                                                           // 
}

「h=ps->h/2;h=((h<pd->h)?h:pd->h)/n;」は、SD画像
サイズから水平幅(N×Mの個数)算出!
「v=ps->v/2;v=((v<pd->v)?v:pd->v)/m;」は、SD画像
サイズから垂直幅(N×Mの個数)算出!
「ptrSY=(BYTE*)ps->adr;ptrDY=(BYTE*)pd->adr;」は、
SD画像の処理ポインタをセット!
「incS=ps->incm2;」は、S画像をN×M升枠単位垂直
増加幅算出!
「incD=pd->incm;」は、D画像をN×M升枠単位垂直
増加幅算出!
「for(;--v>=0;ptrSY+=incS,ptrDY+=incD){・・外側ループ
本体・・}」は、forループ構文で良くこの解説で紹介
するループ条件「--v>=0;」で垂直個数繰り返し、中身で
垂直方向の処理を行い、ループ後置「ptrSY+=incS,
ptrDY+=incD」でSD両者の垂直方向処理ポインタを進行!
外側ループ本体「ptrSX=ptrSY;ptrDX=ptrDY;」は、SD両者
の水平方向処理ポインタの始点をセット、
「for(i=h;--i>=0;ptrSX+=n2,ptrDX+=n){
ReductNMSkip(ptrSX,ptrDX,ps->inc,pd->inc,n,m);}」は、
forループ構文で内側のループ初期化「i=h;」で一旦、
ループカウンタをセット!ループ条件「--i>=0;」水平方向
繰り返し、中身でサブルーチン関数「ReductNMSkip()」で
S画像を(N×2)×(M×2)升枠単位から
D画像をN×M升枠単位に縮小します!

(4-14-191)関数「void GetHVReductImageNM(
TypeArray* ps,TypeArray* pd,
int n,int m,int& resH,int& resV
){・・・}

/************************************************************************/
/*****      n×m画素正規化相関用画像圧縮(平均値)用縦横個数取得  *****/
/************************************************************************/

void            CopyClear::GetHVReductImageNM(
    TypeArray*  ps,                                     // S配列
    TypeArray*  pd,                                     // D配列
    int         n,                                      // n×mのn
    int         m,                                      // n×mのm
    int&        resH,                                   // 取得する水平個数
    int&        resV                                    // 取得する垂直個数
){
    resH = ps->h / 2;                                   // 水平個数を
    resH = ( ( resH < pd->h ) ? resH : pd->h ) / n;     // 算出
    resV = ps->v / 2;                                   // 垂直個数を
    resV = ( ( resV < pd->v ) ? resV : pd->v ) / m;     // 算出
}

☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「GetHVReductImageNM()」の【関数名】

「Get」は、カタカナ語でもゲット、詰り取得するで
「HV」は、水平・垂直方向の個数を意味します!
「Reduct」は、英単語「reduction」で縮小、
「Image」は、勿論、画像です!
「NM」は、縮小する画像の範囲として「縦×横=
N×M画素」のサイズを意味します!
この関数「GetHVReductImageNM()」は、その補助関数
として関数「ReductImage()」等のの前に
仮引数「int &resH,int &resV」で水平垂直方向の結果
個数を事前算出する事を行います!

(B)関数「void GetHVReductImageNM()」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「GetHVReductImageNM()」の【仮引数】

void            CopyClear::GetHVReductImageNM(
    TypeArray*  ps,                                     // S配列
    TypeArray*  pd,                                     // D配列
    int         n,                                      // n×mのn
    int         m,                                      // n×mのm
    int&        resH,                                   // 取得する水平個数
    int&        resV                                    // 取得する垂直個数
){

「TypeArray* ps」は、S(元)画像
「TypeArray* pd」は、D(結果)画像
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int &resH,」は、水平方向の結果個数
「int &resV」は、垂直方向の結果個数

(D)関数「GetHVReductImageNM()」の【アルゴリズム】

){
    resH = ps->h / 2;                                   // 水平個数を
    resH = ( ( resH < pd->h ) ? resH : pd->h ) / n;     // 算出
    resV = ps->v / 2;                                   // 垂直個数を
    resV = ( ( resV < pd->v ) ? resV : pd->v ) / m;     // 算出
}

「resH=ps->h/2;resH=((resH<pd->h)?resH:pd->h)/n;
resV=ps->v/2;resV=((resV<pd->v)?resV:pd->v)/m;」は、
S画像のサイズ÷2と仮引数「int n;int m;」の小さい方を
N×Mとする様に調整し、引数辺値にセット!

本日(2月6)の講義はココまでとします!まだ、
正規化相関系のpublics関数の説明は終わっていません!
※編集追加時に赤字「下書きの保存に失敗」と
noteエディタが忠告を出したので
この続きは、解説『クラスCopyClear(25)』
続きます!!引き続き御贔屓をお願いします!

文末

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