5

Background: I have 2 sets of color pixels from an image, one corresponding to the background, another corresponding to the foreground. Next, I train 2 Gaussian Mixture Models using EM from OpenCV for each set. My aim is to find the probability of a random pixel to belong to the foreground and to the background. Thus, I use the function "predict" for each EM on my pixel.

Question:

  • I don't understand the values returned by this function. In the documentation of OpenCV, it is written:

The method returns a two-element double vector. Zero element is a likelihood logarithm value for the sample. First element is an index of the most probable mixture component for the given sample.

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

I don't understand what means "likehood logarithm". In my results, I have sometimes negative values and values > 1. Is anyone who used the same function has this kind of results or resuts between 0 and 1 ? What can I conclude from my results ?

  • How can I get the probability of a pixel to belong to the whole GMM (not the probality to belong to each cluster of the GMM) ?

Here is my code:

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]);
    }
}

EDIT

After @BrianL explained, I now understand the log likelihood.

My problem is the log probability of the predict function is sometimes >0. But it should be <=0. Has anyone met this problem before?

I have edited the code above to show the problem. I have tried the program with images below:

The first image is the ImageCurrent.tif, the second is the ImageFormer.tif and the last one is mask.tif.

current image former image mask

Is this can be considered a bug in OpenCV? Should I open a ticket on OpenCV bug tracker?

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
Seltymar
  • 337
  • 6
  • 21

3 Answers3

4

The "likelihood logarithm" means the log of the probability. Since for a probability p we expect 0 ≤ p ≤ 1, I would expect the values to be negative: log(p) ≤ 0. Larger negative numbers imply smaller probabilities.

This form is helpful when you are dealing with products of very small probabilities: if you multiplied the normal way, you could easily get underflow and lose precision because the probability becomes very small. But in log space the multiplication turns into an addition, which improves the accuracy and also potentially the speed of the calculation.

The predict function is for classifying a data point. If you want to give a point a score for how likely it is to belong to any component in the model, you can use the model parameters (see the get documentation) to calculate it yourself.

Brian L
  • 3,201
  • 1
  • 15
  • 15
  • Sorry to bother you but do you see any problem in the code above ? I still don't understand how the predict function can return me likelihood logarithm superior of 0. – Seltymar Feb 06 '13 at 06:16
  • it seems that, for example `color[2]/255.0` is not correct and leads to error. – Seltymar Feb 06 '13 at 06:35
  • Why are you dividing by 255? Is that what you've done to the training data too? Also why do you switch around the indexes - `color[2/1/0]` goes to `sample(0/1/2)`? There seem to be a number of things going on in your code, so I'm not sure what error you are specifically getting. The `predict` function returns a 2-element vector; the first element is the classification, and the second element is the log likelihood. The second element should never be positive, but the first one can be. – Brian L Feb 07 '13 at 04:02
  • Actually, I'm dividing by 255 because I have a 3 channels with 8 bits color image. So I wanted to normalize my data but it is not necessary (same for the training data too). As Opencv reads always image in BGR format it was just to get a RGB format to be coherent with my code but I changed that and now have `color[0/1/2]`. From the documentation of `predict` http://docs.opencv.org/modules/ml/doc/expectation_maximization.html?highlight=em#em-predict the zero element is the log likehood and it is this one that I'm looking. Should I edit my code or open a new question ? I still have the problem. – Seltymar Feb 07 '13 at 05:40
1

I notice that you are doing graphcut based image segmentation.

You might want to take a look at the following blog post which use OpenCV and its GMM class in a very similar way as what you are doing to perform graph cut-based image segmentation. Code is given in C++ with detailed explanations. Here is the link: link

Basically, I can only say that the log probability, whether it is correct or not, is not what you are looking for. Check out the above link for details.

lightalchemist
  • 10,031
  • 4
  • 47
  • 55
  • Thank you for the link. But I don't want to build a graph-cut. As I already know the color for my foreground and background, I try to cluster them and to define the affinity to belongs to one and the other GMM. But after that, I don't use a graph-cut. I try to implement the point 2.1 from this paper http://juew.org/projects/SnapCut/snapcut.htm (this is the page project, you can choose the quality of the pdf). I will try to compute the probability using the weight and the probability of each cluster. – Seltymar Feb 21 '13 at 06:57
  • Actually, it can't work using the probability of each cluster and the weight. The sum of the weight is 1 and the sum of probability is 1 too. for example, if I have 2 clusters in my GMM with weights (0.6 and 0.4). Now, I have a pixel very far from the GMM in color space but with probability to belong to each cluster of (0.5 and 0.5), I will have a probability of 0.3. But in reality, I should get something close to 0 as it is very far. That's why I wanted to get the probability to belongs to the whole GMM. – Seltymar Feb 21 '13 at 07:30
  • Hi. My intention of giving the link is to show you how the authors of the graphcut-based image segmentation code used GMM to compute the probability a sample pixel belongs to a foreground/background color model. Basically, what I'm saying is the probability which you obtained from calling the "predict" method of the GMM class is not what you are looking for. The GC segmentation code however does, so check it out. Hope this helps. – lightalchemist Feb 21 '13 at 09:01
  • But what I understand from his code is that he's taking the highest probability by multiplying the weight by the probability of each cluster.`for(int g=0;g – Seltymar Feb 21 '13 at 10:22
  • If I take only probability to belongs to the foreground (with 1 GMM). I will have error when foreground color and background colors are similar. – Seltymar Feb 21 '13 at 10:23
  • Maybe, I misunderstoud what the probability is computed in the paper Video Snapcut. – Seltymar Feb 22 '13 at 00:33
  • This is not graph-cut based segmentation. – koshy george Nov 27 '15 at 03:50
1

As I understand you have two separate GMMs for the foreground and background part of the image.The total probability of a sample pixel 'x' in the test image when evaluated in the foreground GMM is

P_fg(x) = sum_over_j_1_to_k ( Wj_fg * Pj_fg( x ))
where 
k = number of clusters in foreground GMM
x = test sample
Pj_fg(x) = probability that sample x is in j-th  cluster according to the foreground GMM
Wj_fg = weight of the j-th cluster in foreground GMM
also, sum of all weights should be 1 for each GMM.

We can do a similar calculation for the background GMM.

From looking at the EM code in opencv, it looks like the first part of the 2 values that EM returns is the log likelihood. For the foreground GMM this is

log(P_fg(x_i))

I implemented your algorithm and for each pixel in the test image, I compared the log-likelihoods returned for each of the two GMM-s and classified the pixel with the GMM with higher value. I got decent results.

In that respect, yes this value is an indication of the pixel to be belonging to the entire GMM.

2) In my implementation of your problem, I always got the log likelihoods of all GMMS of all test-sample pixels under 0.

koshy george
  • 671
  • 6
  • 24