サイトマップ
お知らせ、メモ
案内板
うちのヘッドライン
 




トップ  >  プログラム豆知識  >  アルゴリズム豆知識  >  画像の分散・共分散行列を求める

画像の分散・共分散行列を求める

教師付き分類を行うときに最尤法を用いる場合、 マハラノビス距離を計算するために教師データの分散・共分散行列が必要になります。

チャンネル数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];
    }
  }
}

参考文献


クリエイティブ・コモンズ・ライセンス
This documents by Yamate,N is licensed under a Creative Commons 表示 - 継承 3.0 非移植 License.
login