5

背景: 画像から 2 セットのカラー ピクセルがあり、1 つは背景に対応し、もう 1 つは前景に対応します。次に、各セットに対して OpenCV の EM を使用して 2 つのガウス混合モデルをトレーニングします。私の目的は、ランダムなピクセルが前景と背景に属する確率を見つけることです。したがって、ピクセルの各 EM に対して「予測」機能を使用します。

質問:

  • この関数が返す値がわかりません。OpenCV のドキュメントでは、次のように書かれています。

このメソッドは、2 要素の double ベクトルを返します。ゼロ要素は、サンプルの尤度対数値です。最初の要素は、特定のサンプルの最も可能性の高い混合成分のインデックスです。

http://docs.opencv.org/modules/ml/doc/expectation_maximization.html?highlight=predict#Vec2d%20EM::predict%28InputArray%20sample,%20OutputArray%20probs%29%20const

「尤度対数」の意味がわかりません。私の結果では、時々負の値と値 > 1 があります。同じ関数を使用した人で、この種の結果または 0 と 1 の間の結果が得られますか? 私の結果から何を結論付けることができますか?

  • ピクセルが GMM 全体に属する確率を取得するにはどうすればよいですか (GMM の各クラスターに属する確率ではありません)。

これが私のコードです:

Mat mask = imread("mask.tif", 0);
Mat formerImage = imread("ImageFormer.tif");
Mat currentImage = imread("ImageCurrent.tif");

// number of cluster in the GMM 
int nClusters = 5;

int countB=0, countF=0;

Vec3b color;

Vec2d probFg, probBg; // probabilities to belong to the foreground or background from GMMs

//count the number of pixels for each training data
for(int c=0; c<=40;c++) {
    for(int l=0; l<=40;l++) {
        if(mask.at<BYTE>(l, c)==255) {
            countF++;
        } else if(mask.at<BYTE>(l, c)==0) {
            countB++;
        }
    }
}


printf("countB %d countF %d \n", countB, countF);

Mat samplesForeground = Mat(countF,3, CV_64F);

Mat samplesBackground = Mat(countB,3, CV_64F);


// Expectation-Maximisation able to resolve the GMM and to predict the probability for a pixel to belong to the GMM.
EM em_foreground= EM(nClusters);
EM em_background= EM(nClusters);

countB=0;
countF=0;

// fill the training data from the former image depending of the mask
for(int c=0; c<=40;c++) {
    for(int l=0; l<=40;l++) {
        if(mask.at<BYTE>(l, c)==255) {
            color = formerImage.at<Vec3b>(l, c);
            samplesForeground.at<double>(countF,0)=color[0];
            samplesForeground.at<double>(countF,1)=color[1];
            samplesForeground.at<double>(countF,2)=color[2];
            countF++;
        } else if(mask.at<BYTE>(l, c)==0) {
            color = formerImage.at<Vec3b>(l, c);
            samplesBackground.at<double>(countB, 0)=color[0];
            samplesBackground.at<double>(countB, 1)=color[1];
            samplesBackground.at<double>(countB, 2)=color[2];
            countB++;
        }
    }
}

printf("countB %d countF %d \n", countB, countF);
em_foreground.train(samplesForeground);
em_background.train(samplesBackground);

Mat sample(1, 3, CV_64F);

// try every pixel of the current image and get the log likelihood
for(int c=0; c<=40;c++) {
    for(int l=0; l<=40;l++) {
        color = currentImage.at<Vec3b>(l,c);
        sample.at<double>(0)=color[0];
        sample.at<double>(1)=color[1];
        sample.at<double>(2)=color[2];
        probFg=em_foreground.predict(sample);
        probBg=em_background.predict(sample);
        if(probFg[0]>0 || probBg[0]>0)
            printf("probFg[0] %f probBg[0] %f \n", probFg[0], probBg[0]);
    }
}

編集

@BrianL が説明した後、対数の可能性がわかりました。

私の問題は、予測関数の対数確率が 0 を超える場合があることです。ただし、<=0 である必要があります。以前にこの問題に遭遇した人はいますか?

問題を表示するために上記のコードを編集しました。以下の画像でプログラムを試しました:

最初の画像は ImageCurrent.tif、2 番目は ImageFormer.tif、最後の画像は mask.tif です。

現在の画像 元画像 マスク

これは OpenCV のバグと見なすことができますか? OpenCV バグトラッカーでチケットを開く必要がありますか?

4

3 に答える 3

4

「尤度対数」とは、確率の対数を意味します。確率pについては 0 ≤ p ≤ 1 と予想されるため、値は負であると予想されます: log( p ) ≤ 0. 負の数値が大きいほど、確率は小さくなります。

この形式は、確率が非常に小さい積を扱う場合に役立ちます。通常の方法で乗算すると、確率が非常に小さくなるため、アンダーフローが発生しやすくなり、精度が失われる可能性があります。しかし、対数空間では、乗算が加算に変わり、精度が向上し、計算速度も向上する可能性があります。

このpredict関数は、データ ポイントを分類するためのものです。ポイントがモデル内のいずれかのコンポーネントに属する可能性についてスコアを付けたい場合は、モデル パラメーター (getドキュメントを参照) を使用して自分で計算できます。

于 2013-01-10T04:10:41.390 に答える
1

グラフカットベースの画像セグメンテーションを行っていることに気付きました。

グラフカットベースの画像セグメンテーションを実行するために行っているのと非常によく似た方法でOpenCVとそのGMMクラスを使用する次のブログ投稿を参照することをお勧めします。コードはC++で詳細な説明とともに提供されています。リンクは次のとおりです。link

基本的に、ログの確率は、それが正しいかどうかにかかわらず、あなたが探しているものではないとしか言​​えません。詳細については、上記のリンクを確認してください。

于 2013-02-21T04:53:09.243 に答える