
解説クラスCopyClear(25)
解説クラスCopyClear(25)
2025年2月7初稿(初講)
正規化相関関数系の「public:属性」の関数の解説を行います
基本的に画像の比較を行う処理です!
解説『解説クラスCopyClear(24)』の続きです
(4-14-192)関数「void VectorCorrImageNM(
TypeArray* pa,
TypeArray* pb,
double* bufVecX,
double* bufVecY,int n,int m,
int nOffsetH,int nOffsetV,
int nStepH,int nStepV,
int& resH,int& resV){・・・}
/****************************************************************************/
/***** n×m画素正規化相関を使用した動線ベクトル算出 *****/
/****************************************************************************/
void CopyClear::VectorCorrImageNM(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
double* bufVecX, // X方向結果バッファー
double* bufVecY, // Y方向結果バッファー
int n, // n×mのn
int m, // n×mのm
int nOffsetH, // 水平方向オフセット(左右ずれ)
int nOffsetV, // 垂直方向オフセット(上下ずれ)
int nStepH, // 水平方向次点ステップ数
int nStepV, // 垂直方向次点ステップ数
int& resH, // 返値:取得する水平個数
int& resV // 返値:取得する垂直個数
){
BYTE* ptrAX; // A配列:処理ポインタ
BYTE* ptrAY; // A配列:処理ポインタ
BYTE* ptrBX; // B配列:処理ポインタ
BYTE* ptrBY; // B配列:処理ポインタ
int incA; // A配列:増加幅(nStepV単位)
int incB; // B配列:増加幅(nStepV単位)
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
int HV; // 水平/垂直幅の有効幅
int i; // カウンタ
HV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅最小値算出
HV = HV - ( n + nOffsetH * 2 ); // 水平幅の有効幅算出
h = HV / nStepH; // 水平個数を算出
HV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅最小値算出
HV = HV - ( m + nOffsetV * 2 ); // 垂直幅の有効幅算出
v = HV / nStepV; // 垂直個数を算出
resH = h; // 返値:水平個数
resV = v; // 返値:垂直個数
ptrAY = (BYTE*)pa->adr + nOffsetH + nOffsetV * pa->inc; // A配列:始点処理ポインタ
ptrBY = (BYTE*)pb->adr + nOffsetH + nOffsetV * pb->inc; // 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; ){ // 水平個数分
VectorCorrNM( ptrAX, ptrBX, //
pa->inc, pb->inc, n, m, //
nOffsetH, nOffsetV, //
bufVecX, bufVecY ); //
bufVecX++; // 格納ポインタ次点移動
bufVecY++; // 格納ポインタ次点移動
ptrAX += nStepH; // A配列:次点移動
ptrBX += nStepH; // B配列:次点移動
} //
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(A)関数「VectorCorrImageNM()」の【関数名】
「Vector」は、英単語「vector」、カタカナ語「ベクター・
ベクトル」で、数学的には「方向量」と向きと大きさを意味
「Corr」は、カタカナ語「コア」で物事の中心を意味!
「Image」は、勿論、画像
「NM」は、処理する画像の範囲として「縦×横=N×M
画素」のサイズを意味します!
(B)関数「void VectorCorrImageNM()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「VectorCorrImageNM()」の【仮引数】
void CopyClear::VectorCorrImageNM(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
double* bufVecX, // X方向結果バッファー
double* bufVecY, // Y方向結果バッファー
int n, // n×mのn
int m, // n×mのm
int nOffsetH, // 水平方向オフセット(左右ずれ)
int nOffsetV, // 垂直方向オフセット(上下ずれ)
int nStepH, // 水平方向次点ステップ数
int nStepV, // 垂直方向次点ステップ数
int& resH, // 返値:取得する水平個数
int& resV // 返値:取得する垂直個数
){
「TypeArray* pa,」は、比較対象画像A
「TypeArray* pb,」は、比較対象画像B
「double* bufVecX,」は、ベクターのX座標成分バッファー
「double* bufVecY,」は、ベクターのY座標成分バッファー
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int nOffsetH,」は、水平方向オフセット
「int nOffsetV,」は、垂直方向オフセット
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数
(D)関数「VectorCorrImageNM()」の【アルゴリズム】
){
BYTE* ptrAX; // A配列:処理ポインタ
BYTE* ptrAY; // A配列:処理ポインタ
BYTE* ptrBX; // B配列:処理ポインタ
BYTE* ptrBY; // B配列:処理ポインタ
int incA; // A配列:増加幅(nStepV単位)
int incB; // B配列:増加幅(nStepV単位)
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
int HV; // 水平/垂直幅の有効幅
int i; // カウンタ
HV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅最小値算出
HV = HV - ( n + nOffsetH * 2 ); // 水平幅の有効幅算出
h = HV / nStepH; // 水平個数を算出
HV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅最小値算出
HV = HV - ( m + nOffsetV * 2 ); // 垂直幅の有効幅算出
v = HV / nStepV; // 垂直個数を算出
resH = h; // 返値:水平個数
resV = v; // 返値:垂直個数
ptrAY = (BYTE*)pa->adr + nOffsetH + nOffsetV * pa->inc; // A配列:始点処理ポインタ
ptrBY = (BYTE*)pb->adr + nOffsetH + nOffsetV * pb->inc; // 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; ){ // 水平個数分
VectorCorrNM( ptrAX, ptrBX, //
pa->inc, pb->inc, n, m, //
nOffsetH, nOffsetV, //
bufVecX, bufVecY ); //
bufVecX++; // 格納ポインタ次点移動
bufVecY++; // 格納ポインタ次点移動
ptrAX += nStepH; // A配列:次点移動
ptrBX += nStepH; // B配列:次点移動
} //
} //
}
(D-1)ローカル変数
){
BYTE* ptrAX; // A配列:処理ポインタ
BYTE* ptrAY; // A配列:処理ポインタ
BYTE* ptrBX; // B配列:処理ポインタ
BYTE* ptrBY; // B配列:処理ポインタ
int incA; // A配列:増加幅(nStepV単位)
int incB; // B配列:増加幅(nStepV単位)
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
int HV; // 水平/垂直幅の有効幅
int i; // カウンタ増加幅(nStepV単位)
「BYTE* ptrAX;」は、A画像X座標方向処理ポインタ
「BYTE* ptrAY;」は、A画像Y座標方向処理ポインタ
「BYTE* ptrBX;」は、B画像X座標方向処理ポインタ
「BYTE* ptrBY;」は、B画像Y座標方向処理ポインタ
「int incA;」は、A画像増加幅
「int incB;」は、B画像増加幅
「int h;」は、水平幅(8×8の個数)
「int v;」は、垂直幅(8×8の個数)
「int HV;」は、水平垂直幅算出用の計算途中置き場
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
HV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅最小値算出
HV = HV - ( n + nOffsetH * 2 ); // 水平幅の有効幅算出
h = HV / nStepH; // 水平個数を算出
HV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅最小値算出
HV = HV - ( m + nOffsetV * 2 ); // 垂直幅の有効幅算出
v = HV / nStepV; // 垂直個数を算出
resH = h; // 返値:水平個数
resV = v; // 返値:垂直個数
ptrAY = (BYTE*)pa->adr + nOffsetH + nOffsetV * pa->inc; // A配列:始点処理ポインタ
ptrBY = (BYTE*)pb->adr + nOffsetH + nOffsetV * pb->inc; // 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; ){ // 水平個数分
VectorCorrNM( ptrAX, ptrBX, //
pa->inc, pb->inc, n, m, //
nOffsetH, nOffsetV, //
bufVecX, bufVecY ); //
bufVecX++; // 格納ポインタ次点移動
bufVecY++; // 格納ポインタ次点移動
ptrAX += nStepH; // A配列:次点移動
ptrBX += nStepH; // B配列:次点移動
} //
} //
}
「HV=(pa->h<pb->h)?pa->h:pb->h;HV=HV-(n+nOffsetH2);」
は、水平方向の実効長さ算出し、「h=HV/nStepH;」で
N×M升枠水平方向個数算出!
「HV=(pa->v<pb->v)?pa->v:pb->v;HV=HV-(m+nOffsetV2);」
は、垂直方向の実効長さ算出し、「v=HV/nStepV;」で
N×M升枠垂直方向個数算出!
「resH=h;resV=v;」は、仮引数「int& resH,int& resV」へ
引数辺値を返す!
「ptrAY=(BYTE*)pa->adr+nOffsetH+nOffsetVpa->inc;」は
A画像Y座標方向処理ポインタ処理始点セット!
「ptrBY=(BYTE)pb->adr+nOffsetH+nOffsetVpb->inc;」は
B画像Y座標方向処理ポインタ処理始点セット!
「incA=pa->incnStepV;incB=pb->inc*nStepV;」は、
A画像・B画像のN×M升枠垂直方向増加幅を算出しセット
「for(;--v>=0;ptrAY+=incA,ptrBY+=incB){・・外側ループ
中身・・}」とforループ構文で良くこの解説で紹介する
ループ条件「--v>=0;」で垂直個数繰り返し、中身で垂直
方向の処理を行い、ループ後置「ptrAY+=incA,ptrBY+=incB」
でAB両者の垂直方向処理ポインタを進行!外側ループ本体
「ptrAX=ptrAY;ptrBX=ptrBY;」は、A画像・B画像のX座標
方向処理ポインタ処理始点セット!
「for(i=h;--i>=0;){・・内側ループ中身・・}」は、
ループ初期化「i=h;」でループカウンタに水平方向個数を
セットし、forループ構文で良くこの解説で紹介する
ループ条件「--i>=0;」で水平個数繰り返し、中身は、まず
「VectorCorrNM(ptrAX,ptrBX,pa->inc,pb->inc,n,m,
nOffsetH,nOffsetV,bufVecX,bufVecY);」でサブルーチン
関数「VectorCorrNM()」でN×M升枠に1単位処理し、
「bufVecX++;bufVecY++;」で算出したベクターX座標成分
Y座標成分バッファー格納ポインタを進める!
「ptrAX+=nStepH;ptrBX+=nStepH;」は、AB両者の水平方
向処理ポインタを進行!
(4-14-193)関数「void GetHVVectorCorrImageNM(
TypeArray* pa,
TypeArray* pb,
int n,int m,int nOffsetH,
int nOffsetV,int nStepH,
int nStepV,int& resH,int& resV){・・・}
/********************************************************************************/
/***** n×m画素正規化相関を使用した動線ベクトル算出用升目個数取得 *****/
/********************************************************************************/
void CopyClear::GetHVVectorCorrImageNM(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
int n, // n×mのn
int m, // n×mのm
int nOffsetH, // 水平方向オフセット(左右ずれ)
int nOffsetV, // 垂直方向オフセット(上下ずれ)
int nStepH, // 水平方向次点ステップ数
int nStepV, // 垂直方向次点ステップ数
int& resH, // 返値:取得する水平個数
int& resV // 返値:取得する垂直個数
){
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
int HV; // 水平/垂直幅の有効幅
HV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅最小値算出
HV = HV - ( n + nOffsetH * 2 ); // 水平幅の有効幅算出
h = HV / nStepH; // 水平個数を算出
HV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅最小値算出
HV = HV - ( m + nOffsetV * 2 ); // 垂直幅の有効幅算出
v = HV / nStepV; // 垂直個数を算出
resH = h; // 返値:水平個数
resV = v; // 返値:垂直個数
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(A)関数「GetHVVectorCorrImageNM()」の【関数名】
「Get」は、カタカナ語でもゲット、詰り取得するで
「HV」は、水平・垂直方向の個数を意味します!
「Vector」は、英単語「vector」、カタカナ語「ベクター・
ベクトル」で、数学的には「方向量」と向きと大きさを意味
「Corr」は、カタカナ語「コア」で物事の中心を意味!
「Image」は、勿論、画像
「NM」は、処理する画像の範囲として「縦×横=N×M
画素」のサイズを意味します!
(B)関数「void GetHVVectorCorrImageNM()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「GetHVVectorCorrImageNM()」の【仮引数】
void CopyClear::GetHVVectorCorrImageNM(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
int n, // n×mのn
int m, // n×mのm
int nOffsetH, // 水平方向オフセット(左右ずれ)
int nOffsetV, // 垂直方向オフセット(上下ずれ)
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 nOffsetH,」は、水平方向オフセット
「int nOffsetV,」は、垂直方向オフセット
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「int& resH,」は、水平方向の結果個数
「int& resV」は、垂直方向の結果個数
(D)関数「GetHVVectorCorrImageNM()」の【アルゴリズム】
){
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
int HV; // 水平/垂直幅の有効幅
HV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅最小値算出
HV = HV - ( n + nOffsetH * 2 ); // 水平幅の有効幅算出
h = HV / nStepH; // 水平個数を算出
HV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅最小値算出
HV = HV - ( m + nOffsetV * 2 ); // 垂直幅の有効幅算出
v = HV / nStepV; // 垂直個数を算出
resH = h; // 返値:水平個数
resV = v; // 返値:垂直個数
}
(D-1)ローカル変数
){
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
int HV; // 水平/垂直幅の有効幅
「int h;」は、水平幅(8×8の個数)
「int v;」は、垂直幅(8×8の個数)
「int HV;」は、水平垂直幅算出用の計算途中置き場
(D-2)アルゴリズムコード
HV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅最小値算出
HV = HV - ( n + nOffsetH * 2 ); // 水平幅の有効幅算出
h = HV / nStepH; // 水平個数を算出
HV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅最小値算出
HV = HV - ( m + nOffsetV * 2 ); // 垂直幅の有効幅算出
v = HV / nStepV; // 垂直個数を算出
resH = h; // 返値:水平個数
resV = v; // 返値:垂直個数
}
「HV=(pa->h<pb->h)?pa->h:pb->h;
HV=HV-(n+nOffsetH2);」
は、水平方向の実効長さ算出し、「h=HV/nStepH;」で
N×M升枠水平方向個数算出!
「HV=(pa->v<pb->v)?pa->v:pb->v;
HV=HV-(m+nOffsetV2);」
は、垂直方向の実効長さ算出し、「v=HV/nStepV;」で
N×M升枠垂直方向個数算出!
「resH=h;resV=v;」は、仮引数「int& resH,int& resV」へ
引数辺値を返す!
(4-14-194)関数「double AverageImageNMXY(
TypeArray* pa,TypeXY* xy,
int offX,int offY){・・・}
/************************************************************************************/
/***** n×m画素画像平均適応:個別座標指定 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
double CopyClear::AverageImageNMXY(
TypeArray* pa, // A配列
int n, // n×mのn
int m, // n×mのm
int x, // X座標オフセット
int y // Y座標オフセット
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
ptrA = (BYTE*)pa->adr; // A配列:処理ポインタ
incA = pa->inc; // A配列:増加幅
if( x >= 0 && x < minH && y >= 0 && y < minV ){ // 有効範囲内ならば
return( AveNM( ptrA + x + y * incA, incA, n, m ) ); // n×m画素平均算出
}else{ // 範囲外ならば
return( 0.0 ); // 0.0を返す
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「AverageImageNMXY()」の【関数名】
「Average」は、英単語「Average」で「平均値」を意味
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の平均値算出関数です!
この多重定義(オーバーロード)関数は、
仮引数「TypeXY* xy,」で複数指定します!
(B)関数「double AverageImageNMXY()」の【返値】
関数返値として算出した平均値を返す関数です!
(C)関数「AverageImageNMXY()」の【仮引数】
double CopyClear::AverageImageNMXY(
TypeArray* pa, // A配列
int n, // n×mのn
int m, // n×mのm
int x, // X座標オフセット
int y // Y座標オフセット
){
「TypeArray* pa,」は、画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int x」は、X座標
「int y」は、Y座標
(D)関数「AverageImageNMXY()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
ptrA = (BYTE*)pa->adr; // A配列:処理ポインタ
incA = pa->inc; // A配列:増加幅
if( x >= 0 && x < minH && y >= 0 && y < minV ){ // 有効範囲内ならば
return( AveNM( ptrA + x + y * incA, incA, n, m ) ); // n×m画素平均算出
}else{ // 範囲外ならば
return( 0.0 ); // 0.0を返す
} //
}
(D-1)ローカル変数
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
「BYTE* ptrA;」は、画素単位処理ポインタ
「int incA;」は、増加幅★備考★「int inc;」の方が相応
しいと思われるでしょう、この記載に成ったのは、単に
コピペで他の部分から流用したからです!同じ様に処理ポイ
ンタも「BYTE* ptr;」の方が相応しいが、同じ理由から、
この変数名に成ったのです!
「int minH;」は、水平幅の有効(N×M升枠を考慮)幅
「int minV;」は、垂直幅の有効(N×M升枠を考慮)幅
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
ptrA = (BYTE*)pa->adr; // A配列:処理ポインタ
incA = pa->inc; // A配列:増加幅
if( x >= 0 && x < minH && y >= 0 && y < minV ){ // 有効範囲内ならば
return( AveNM( ptrA + x + y * incA, incA, n, m ) ); // n×m画素平均算出
}else{ // 範囲外ならば
return( 0.0 ); // 0.0を返す
} //
}
「minH=pa->h-n;」は、水平有効幅算出
「minV=pa->v-m;」は、垂直有効幅算出
「ptrA=(BYTE*)pa->adr;」は、処理ポインタのセット
「incA=pa->inc;」は、増加幅のセット
「if(x>=0&&x<minH&&y>=0&&y<minV){・・成立・・」
は、if条件「x>=0&&x<minH&&y>=0&&y<minV」で
XY座標が、画像内に有効座標が有る場合で成立の場合は、
「return(AveNM(ptrA+x+y*incA,incA,n,m));」と
サブルーチン関数「AveNM()」でN×M升枠の平均値算出し
関数辺値として値を返す!
「else{return(0.0);}」は、不成立時は、「0.0」を関数の
関数辺値として値を返す!
(4-14-195)関数「void AverageImageNMXY(
TypeArray* pa,TypeXY* xy,
BYTE* buf,int size,int offX=0,
int offY=0){・・・}
/************************************************************************************/
/***** n×m画素画像平均適応 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
void CopyClear::AverageImageNMXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
BYTE* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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)AveNM( ptrA + x + y * incA, incA, n, m ); // n×m画素平均算出
}else{ // 範囲外ならば
*buf = 0; // 0をセット
} //
} //
}
☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「AverageImageNMXY()」の【関数名】
「Average」は、英単語「Average」で「平均値」を意味
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の平均値算出関数です!
この多重定義(オーバーロード)関数は、
仮引数「TypeXY* xy,」で複数指定します!
(B)関数「void AverageImageNMXY()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「AverageImageNMXY()」の【仮引数】
void CopyClear::AverageImageNMXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
BYTE* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
int size, // バッファーサイズ
int offX, // X座標オフセット(省略時0)
int offY // Y座標オフセット(省略時0)
){
「TypeArray* pa,」は、画像情報
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「BYTE* buf,」は、結果格納バッファー!
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
(D)関数「AverageImageNMXY()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
int x; // X座標値
int y; // Y座標値
int i; // カウンタ
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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)AveNM( ptrA + x + y * incA, incA, n, m ); // n×m画素平均算出
}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;」は、水平幅の有効(N×M升枠を考慮)幅
「int minV;」は、垂直幅の有効(N×M升枠を考慮)幅
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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)AveNM( ptrA + x + y * incA, incA, n, m ); // n×m画素平均算出
}else{ // 範囲外ならば
*buf = 0; // 0をセット
} //
} //
}
「minH=pa->h-n;」は、水平有効幅算出
「minV=pa->v-m;」は、垂直有効幅算出
「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)AveNM(ptrA+x+yincA,incA,n,m);}」は、
if条件「x>=0&&x<minH&&y>=0&&y<minV」で取り出したXY座標が、有効な時「buf=(int)AveNM(
ptrA+x+yincA,incA,n,m);」とサブルーチン関数「
AveNM(ptrA+x+y*incA,incA,n,m);」で平均値算出し、
「*buf=(int)・・・」は、整数型に型変換(小数点以下
切り捨て)し結果バッファに格納!
「else{*buf=0;}」は、XY座標が範囲外の場合で
「*buf=0;」とバッファに「0」を格納!
(4-14-196)関数「void AverageImageNMXY(
TypeArray* pa,TypeXY* xy,
double* buf,int size,int offX=0,
int offY=0){・・・}
/************************************************************************************/
/***** n×m画素画像平均適応 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
void CopyClear::AverageImageNMXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = AveNM( ptrA + x + y * incA, incA, n, m ); // n×m画素平均算出
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
} //
} //
}
☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「AverageImageNMXY()」の【関数名】
「Average」は、英単語「Average」で「平均値」を意味
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の平均値算出関数です!
この多重定義(オーバーロード)関数は、
仮引数「TypeXY* xy,」で複数指定します!
(B)関数「void AverageImageNMXY()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「AverageImageNMXY()」の【仮引数】
void CopyClear::AverageImageNMXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
int size, // バッファーサイズ
int offX, // X座標オフセット(省略時0)
int offY // Y座標オフセット(省略時0)
){
「TypeArray* pa,」は、画像情報
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
(D)関数「AverageImageNMXY()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
int x; // X座標値
int y; // Y座標値
int i; // カウンタ
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = AveNM( ptrA + x + y * incA, incA, n, m ); // n×m画素平均算出
}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;」は、水平幅の有効(N×M升枠を考慮)幅
「int minV;」は、垂直幅の有効(N×M升枠を考慮)幅
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = AveNM( ptrA + x + y * incA, incA, n, m ); // n×m画素平均算出
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
} //
} //
}
「minH=pa->h-n;」は、水平有効幅算出
「minV=pa->v-m;」は、垂直有効幅算出
「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=AveNM(ptrA+x+yincA,incA,n,m);}」は、
if条件「x>=0&&x<minH&&y>=0&&y<minV」で取り出したXY座標が、有効な時「buf=(int)AveNM(
ptrA+x+yincA,incA,n,m);」とサブルーチン関数「
AveNM(ptrA+x+y*incA,incA,n,m);」で平均値算出し、結果
バッファに格納!
「else{*buf=0.0;}」は、XY座標が範囲外の場合で
「*buf=0.0;」とバッファに「0.0」を格納!
(4-14-197)関数「double CorrImageNMXY(
TypeArray* pa,TypeArray* pb,
int n,int m,int x,int y){・・・}」
/************************************************************************************/
/***** n×m画素正規化相関画像適応:個別座標指定 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
double CopyClear::CorrImageNMXY(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
int n, // n×mのn
int m, // n×mのm
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 ) - n; // 水平幅の最小値算出
minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - m; // 垂直幅の最小値算出
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( CorrNM( ptrA + x + y * incA, // n×m画素の正規相関を
ptrB + x + y * incB, incA, incB, n, m ) ); // 演算
}else{ // 範囲外ならば
return( 0.0 ); // 0.0を返す
} //
}
☆備考☆この関数はファイル「CopyClear400.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMXY()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
(B)関数「double CorrImageNMXY()」の【返値】
関数返値として算出し相関値(一致率)を返す関数です!
(C)関数「CorrImageNMXY()」の【仮引数】
double CopyClear::CorrImageNMXY(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
int n, // n×mのn
int m, // n×mのm
int x, // X座標オフセット
int y // Y座標オフセット
){
「TypeArray* pa,」は、比較対象画像A
「TypeArray* pb,」は、比較対象画像B
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int x」は、X座標
「int y」は、Y座標
(D)関数「CorrImageNMXY()」の【アルゴリズム】
){
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 ) - n; // 水平幅の最小値算出
minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - m; // 垂直幅の最小値算出
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( CorrNM( ptrA + x + y * incA, // n×m画素の正規相関を
ptrB + x + y * incB, incA, incB, n, m ) ); // 演算
}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;」は、有効水平幅(N×M升枠考慮)
「int minV;」は、有効垂直幅(N×M升枠考慮)
(D-2)アルゴリズムコード
minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - n; // 水平幅の最小値算出
minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - m; // 垂直幅の最小値算出
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( CorrNM( ptrA + x + y * incA, // n×m画素の正規相関を
ptrB + x + y * incB, incA, incB, n, m ) ); // 演算
}else{ // 範囲外ならば
return( 0.0 ); // 0.0を返す
} //
}
「minH=((pa->h<pb->h)?pa->h:pb->h)-n;」は、水平画素数
の有効(最小でN×M升枠考慮)サイズ算出!
「minV=((pa->v<pb->v)?pa->v:pb->v)-m;」は、垂直画素数の有効(最小でN×M升枠考慮)サイズ算出!
「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(CorrNM(ptrA+x+yincA,ptrB+x+yincB,incA,incB,
n,m));」とサブルーチン関数「CorrNM()」で処理し関数
終了!
不成立「else{return(0.0);}」で関数辺値として「0.0」を
返し関数終了!
(4-14-198)関数「void CorrImageNMXY(
TypeArray* pa,
TypeArray* pb,TypeXY* xy,
double* buf,int n,int m,int size,
int offX,int offY){・・・}」
/************************************************************************************/
/***** n×m画素正規化相関画像適応 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
void CopyClear::CorrImageNMXY(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
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 ) - n; // 水平幅の最小値算出
minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - m; // 垂直幅の最小値算出
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 = CorrNM( ptrA + x + y * incA, // n×m画素の正規相関を
ptrB + x + y * incB, incA, incB, n, m ); // 演算
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
} //
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMXY()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
(B)関数「void CorrImageNMXY()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「CorrImageNMXY()」の【仮引数】
void CopyClear::CorrImageNMXY(
TypeArray* pa, // A配列
TypeArray* pb, // B配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
int size, // バッファーサイズ
int offX, // X座標オフセット(省略時0)
int offY // Y座標オフセット(省略時0)
){
「TypeArray* pa,」は、比較対象画像A
「TypeArray* pb,」は、比較対象画像B
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
(D)関数「CorrImageNMXY()」の【アルゴリズム】
){
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 ) - n; // 水平幅の最小値算出
minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - m; // 垂直幅の最小値算出
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 = CorrNM( ptrA + x + y * incA, // n×m画素の正規相関を
ptrB + x + y * incB, incA, incB, n, m ); // 演算
}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;」は、水平幅の有効(N×M升枠を考慮)幅
「int minV;」は、垂直幅の有効(N×M升枠を考慮)幅
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minH = ( ( pa->h < pb->h ) ? pa->h : pb->h ) - n; // 水平幅の最小値算出
minV = ( ( pa->v < pb->v ) ? pa->v : pb->v ) - m; // 垂直幅の最小値算出
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 = CorrNM( ptrA + x + y * incA, // n×m画素の正規相関を
ptrB + x + y * incB, incA, incB, n, m ); // 演算
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
} //
} //
}
「minH=pa->h-n;」は、水平有効幅算出
「minV=pa->v-m;」は、垂直有効幅算出
「ptrA=(BYTE*)pa->adr;ptrB=(BYTE*)pb->adr;」は、処理
ポインタのセット!
「incA=pa->inc;incB=pb->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=CorrNM(ptrA+x+yincA,ptrB+x+yincB,incA,incB,
n,m);}」は、if条件「x>=0&&x<minH&&y>=0&&y<minV」で
取り出したXY座標が、有効な時「buf=(int)CorrNM(
ptrA+x+yincA,ptrB+x+yincB,incA,incB,n,m);」とサブ
ルーチン関数「CorrNM(ptrA+x+yincA,ptrB+x+yincB,
incA,incB,n,m);」で相関値算出し、結果バッファに格納!
「else{*buf=0.0;}」は、XY座標が範囲外の場合で
「*buf=0.0;」とバッファに「0.0」を格納!
(4-14-199)関数「double CorrImageNMMyselfXY(
TypeArray* pa,int n,int m,int x,
int y){・・・}」
/************************************************************************************/
/***** n×m画素自己相関画像適応:個別座標指定 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
double CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
int n, // n×mのn
int m, // n×mのm
int x, // X座標オフセット
int y // Y座標オフセット
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
ptrA = (BYTE*)pa->adr; // A配列:処理ポインタ
incA = pa->inc; // A配列:増加幅
if( x >= 0 && x < minH && y >= 0 && y < minV ){ // 有効範囲内ならば
return( CorrNMMyself( ptrA + x + y * incA, incA, n, m ) ); // n×m画素自己相関算出
}else{ // 範囲外ならば
return( 0.0 ); // 0.0を返す
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMMyselfXY()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
(B)関数「double CorrImageNMMyselfXY()」の【返値】
関数返値として算出し相関値(一致率)を返す関数です!
★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
(C)関数「CorrImageNMMyselfXY()」の【仮引数】
double CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
int n, // n×mのn
int m, // n×mのm
int x, // X座標オフセット
int y // Y座標オフセット
){
「TypeArray* pa,」は、画像情報
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int x」は、X座標
「int y」は、Y座標
(D)関数「CorrImageNMMyselfXY()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
ptrA = (BYTE*)pa->adr; // A配列:処理ポインタ
incA = pa->inc; // A配列:増加幅
if( x >= 0 && x < minH && y >= 0 && y < minV ){ // 有効範囲内ならば
return( CorrNMMyself( ptrA + x + y * incA, incA, n, m ) ); // n×m画素自己相関算出
}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;」は、有効水平幅(N×M升枠考慮)
「int minV;」は、有効垂直幅(N×M升枠考慮)
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
ptrA = (BYTE*)pa->adr; // A配列:処理ポインタ
incA = pa->inc; // A配列:増加幅
if( x >= 0 && x < minH && y >= 0 && y < minV ){ // 有効範囲内ならば
return( CorrNMMyself( ptrA + x + y * incA, incA, n, m ) ); // n×m画素自己相関算出
}else{ // 範囲外ならば
return( 0.0 ); // 0.0を返す
} //
}
「minH=pa->h-n;」は、水平画素数
の有効(最小でN×M升枠考慮)サイズ算出!
「minV=pa->v-m;」は、垂直画素数の
有効(最小でN×M升枠考慮)サイズ算出!
「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(CorrNMMyself(
ptrA+x+yincA,incA,n,m));」でサブルーチン関数
「CorrNMMyself()」で処理、★備考★実引数
「ptrA+x+yincA,,,」でXY座標がポインタ演算で画像
ピンポイントで算出している事に注意!そしてif
不成立「else{return(0.0);}」は、「0.0」を関数辺値とし
返し関数終了!
(4-14-200)関数「void CorrImageNMMyselfXY(
TypeArray* pa,TypeXY* xy,
double* buf,int n,int m,int size,
int offX=0,int offY=0){・・・}」
/************************************************************************************/
/***** n×m画素自己相関画像適応 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, n, m ); // n×m画素自己相関算出
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
} //
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMMyselfXY()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
(B)関数「void CorrImageNMMyselfXY()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「CorrImageNMMyselfXY()」の【仮引数】
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
int n, // n×mのn
int m, // n×mのm
int size, // バッファーサイズ
int offX, // X座標オフセット(省略時0)
int offY // Y座標オフセット(省略時0)
){
「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
(D)関数「CorrImageNMMyselfXY()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
int x; // X座標値
int y; // Y座標値
int i; // カウンタ
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, n, m ); // n×m画素自己相関算出
}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;」は、有効水平幅(N×M升枠考慮)
「int minV;」は、有効垂直幅(N×M升枠考慮)
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, n, m ); // n×m画素自己相関算出
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
} //
} //
}
「minH=pa->h-n;」は、水平画素数の有効(最小でN×M升
枠考慮)サイズ算出!
「minV=pa->v-m;」は、垂直画素数の有効(最小でN×M升
枠考慮)サイズ算出!
「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=CorrNMMyself(ptrA+x+yincA,incA,n,m);」でサブ
ルーチン関数「CorrNMMyself()」で処理しバッファー格納!
そしてif不成立「else{*buf=0.0;}」は「0.0」を
バッファー格納!
(4-14-201)関数「void CorrImageNMMyselfXY(
TypeArray* pa,TypeXY* xy,
double* buf,BYTE* bufAve,int n,
int m,int size,int offX=0,
int offY=0){・・・}」
/************************************************************************************/
/***** n×m画素自己相関画像適応+画像平均 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
BYTE* bufAve, // 結果バッファー:平均
int n, // n×mのn
int m, // n×mのm
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, // n×m画素自己相関算出
n, m, ave ); // (平均も算出)
*bufAve = ave; // 平均値を格納
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
*bufAve = 0; // 0をセット
} //
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMMyselfXY()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
(B)関数「void CorrImageNMMyselfXY()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「CorrImageNMMyselfXY()」の【仮引数】
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
double* buf, // 結果バッファー
BYTE* bufAve, // 結果バッファー:平均
int n, // n×mのn
int m, // n×mのm
int size, // バッファーサイズ
int offX, // X座標オフセット(省略時0)
int offY // Y座標オフセット(省略時0)
){
「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果(分散値)格納バッファー!
「BYTE* bufAve,」は、結果(平均値)格納バッファー!
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
★備考★「BYTE* bufAve,」が有る事で多重定義(オーバー
ロード)関数の識別が出来ます!分散値だけで無く平均値
も必要な場合を考えた関数ですが、関数名を新規に考えるの
が面倒に成った(適切な名前より得られる引数追加の方が
簡単)のでコノ状態に成りました!平均値を使わない場合は
引数を記載しなければ良いとの考えです!多重定義の使い方
としてコレも有りなのだ!
(D)関数「CorrImageNMMyselfXY()」の【アルゴリズム】
){
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, // n×m画素自己相関算出
n, m, 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;」は、有効水平幅(N×M升枠考慮)
「int minV;」は、有効垂直幅(N×M升枠考慮)
「int ave;」は、個別の平均値
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, // n×m画素自己相関算出
n, m, ave ); // (平均も算出)
*bufAve = ave; // 平均値を格納
}else{ // 範囲外ならば
*buf = 0.0; // 0.0をセット
*bufAve = 0; // 0をセット
} //
} //
}
「minH=pa->h-n;」は、水平画素数の有効(最小でN×M升
枠考慮)サイズ算出!
「minV=pa->v-m;」は、垂直画素数の有効(最小でN×M升
枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「for(i=0;i<size;i++,xy++,buf++,bufAve++){・・ループ
本体・・}」は、ループ初期値「i=0;」ループ条件
「i<size;」ループ終了後処理「i++,xy++,buf++,bufAve++」
と教科書的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=CorrNMMyself(ptrA+x+yincA,incA,n,m,ave);
*bufAve=ave;」でサブルーチン関数「CorrNMMyself()」で
処理しバッファー格納!更に★注意★サブルーチン関数
「CorrNMMyself(・・ave・・)」と多重定義(オーバーロー
ド)関数として「ave」を指定して平均値算出と指定し無い
関数が存在し、ココでは指定する関数を使用、
「*bufAve=ave;」は、平均値格納バッファー平均値を格納!
そしてif不成立「else{*buf=0.0;*bufAve=0;}」は、
「0.0」を分散値、「0」を平均値とし引数辺値とし返し
関数終了!
(4-14-202)関数「void CorrImageNMMyselfXY(
TypeArray* pa,TypeXY* xy,
int* buf,int n,int m,int size,
int offX=0,int offY=0){・・・}」
/************************************************************************************/
/***** n×m画素自己相関画像適応 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
int* buf, // 結果バッファー:整数値
int n, // n×mのn
int m, // n×mのm
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, n, m ); // n×m画素自己相関算出
}else{ // 範囲外ならば
*buf = 0; // 0をセット
} //
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMMyselfXY()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
(B)関数「void CorrImageNMMyselfXY()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「CorrImageNMMyselfXY()」の【仮引数】
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
int* buf, // 結果バッファー:整数値
int n, // n×mのn
int m, // n×mのm
int size, // バッファーサイズ
int offX, // X座標オフセット(省略時0)
int offY // Y座標オフセット(省略時0)
){
「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「int* buf,」は、結果格納バッファー!★備考★ここが、
多重定義(オーバーロード)で格納する型が違う事に留意
して下さい!
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
(D)関数「CorrImageNMMyselfXY()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
int incA; // A配列:増加幅
int minH; // Aの有効水平幅
int minV; // Aの有効垂直幅
int x; // X座標値
int y; // Y座標値
int i; // カウンタ
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, n, m ); // n×m画素自己相関算出
}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;」は、有効水平幅(N×M升枠考慮)
「int minV;」は、有効垂直幅(N×M升枠考慮)
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, n, m ); // n×m画素自己相関算出
}else{ // 範囲外ならば
*buf = 0; // 0をセット
} //
} //
}
「minH=pa->h-n;」は、水平画素数
の有効(最小でN×M升枠考慮)サイズ算出!
「minV=pa->v-m;」は、垂直画素数の
有効(最小でN×M升枠考慮)サイズ算出!
「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=CorrNMMyself(
ptrA+x+yincA,incA,n,m);」でサブルーチン関数
「CorrNMMyself()」で処理しバッファー格納
そしてif不成立「else{*buf=0;}」は、「0」を分散値
とし返し関数終了!
(4-14-203)関数「void CorrImageNMMyselfXY(
TypeArray* pa,TypeXY* xy,
int* buf,BYTE* bufAve,int n,
int m,int size,int offX=0,int offY=0){・・・}」
/************************************************************************************/
/***** n×m画素自己相関画像適応+画像平均 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/************************************************************************************/
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
int* buf, // 結果バッファー:整数値
BYTE* bufAve, // 結果バッファー:平均
int n, // n×mのn
int m, // n×mのm
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, // n×m画素自己相関算出
n, m, ave ); // (平均も算出)
*bufAve = ave; // 平均値を格納
}else{ // 範囲外ならば
*buf = 0; // 0をセット
*bufAve = 0; // 0をセット
} //
} //
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMMyselfXY()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
(B)関数「void CorrImageNMMyselfXY()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「CorrImageNMMyselfXY()」の【仮引数】
void CopyClear::CorrImageNMMyselfXY(
TypeArray* pa, // A配列
TypeXY* xy, // 探索座標列
int* buf, // 結果バッファー:整数値
BYTE* bufAve, // 結果バッファー:平均
int n, // n×mのn
int m, // n×mのm
int size, // バッファーサイズ
int offX, // X座標オフセット(省略時0)
int offY // Y座標オフセット(省略時0)
){
「TypeArray* pa,」は、比較対象画像A
「TypeXY* xy,」は、XY座標バッファーで複数指定!
「int* buf,」は、結果格納バッファー!★備考★ここが、
多重定義(オーバーロード)で格納する型が違う事に留意
して下さい!
「BYTE* bufAve,」は、結果(平均値)格納バッファー!
「int n,」は、N×MのN指定!
「int m,」は、N×MのM指定!
「int size,」は、XY座標バッファー及び結果バッファー
のサイズです!
「int offX,」は、画像始点からのオフセット座標のX座標
「int offY 」は、画像始点からのオフセット座標のY座標
★備考★「BYTE* bufAve,」が有る事で多重定義(オーバー
ロード)関数の識別が出来ます!分散値だけで無く平均値
も必要な場合を考えた関数ですが、関数名を新規に考えるの
が面倒に成った(適切な名前より得られる引数追加の方が
簡単)のでコノ状態に成りました!平均値を使わない場合は
引数を記載しなければ良いとの考えです!多重定義の使い方
としてコレも有りなのだ!
(D)関数「CorrImageNMMyselfXY()」の【アルゴリズム】
){
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 - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, // n×m画素自己相関算出
n, m, 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;」は、有効水平幅(N×M升枠考慮)
「int minV;」は、有効垂直幅(N×M升枠考慮)
「int ave;」は、個別の平均値
「int x;」は、個別位置のX座標
「int y;」は、個別位置のY座標
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minH = pa->h - n; // 水平幅の有効範囲算出
minV = pa->v - m; // 垂直幅の有効範囲算出
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 = CorrNMMyself( ptrA + x + y * incA, incA, // n×m画素自己相関算出
n, m, ave ); // (平均も算出)
*bufAve = ave; // 平均値を格納
}else{ // 範囲外ならば
*buf = 0; // 0をセット
*bufAve = 0; // 0をセット
} //
} //
}
「minH=pa->h-n;」は、水平画素数
の有効(最小でN×M升枠考慮)サイズ算出!
「minV=pa->v-m;」は、垂直画素数の
有効(最小でN×M升枠考慮)サイズ算出!
「ptrA=(BYTE*)pa->adr;」は、A画像用始点処理ポインタ
をセット!
「incA=pa->inc;」は、A画像増加幅をセット!
「for(i=0;i<size;i++,xy++,buf++,bufAve++){・・ループ
本体・・}」は、ループ初期値「i=0;」ループ条件
「i<size;」ループ終了後処理「i++,xy++,buf++,bufAve++」
と教科書的for構文でのアップカウンタ「i=0;」を
条件「i<size;」増分「i++,」と「0からsize未満」まで
繰り返し同時に「xy++,buf++,bufAve++」とバッファを示す
ポインタ増加でループ本体で
「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=CorrNMMyself(ptrA+x+yincA,
incA,ave);bufAve=ave;」でサブルーチン関数
「CorrNMMyself()」で処理しバッファー格納★備考★実引数
「ptrA+x+yincA,」でXY座標がポインタ演算で画像ピン
ポイントで算出している事に注意!更に★注意★サブルー
チン関数「CorrNMMyself(・・ave・・)」と多重定義(オー
バーロード)関数として「ave」を指定して平均値算出と
指定し無い関数が存在し、ココでは指定する関数を使用、
「*bufAve=ave;」は、平均値格納バッファー平均値を
格納!
そしてif不成立「else{*buf=0;*bufAve=0;}」は、
「0」を分散値、「0」を平均値としバッファー格納!
(4-14-204)関数「void CorrImageNMMyselfExtend(
TypeArray* image,
TypeXY* xy,double* buf,int n,
int m,int size,int offX=0,int offY=0){・・・}」
/************************************************************************************/
/***** n×m画素自己相関画像適応:拡張 *****/
/***** ☆n×mの基本単位毎に指定された場所の画像を演算しバッファーに格納☆*****/
/***** (1)概要でステップ毎に演算 *****/
/***** (2)詳細で座標に従い細かく演算 *****/
/************************************************************************************/
int CopyClear::CorrImageNMMyselfExtend(
TypeArray* image, // 画像
TypeXY* bufXY, // 結果座標バッファー
double* buf, // 結果バッファー
int nN, // n×mのn
int nM, // n×mのm
int maxN, // 最大結果数
int nStepH, // 水平方向次点ステップ数
int nStepV, // 垂直方向次点ステップ数
double tA, // 最小概要しきい値
double tB // 最大概要しきい値
){
int* bufL; // 結果バッファー:概要
int nH; // 水平方向個数
int nV; // 垂直方向個数
int nHV; // 個数(nH*nV)
int n; // 計測個数
GetHVCorrImageNMMyself( image, nN, nM, nStepH, nStepV, nH, nV ); // 自己相関升目個数
nHV = nH * nV; // 個数(nH*nV)算出
bufL = (int*)malloc( sizeof(int) * nHV ); // 座標バッファーをメモリ確保
if( bufL == 0 ){ // 確保失敗時
return( STI_MEM ); // 左記を返す
} //
CorrImageNMMyself( image, bufL, nN, nM, nStepH, nStepV, nH, nV ); // 自己相関作成
tA = tA * tA * nN * nM; // 偏差値→判定値
tB = tB * tB * nN * nM; // 偏差値→判定値
n = makeCorrImageMyselfExtend( image, bufXY, bufL, maxN, // 座標作成
nStepH, nStepV, tA, tB, nN / 2, nM / 2 ); //
CorrImageNMMyselfXY( image, bufXY, buf, nN, nM, n, // 詳細自己相関作成
-nN / 2, -nM / 2 ); //
free( bufL ); // メモリ解放
return( n ); // 有効個数を返す
}
☆備考☆この関数はファイル「CopyClear410.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!
(A)関数「CorrImageNMMyselfExtend()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を算出しますのでモット大きな値に成ります!
「Image」は、勿論、画像です!
「NM」は、処理する画像の範囲として「縦×横=N×Mの
サイズを意味します!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* image,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
「XY」は、XY座標を意味します!詰り、画像の中でXY
座標を指定した場所のN×M升枠の相関値算出関数です!
「Extend」は、英単語「extend」、「拡張」を意味します!
詰り、前記した関数「CorrImageNMMyself()」の機能を拡張
した関数です!
(B)関数「void CorrImageNMMyselfExtend()」の【返値】
計測した有効個数を返す関数です!
(C)関数「CorrImageNMMyselfExtend()」の【仮引数】
int CopyClear::CorrImageNMMyselfExtend(
TypeArray* image, // 画像
TypeXY* bufXY, // 結果座標バッファー
double* buf, // 結果バッファー
int nN, // n×mのn
int nM, // n×mのm
int maxN, // 最大結果数
int nStepH, // 水平方向次点ステップ数
int nStepV, // 垂直方向次点ステップ数
double tA, // 最小概要しきい値
double tB // 最大概要しきい値
){
「TypeArray* image,」は、比較対象画像A
「TypeXY* bufXY,」は、XY座標バッファーで複数指定!
「double* buf,」は、結果格納バッファー!
「int nN,」は、N×MのN指定!
「int nM,」は、N×MのM指定!
「int maxN,」は、処理するN×M升枠の個数最大の数制限
「int nStepH,」は、比較N×M升枠移動水平方向ステップ
「int nStepV,」は、比較N×M升枠移動垂直方向ステップ
「double tA,」は、N×M升枠の相関値(分散値)下限で
「double tB」は、上限値で算出した相関値(分散値)が
下限から上限の間に有る様に調整する範囲です!
(D)関数「CorrImageNMMyselfExtend()」の【アルゴリズム】
){
int* bufL; // 結果バッファー:概要
int nH; // 水平方向個数
int nV; // 垂直方向個数
int nHV; // 個数(nH*nV)
int n; // 計測個数
GetHVCorrImageNMMyself( image, nN, nM, nStepH, nStepV, nH, nV ); // 自己相関升目個数
nHV = nH * nV; // 個数(nH*nV)算出
bufL = (int*)malloc( sizeof(int) * nHV ); // 座標バッファーをメモリ確保
if( bufL == 0 ){ // 確保失敗時
return( STI_MEM ); // 左記を返す
} //
CorrImageNMMyself( image, bufL, nN, nM, nStepH, nStepV, nH, nV ); // 自己相関作成
tA = tA * tA * nN * nM; // 偏差値→判定値
tB = tB * tB * nN * nM; // 偏差値→判定値
n = makeCorrImageMyselfExtend( image, bufXY, bufL, maxN, // 座標作成
nStepH, nStepV, tA, tB, nN / 2, nM / 2 ); //
CorrImageNMMyselfXY( image, bufXY, buf, nN, nM, n, // 詳細自己相関作成
-nN / 2, -nM / 2 ); //
free( bufL ); // メモリ解放
return( n ); // 有効個数を返す
}
(D-1)ローカル変数
){
int* bufL; // 結果バッファー:概要
int nH; // 水平方向個数
int nV; // 垂直方向個数
int nHV; // 個数(nH*nV)
int n; // 計測個数
「int* bufL;」は、N×M升枠の相関値(分散値)内部算出
バッファー!
「int nH;」は、N×M升枠の水平方向個数
「int nV;」は、N×M升枠の垂直方向個数
「int nHV;」は、個数≪nHnV≫
「int n;」は、計測個数
(D-2)アルゴリズムコード
GetHVCorrImageNMMyself( image, nN, nM, nStepH, nStepV, nH, nV ); // 自己相関升目個数
nHV = nH * nV; // 個数(nH*nV)算出
bufL = (int*)malloc( sizeof(int) * nHV ); // 座標バッファーをメモリ確保
if( bufL == 0 ){ // 確保失敗時
return( STI_MEM ); // 左記を返す
} //
CorrImageNMMyself( image, bufL, nN, nM, nStepH, nStepV, nH, nV ); // 自己相関作成
tA = tA * tA * nN * nM; // 偏差値→判定値
tB = tB * tB * nN * nM; // 偏差値→判定値
n = makeCorrImageMyselfExtend( image, bufXY, bufL, maxN, // 座標作成
nStepH, nStepV, tA, tB, nN / 2, nM / 2 ); //
CorrImageNMMyselfXY( image, bufXY, buf, nN, nM, n, // 詳細自己相関作成
-nN / 2, -nM / 2 ); //
free( bufL ); // メモリ解放
return( n ); // 有効個数を返す
}
「GetHVCorrImageNMMyself(image,nN,nM,nStepH,nStepV,
nH,nV);」は、ローカル変数「int nH;int nV;」に処理する
N×M升枠を算出し、「nHV=nHnV;」全体個数を算出後、
「bufL=(int*)malloc(sizeof(int)nHV);」は、N×M升枠
の自己相関値(分散値)内部算出用バッファーメモリ確保
「if(bufL==0){return(STI_MEM);}」は、バッファーメモリ
確保に失敗したらエラーコード「STI_MEM」を辺値とし返し
関数終了!
「CorrImageNMMyself(image,bufL,nN,nM,nStepH,nStepV,
nH,nV);」は、一旦、サブルーチン関数
「CorrImageNMMyself()」で自己相関を算出し、
「tA=tAtAnNnM;tB=tBtBnN*nM;」は、仮引数
「double tA,double tB」が「0.0から1.0」と分かり易い
パラメータにした物を内部で使用する自己相関値との比較に
相応しい値に成る様に変換!
「n=makeCorrImageMyselfExtend(image,bufXY,bufL,maxN,
nStepH,nStepV,tA,tB,nN/2,nM/2);」は、サブルーチン関数
「makeCorrImageMyselfExtend()」で詳細に検査するXY
座標を作成!
「CorrImageNMMyselfXY(image,bufXY,buf,nN,nM,n,
-nN/2,-nM/2);」は、サブルーチン関数
「CorrImageNMMyselfXY()」で詳細の場所で自己相関算出!
「free(bufL);return(n);」は、後始末「確保メモリ解放」
し、算出個数を関数辺値とし返し関数終了!
(4-14-205)関数「void CorrImageNMLarge(
TypeArray* pa,
TypeArray* pb,double* buf,
int n,int m,int nStepH,
int nStepV,int& resH,int& resV){・・・}」
/************************************************************************/
/***** n×m画素正規化相関画像適応 *****/
/***** ☆n×mの基本単位毎に画像全体を演算しバッファーに格納☆*****/
/***** 引数返値:水平個数 *****/
/***** 引数返値:垂直個数 *****/
/************************************************************************/
void CopyClear::CorrImageNMLarge(
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 minHV; // 水平/垂直幅の最小値
int i; // カウンタ
minHV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅の最小値算出
h = ( minHV - n ) / nStepH; // 水平個数を算出
minHV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅の最小値算出
v = ( minHV - 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++ = CorrNMLarge( ptrAX, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, n, m ); // 算出しバッファーに格納
} //
} //
}
☆備考☆この関数はファイル「CopyClear420.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(A)関数「CorrImageNMLarge()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=N×M画素
」のサイズを意味します★備考★この「NM」は、仮引数「
int n,int m,」で指定した値です!更に★備考★少し前の
方で「CorrImage44()」とか「CorrImage88()」と「NM」で
無く、「44」・「88」が名称に入った関数を解説しました
何故、この様に「NM」で指定すれば同じ機能の関数が使え
るのに専用の「CorrImage44()」・「CorrImage88()」が、
存在するかと言うと使用頻度が多い関数だからです!頻度
が高いと言う事は、高性能化(高速化)する必要が有り、
特化したのです!では、「CorrImageNMLarge()」は、何故、存在するかと言うと、依り、汎用に使用したり、「44」・「88」の関数を作成する前にテスト的に色々な組み合わせを研究に使用したからです!
「Large」は、広いとか大きいの意味でココでは、NMの
サイズが大きく途中の相関値計算で32ビット整数を超える
ので浮動小数演算に換えて算出する関数だからです!
(B)関数「void CorrImageNMLarge()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「CorrImageNMLarge()」の【仮引数】
void CopyClear::CorrImageNMLarge(
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)関数「CorrImageNMLarge()」の【アルゴリズム】
){
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 minHV; // 水平/垂直幅の最小値
int i; // カウンタ
minHV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅の最小値算出
h = ( minHV - n ) / nStepH; // 水平個数を算出
minHV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅の最小値算出
v = ( minHV - 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++ = CorrNMLarge( ptrAX, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, 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 minHV; // 水平/垂直幅の最小値
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 minHV;」は、水平(垂直)幅の最小値
★備考★上記「int minHV;」は画像自体の水平垂直幅で、
「N×M升枠」を単位とした処理が可能な最小(有効)画素
サイズの算出です!
「int i;」は、ループカウンタ
(D-2)アルゴリズムコード
minHV = ( pa->h < pb->h ) ? pa->h : pb->h; // 水平幅の最小値算出
h = ( minHV - n ) / nStepH; // 水平個数を算出
minHV = ( pa->v < pb->v ) ? pa->v : pb->v; // 垂直幅の最小値算出
v = ( minHV - 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++ = CorrNMLarge( ptrAX, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, n, m ); // 算出しバッファーに格納
} //
} //
}
「minHV=((pa->h<pb->h)?pa->h:pb->h);
h=(minHV-n)/nStepH;」は、水平画素数の有効(最小)
サイズ算出!
「minVV=((pa->v<pb->v)?pa->v:pb->v);
v=(minHV-m)/nStepV;」は、垂直画素数の有効(最小)
サイズ算出!
「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++=CorrNMLarge(ptrAX,ptrBX,pa->inc,pb->inc,
n, m);」は、サブルーチン関数「CorrNMLarge(()」で
「N×M」升枠で相関値を算出し「*buf++=・・」と
バッファーに追加格納!
★備考★往々にして二次元の画像を二重ループで処理する
極標準的なループの組み合わせですので良く他の処理でも
基本的な処理として使用しています!
(4-14-206)関数「void CorrImageNMLargeMyself(
TypeArray* pa,double* buf,
int n,int m,int nStepH,
int nStepV,int &resH,int &resV){・・・}」
/************************************************************************/
/***** n×m画素自己相関画像適応 *****/
/***** ☆n×mの基本単位毎に画像全体を演算しバッファーに格納☆*****/
/***** 引数返値:水平個数 *****/
/***** 引数返値:垂直個数 *****/
/************************************************************************/
void CopyClear::CorrImageNMLargeMyself(
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; // カウンタ
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++ = CorrNMLargeMyself( ptrAX, pa->inc, // n×m画素自己相関算出
n, m ); //
} //
} //
}
☆備考☆この関数はファイル「CopyClear420.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(A)関数「CorrImageNMLargeMyself()」の【関数名】
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!★備考★相関値は、0.0から
1.0の間の値に成りますが、ココでは、計算途中の分散値
を整数型で算出しますのでモット大きな整数値に成ります!
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=N×M画素」のサイズを意味します
「Large」は、広いとか大きいの意味でココでは、NMの
サイズが大きく途中の相関値計算で32ビット整数を超える
ので浮動小数演算に換えて算出する関数だからです!
「Myself」は、英単語「Myself」の意味通り「自分自身」
です⇒仮引数「TypeArray* pa,」と画像情報が一つしか
無い事に注目して下さい!、詰り、自己相関を算出します!
(B)関数「void CorrImageNMLargeMyself()」の【返値】
関数返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「CorrImageNMLargeMyself()」の【仮引数】
void CopyClear::CorrImageNMLargeMyself(
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)関数「CorrImageNMLargeMyself()」の【アルゴリズム】
){
BYTE* ptrAX; // A配列:処理ポインタ
BYTE* ptrAY; // A配列:処理ポインタ
int incA; // A配列:増加幅(nStepV単位)
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
int i; // カウンタ
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++ = CorrNMLargeMyself( 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)アルゴリズムコード
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++ = CorrNMLargeMyself( ptrAX, pa->inc, // n×m画素自己相関算出
n, m ); //
} //
} //
}
「h=(pa->h-n)/nStepH;v=(pa->v-m)/nStepV;」は、水平・
垂直の処理個数算出!
「resH=h;resV=v;」は、水平・垂直の処理個数を引数辺値
として返す!
「ptrAY=(BYTE*)pa->adr;」は、Y座標処理ポインタの
セット!
「incA=pa->inc*nStepV;」は、NM升枠単位の垂直増加幅
のセット!
次は、処理する二重ループで
「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」と
値が変っても良い変数をダウンカウンタに使用する事で
教科書的な記述よりも現実のコンパイラ環境で依り高速な
機械コード(アセンブラ出力で確認)が生成されるので私の
ソースコードでは多く採用≫、そして内側ループ本体
「*buf++=CorrNMLargeMyself(ptrAX,pa->inc,n,m);」は、
サブルーチン関数「CorrNMLargeMyself()」で自己相関(
分散値)を算出しバッファー格納
(4-14-207)関数「void SearchCorrImageNMLarge(
TypeArray* pa,
TypeArray* pb,double* buf,
int n,int m,int nStepH,
int nStepV,int &resH,int &resV){・・・}
/****************************************************************************/
/***** n×m画素正規化相関サーチ画像適応 *****/
/***** ☆n×mの基本単位毎に画像をサーチし結果をバッファーに格納☆*****/
/***** 引数返値:水平個数 *****/
/***** 引数返値:垂直個数 *****/
/****************************************************************************/
void CopyClear::SearchCorrImageNMLarge(
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の個数)
double sumA; // 合計A(及び自己相関)
int avA; // 平均A
int avB; // 平均B
int i; // カウンタ
int j; // カウンタ
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++ = CorrNMLargeFirst( 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++ = CorrNMLargeSecond( ptrA, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, // 算出しバッファーに格納
n, m, avA, avB, sumA ); //
} //
} //
} //
}
☆備考☆この関数はファイル「CopyClear420.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(A)関数「SearchCorrImageNMLarge()」の【関数名】
「Search」は、英単語「Search」で「探す・探索」です!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「NM」は、比較する画像の範囲として「縦×横=
N×M画素」のサイズを意味します!
「Large」は、広いとか大きいの意味でココでは、NMの
サイズが大きく途中の相関値計算で32ビット整数を超える
ので浮動小数演算に換えて算出する関数だからです!
(B)関数「void SearchCorrImageNMLarge()」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「SearchCorrImageNMLarge()」の【仮引数】
void CopyClear::SearchCorrImageNMLarge(
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)関数「SearchCorrImageNMLarge()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
BYTE* ptrBX; // B配列:処理ポインタ
BYTE* ptrBY; // B配列:処理ポインタ
int incB; // B配列:増加幅(nStepV単位)
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
double sumA; // 合計A(及び自己相関)
int avA; // 平均A
int avB; // 平均B
int i; // カウンタ
int j; // カウンタ
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++ = CorrNMLargeFirst( 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++ = CorrNMLargeSecond( 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の個数)
double 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の個数)
「double sumA;」は、A画像用合計値、及び分散値算出用
「int avA;」は、A画像平均値
「int avB;」は、B画像平均値
「int i;」は、ループカウンタ外側
「int j;」は、ループカウンタ内側
★備考★上記「int h;int v;」は画像自体の水平垂直幅で
無く、「N×M升枠」を単位とした処理個数に注意して下さい
(D-2)アルゴリズムコード
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++ = CorrNMLargeFirst( 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++ = CorrNMLargeSecond( ptrA, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, // 算出しバッファーに格納
n, m, avA, avB, sumA ); //
} //
} //
} //
}
「h=(pa->h-n)/nStepH;v=(pa->v-m)/nStepV;」は、水平・
垂直の処理個数算出!
「resH=h;resV=v;」は、水平・垂直の処理個数を引数辺値
として返す!
「ptrA=(BYTE*)pa->adr;」は、A画像Y座標処理ポインタの
セット!
「ptrBY=(BYTE*)pb->adr;」は、B画像Y座標処理ポインタ
のセット!
「incB=pb->inc*nStepV;」は、B画像NM升枠単位の垂直
増加幅のセット!★備考★A画像のパターンをB画像から
サーチするのでこの値をローカルにセットした事は理解して
下さい!
「*buf++=CorrNMLargeFirst(ptrA,ptrBY,pa->inc,pb->inc,
n,m,avA,avB,sumA);」は、最初の一つ目のN×M升枠の
処理としてサブルーチン関数「CorrNMLargeFirst()」と
名前に「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++=CorrNMLargeSecond(ptrA,ptrBX,pa->inc,pb->inc,
avA,avB,sumA);}」とif条件「!(i==0&&j==0)」詰り、
ループカウンタ「i,j」が同時に「0」最初以外で成立中身
「*buf++=CorrNMLargeSecond(ptrA,ptrBX,pa->inc,
pb->inc,avA,avB,sumA);」とサブルーチン関数
「CorrNMLargeSecond()」で処理します!
(4-14-208)関数「int SearchCorrImageSortLarge(
TypeArray* pa,
TypeArray* pb,TypeCorr *buf,
int size,int n,int m,int nStepH,
int nStepV,double t,
double rate,double minAv,
double maxAv){・・・}
/****************************************************************************/
/***** n×m画素正規化相関サーチ画像適応&データ整理 *****/
/***** ☆n×mの基本単位毎に画像をサーチ☆ *****/
/***** ☆サーチ後、有効相関値以上のデータとその座標を降順に☆ *****/
/***** ☆大きい方からソートし有効数を返す☆ *****/
/***** ☆結果数がサイズより大きい場合は、サイズ内でデータを更新☆ *****/
/***** ★水平/垂直ステップ数×2以内の近接範囲で重複除去を行う★ *****/
/***** 返値:有効個数、負→エラーステータス *****/
/****************************************************************************/
int CopyClear::SearchCorrImageSortLarge(
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の個数)
double 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発生
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 = CorrNMLargeFirst( ptrA, ptrBX, // 先頭の時の相関値算出
pa->inc, pb->inc, //
n, m, avA, avB, sumA ); //
}else{ // 先頭以外ならば
d = CorrNMLargeSecond( ptrA, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, 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 ); // 有効個数を返す
}
☆備考☆この関数はファイル「CopyClear420.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(A)関数「SearchCorrImageSortLarge()」の【関数名】
「Search」は、英単語「Search」で「探す・探索」です!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです、ココでは、サーチした
画像の相関値の大きい方から順にソートする事を示します!
「Large」は、広いとか大きいの意味でココでは、NMの
サイズが大きく途中の相関値計算で32ビット整数を超える
ので浮動小数演算に換えて算出する関数だからです!
(B)関数「void SearchCorrImageSortLarge()」の【返値】
返値としてサーチした有効個数を返す関数です!
(C)関数「SearchCorrImageSortLarge()」の【仮引数】
int CopyClear::SearchCorrImageSortLarge(
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)関数「SearchCorrImageSortLarge()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
BYTE* ptrBX; // B配列:処理ポインタ
BYTE* ptrBY; // B配列:処理ポインタ
int incB; // B配列:増加幅(nStepV単位)
int h; // 水平幅(n×mの個数)
int v; // 垂直幅(n×mの個数)
double 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発生
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 = CorrNMLargeFirst( ptrA, ptrBX, // 先頭の時の相関値算出
pa->inc, pb->inc, //
n, m, avA, avB, sumA ); //
}else{ // 先頭以外ならば
d = CorrNMLargeSecond( ptrA, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, 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の個数)
double 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)アルゴリズムコード
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 = CorrNMLargeFirst( ptrA, ptrBX, // 先頭の時の相関値算出
pa->inc, pb->inc, //
n, m, avA, avB, sumA ); //
}else{ // 先頭以外ならば
d = CorrNMLargeSecond( ptrA, ptrBX, // n×m画素の正規相関を
pa->inc, pb->inc, 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 ); // 有効個数を返す
}
「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=CorrNMLargeFirst(
ptrA,ptrBX,pa->inc,pb->inc,n,m,avA,avB,sumA);}」は、
if条件「!firstSw」と初回「first」のサブルーチン
関数「CorrNMLargeFirst()」が処理されて無ければ、
「firstSw=TRUE;」と処理済みにスィッチをセット、
そしてサブルーチン関数「CorrNMLargeFirst()」で
1升N×M升枠の相関値算出処理し、
「}else{d=CorrNMLargeSecond(ptrA,ptrBX,pa->inc,
pb->inc,n,m,avA,avB,sumA);}」で条件不成立「既に初回
firstのサブルーチン関数「CorrNMLargeFirst()」が処理
済みならば、
「d=CorrNMLargeSecond(ptrA,ptrBX,pa->inc,pb->inc,
n,m,avA,avB,sumA);}」とサブルーチン関数
「CorrNMLargeSecond()」で一升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-209)関数「int SearchCorrImageXYSortLarge(
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::SearchCorrImageXYSortLarge(
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配列:増加幅
double sumA; // 合計A(及び自己相関)
int avA; // 平均A
int avB; // 平均B
double d; // 相関値
int x; // X座標
int y; // Y座標
double r; // 正/反転の割合
int i; // カウンタ
int firstSw; // 真→先頭処理済み
int n1; // 有効個数
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 = CorrNMLargeFirst( ptrA, ptrBXY, // 先頭の時の相関値算出
pa->inc, pb->inc, //
n, m, avA, avB, sumA ); //
}else{ // 2番目以降ならば
d = CorrNMLargeSecond( ptrA, ptrBXY, // n×m画素の正規相関を
pa->inc, pb->inc, 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 ); // 有効個数を返す
}
☆備考☆この関数はファイル「CopyClear420.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(A)関数「SearchCorrImageXYSortLarge()」の【関数名】
「Search」は、英単語「Search」で「探す・探索」です!
「Corr」は、英単語「correlation」の省略で「相関」を
意味します!相関とは、「二つの物が、関わり合いを持つ」
と有る様に二つの画像を比較して相関値≪ここでは、1に
近い程高い相関値が有ると0.0から1.0の相関値を画像
に対して≫を算出します!
「Image」は、勿論、画像です!
「XY」は、XY座標を意味します!
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです、ココでは、他の関数
「SearchCorrImageSort()」で算出した相関値+座標「
TypeCorr* buf,」データを相関値降順(大⇒小)に改めて
ソートする事を示します!
「Large」は、広いとか大きいの意味でココでは、NMの
サイズが大きく途中の相関値計算で32ビット整数を超える
ので浮動小数演算に換えて算出する関数だからです!
(B)関数「int SearchCorrImageXYSortLarge()」の【返値】
返値としてサーチした有効個数を返す関数です!
(C)関数「SearchCorrImageXYSortLarge()」の【仮引数】
int CopyClear::SearchCorrImageXYSortLarge(
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)関数「SearchCorrImageXYSortLarge()」の【アルゴリズム】
){
BYTE* ptrA; // A配列:処理ポインタ
BYTE* ptrB; // B配列:処理ポインタ
BYTE* ptrBXY; // B配列:処理ポインタ
int minH; // B配列:水平幅最小値
int minV; // B配列:垂直幅最小値
int incB; // B配列:増加幅
double sumA; // 合計A(及び自己相関)
int avA; // 平均A
int avB; // 平均B
double d; // 相関値
int x; // X座標
int y; // Y座標
double r; // 正/反転の割合
int i; // カウンタ
int firstSw; // 真→先頭処理済み
int n1; // 有効個数
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 = CorrNMLargeFirst( ptrA, ptrBXY, // 先頭の時の相関値算出
pa->inc, pb->inc, //
n, m, avA, avB, sumA ); //
}else{ // 2番目以降ならば
d = CorrNMLargeSecond( ptrA, ptrBXY, // n×m画素の正規相関を
pa->inc, pb->inc, 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配列:増加幅
double 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* ptrBXY;」は、B画像用XY座標方向処理ポインタ
「int minH;」は、B画像の水平幅最小値
「int minV;」は、B画像の垂直幅最小値
「int incB;」は、B画像増加幅
「double sumA;」は、A画像用合計値、及び分散値算出用
「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)アルゴリズムコード
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 = CorrNMLargeFirst( ptrA, ptrBXY, // 先頭の時の相関値算出
pa->inc, pb->inc, //
n, m, avA, avB, sumA ); //
}else{ // 2番目以降ならば
d = CorrNMLargeSecond( ptrA, ptrBXY, // n×m画素の正規相関を
pa->inc, pb->inc, 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 ); // 有効個数を返す
}
「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=CorrNMFirstLarge(ptrA,ptrBXY,
pa->inc,pb->inc,n,m,avA,avB,sumA);」とサブルーチン
関数「CorrNMFirstLarge()」で相関値を再算出し、
「else{d=CorrNMSecondLarge(ptrA,ptrBXY,pa->inc,
pb->inc,n,m,avA,avB,sumA);}」と「else{」と
不成立時=初回「first」以外=2回目以降としてサブルー
チン関数「CorrNMSecondLarge()」で相関値を再算出!
★注意★ここだけ「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」を
関数辺値とし返し関数終了!
カナリ、この説明文書も大きく成り、追加する予定の関数が
有りますが、ココまでで区切り≪次から「正規相関
にマスク画像が絡む」関数の解説が始まり≫が良いので新し
い解説『解説クラスCopyClear(26)』を近々、
続きとして発表する事にして、ココでこの
解説『解説クラスCopyClear(25)』は終わる事
にします!引き続き、
新規解説『解説クラスCopyClear(26)』を
御贔屓下さい!