期望最大化-在OpenCV中EM::read()保存模型后得到不同的EM::predict()结果



我是OpenCV和c++的新手,我试图在OpenCV中使用高斯混合模型构建一个分类器。我弄清楚了它是如何工作的,并让它工作了……也许吧。我现在得到了这样的东西:

如果我在模型刚刚训练完成并保存之后对训练样本进行分类,我就得到了我想要的结果。但是,当我使用read()对训练数据进行重新分类时,其中一个聚类缺失,这意味着我从相同的GMM模型中得到了不同的聚类结果。我现在没有得到它,因为我想要的集群已经消失了,我无法再次复制分类,直到我使用相同的数据重新训练模型。我在运行时检查了代码,Vec2d中的结果值来自,其中predict()返回从未分配给1(我设置了3个集群)。

可能有bug或者我做错了什么?

注。我在VS2013中使用2.4.8

我的程序是这样的:

培训部分

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

保存/加载模型

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

预测部分
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
                    }
             }
       }
}

我想我的答案将是太迟了,但由于我遇到了同样的问题,我发现的解决方案可能对其他人有用。

通过分析源代码,我注意到在EM::COV_MAT_DIAGONAL的情况下,协方差矩阵的特征值(源代码中的covsEigenValues)是在加载保存的数据后通过SVD获得的。然而,SVD计算奇异值(在我们的例子中是特征值)并按ASCENDING顺序存储它。为了防止这种情况,我只是直接提取covsEigenValues中加载的协方差矩阵的对角元素,以保持良好的顺序。

相关内容

  • 没有找到相关文章

最新更新