Got different EM::predict() results after EM::read() saved model

asked 2014-05-05 13:49:21 -0600

pheliox gravatar image

updated 2014-05-05 13:50:12 -0600

Hi there! I'm new to OpenCV and C++ and I'm trying to build a classifier using Gaussian Mixture Model within the OpenCV. I figured out how it works and got it worked ... maybe. I got something like this now:

If I classify the training samples just after the model was trained and saved, I got the result I want. But when I reclassify my training data using the read(), one of the clusters is missing, means I got different cluster result from the same GMM model. I don't get it now because the cluster I want was gone, I can't reproduce the classification again until I retrained the model using the same data. I checked the code in runtime and the result valule in the Vec2d from <log, result=""> which predict() returned was never assigned to 1 (I set 3 clusters).

Maybe there's a bug or I did something wrong?

p.s. I'm using 2.4.8 in VS2013

My programs like this:

train part

void GaussianMixtureModel::buildGMM(InputArray _src){
    //use source to train GMM and save the model

    Mat samples, input = _src.getMat();    
    createSamples(input, samples);
    bool status = em_model.train(samples);

    saveModel();
}

save/load the model

FileStorage fs(filename, FileStorage::READ);
if (fs.isOpened()) // if we have file with parameters, read them
{
    const FileNode& fn = fs["StatModel.EM"];
    em_model.read(fn);
    fs.release();
}

FileStorage fs_save(filename, FileStorage::WRITE);
if (fs_save.isOpened()) // if we have file with parameters, read them
{
    em_model.write(fs_save);
    fs_save.release();
}

predict part

vector<Mat> GaussianMixtureModel::classify(Mat input){
/// samples is a matrix of channels x N elements, each row is a set of feature
Mat samples;
createSamples(input, samples);
    for (int k = 0; k < clusterN; k++){
        masks[k] = Mat::zeros(input.size(), CV_8UC1);
    }
int idx = 0;
for (int i = 0; i < input.rows; i++){
    for (int j = 0; j < input.cols; j++){
        //process the predicted probability
        Mat probs(1, clusterN, CV_64FC1);
        Vec2d response = em_model.predict(samples.row(idx++), probs);
        int result = cvRound(response[1]);
        for (int k = 0; k < clusterN; k++){
                            if (result == k){
                // change to the k-th class's picture
                masks[k].at<uchar>(i, j) = 255;
            }
                    ...
                    // something else
                    }
             }
       }
}
edit retag flag offensive close merge delete