教師付き分類を行うときに最尤法を用いる場合、
マハラノビス距離を計算するために教師データの分散・共分散行列が必要になります。
チャンネル数Kの画像のチャンネル間の分散・共分散行列は以下の式で表されます。
ここで、対角成分はそれぞれのチャンネルの分散になります。
Mは各チャンネルの平均ベクトルです。
また、分散・共分散行列は対称行列です。
これを用いて入力画像の分散・共分散行列を求めるには以下のようにします。
/** * 入力画像の分散・共分散行列を求める * * @param btImg 入力画像 * @param nRow 画像の縦のピクセル数 * @param nCol 画像の横のピクセル数 * @param nCh 画像のチャンネル数 * @param dMeanVect 各チャンネルの平均ベクトル、あらかじめ確保済み * @param dCovMat 分散・共分散行列、確保済み */ void calc_cov( BYTE *btImg, int nRow, int nCol, int nCh, double *dMeanVect, double *dCovMat ) { int i, j, m, n; double dV; double *pdImg; // 初期化 for ( i = 0; i < nCh; i++ ) { dMeanVect[i] = 0.0; for ( j = 0; j < nCh; j++ ) dCovMat[i*nCh+j] = 0.0; } // まず、平均ベクトルを求める for ( i = 0, n = 1; i < nRow*nCol; i++, n++ ) { for ( j = 0; j < nCh; j++ ) { dV = btImg[i*nCh+j]; dV -= dMeanVect[j]; dMeanVect[j] += dV / n; } } // 分散共分散行列を求める pdImg = new double[nRow*nCol*nCh]; for ( i = 0; i < nRow*nCol; i++ ) { for ( j = 0; j < nCh; j++ ) { pdImg[i*nCh+j] = (double)btImg[i*nCh+j] - dMeanVect[j]; } } for ( i = 0; i < nRow*nCol; i++ ) { for ( m = 0; m < nCh; m++ ) { for ( n = m; n < nCh; n++ ) { dCovMat[m*nCh+n] += pdImg[i*nCh+m] * pdImg[i*nCh+n] / (nRow*nCol); } } } delete[] pdImg; // 一応転置位置の成分を埋める for ( m = 0; m < nCh; m++ ) { for ( n = m+1; n < nCh; n++ ) { dCovMat[n*nCh+m] = dCovMat[m*nCh+n]; } } }