2

私は OpenCV と C++ が初めてで、OpenCV 内でガウス混合モデルを使用して分類器を構築しようとしています。私はそれがどのように機能するかを理解し、それを機能させました...多分。私は今このようなものを得ました:

モデルをトレーニングして保存した直後にトレーニング サンプルを分類すると、必要な結果が得られます。しかし、read()を使用してトレーニング データを再分類すると、クラスターの 1 つが欠落しています。これは、同じ GMM モデルから異なるクラスター結果を得たことを意味します。必要なクラスターがなくなったため、今はわかりません。同じデータを使用してモデルを再トレーニングするまで、分類を再度再現することはできません。実行時にコードをチェックし、Vec2dの結果値を返されたpredict()が 1 に割り当てられることはありませんでした (3 つのクラスターを設定しました)。

たぶんバグがあるか、何か間違ったことをしましたか?

ps 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
                    }
             }
       }
}
4

1 に答える 1

1

私の答えは遅すぎると思いますが、同じ問題に遭遇したので、私が見つけた解決策は他の人にとって役立つかもしれません.

ソースコードを分析すると、EM::COV_MAT_DIAGONAL の場合、共分散行列の固有値 (ソース コードでは covsEigenValues) が、保存されたデータを読み込んだ後に SVD を介して取得されることがわかりました。ただし、SVD は特異値 (この場合は固有値) を計算し、昇順で格納します。これを防ぐために、covsEigenValues に読み込まれた共分散行列の対角要素を直接抽出して、適切な順序を維持します。

于 2014-09-11T02:20:45.853 に答える