0

OpenCV と SVM with images を使用して、このトピックに関連する優れた/包括的な投稿/回答を見つけました。ただし、リンクの回答から明確にしたい質問がいくつかあります。(コメントを書くのに十分な評判がないため)。

私が行ってきたこと: トレーニングに OpenCV SVM を使用しています。トレーニング マトリックスに使用される特徴は、各画像の正規化された平均 R、G、および B 値を計算することによって得られます。したがって、トレーニング マトリックスでは、各行 (または各画像) に 4 つの列があります。これらの列は、ラベル (1 または 0)、 ****r チャネルの正規化された平均****、gおよびbチャネルに対応します。

ところで、元のトレーニング ファイルはテキスト ファイルであり、引き続き float[][] に変換し、最終的に Mat オブジェクトに変換して、opencv の SVM にフィードします。ファイルは次のようになります。

1 0.267053 0.321014 0.411933
1 0.262904 0.314294 0.422802
.
.
0 0.29101 0.337208 0.371782
0 0.261792 0.314494 0.423714

どうやら、これは各行のサイズが画像のサイズと等しくなければならないというリンクの記述と矛盾しています。それはプロトコルですか、それともある種のルールですか? なぜそうすべきなのか(もしそうなら)、私はただ意味がわかりません。

私の質問は、トレーニング行列を構築する際に、各行の長さは画像の領域またはサイズに対応する必要がありますか? 私が作成したトレーニング マトリックスのように、各行の長さは 4 しかありません。これは間違っていますか?

さらに、トレーニング用に 3 つの機能 (3 列) だけで分類/SVM に十分ですか? 私を正しい道に導いてください。これを続けるべきか、それとも問題に対する他のより良いアプローチがあるかどうか疑問に思っています。

SVM のステップの背後にある概念をさらに理解できるようになることを願っています。記事または関連するサンプルをいただければ幸いです。

4

2 に答える 2

2

各行のサイズは、画像サイズと同じである必要はありません。それはあなたが持っている機能によって異なります。画像分類に平均値を使用するだけでは十分ではありません。写真を見たときにオブジェクトをどのように分類するかを考えてみてください。平均値は計算しませんが、輪郭、接続された領域、場合によっては脳の処理の背景にある個々のピクセル値を調べます。

より多くの機能を得るために、私はあなたに提案があります。特徴抽出部分の各列の平均値を計算します。これはおそらくより便利です。

また、別の特徴抽出には、PCA を使用できます。通常、SVM をトレーニングするためにすべてのピクセル値を連続して与えることができますが、200*200 の画像であっても、これは 40.000 の特徴になります。多くの情報を失うことなく、この機能の次元を削減する必要があります。これは、分散の許容パーセンテージを保持することを意味します。したがって、これには PCA が使用され、特徴空間の次元が削減され、分散が許容範囲内に維持されます。

PCA を使用して特徴空間を削減する方法を紹介します。最初に、イメージを Mat 変数に行ごとにロールするよりも、イメージを取得する必要があります。

csv の読み取り:

void read_csv(const string& filename, vector& images, vector& labels, char separator = ';')
{
    std::ifstream file(filename.c_str(), ifstream::in);
    if (!ファイル)
    {
        string error_message = "有効な入力ファイルが指定されていません。指定されたファイル名を確認してください。";
        CV_Error(1, error_message);
    }
    文字列行、パス、クラスラベル。
    while (getline(ファイル、行))
    {
        stringstream liness(行);

        getline(行、パス、区切り);
        getline(ライン、クラスラベル);

        if(!path.empty() && !classlabel.empty())
        {
            Mat im = imread(パス, 0);

            images.push_back(im);
            labels.push_back(atoi(classlabel.c_str()));
        }
    }
}

行ごとに画像をローリング:

Mat rollVectortoMat(const vector<Mat> &data) // data is vector of Mat images
{
   Mat dst(static_cast<int>(data.size()), data[0].rows*data[0].cols, CV_32FC1);
   for(unsigned int i = 0; i < data.size(); i++)
   {
      Mat image_row = data[i].clone().reshape(1,1);
      Mat row_i = dst.row(i);                                       
      image_row.convertTo(row_i,CV_32FC1, 1/255.);
   }
   return dst;
} 

主要

int main()
{

    PCA pca;

    vector<Mat> images_train;
    vector<Mat> images_test;
    vector<int> labels_train;
    vector<int> labels_test;

    read_csv("train1k.txt",images_train,labels_train);
    read_csv("test1k.txt",images_test,labels_test);

    Mat rawTrainData = rollVectortoMat(images_train);                       
    Mat rawTestData  = rollVectortoMat(images_test);                

    Mat trainLabels = getLabels(labels_train);
    Mat testLabels  = getLabels(labels_test);

    int pca_size = 500;

    Mat trainData(rawTrainData.rows, pca_size,rawTrainData.type());
    Mat testData(rawTestData.rows,pca_size,rawTestData.type());


    pca(rawTrainData,Mat(),CV_PCA_DATA_AS_ROW,pca_size);

    for(int i = 0; i < rawTrainData.rows ; i++)
        pca.project(rawTrainData.row(i),trainData.row(i));

    for(int i = 0; i < rawTestData.rows ; i++)
        pca.project(rawTestData.row(i),testData.row(i));

}

要約すると、 image_path;label のような csv ファイルを読み取ります。画像を Mat 変数に行ごとにロールするよりも。pca を適用して 500 機能に減らします。これらの PCA redcution を適用して、200*200 画像 (40000 特徴) を 500 特徴サイズに縮小しました。これを分類するために MLP を適用しました。この testData 変数と trainData 変数は、SVM でも使用できます。また、SO の投稿で MLP を使用してトレーニングする方法を確認することもできます。

OpenCV ニューラル ネットワーク シグモイド出力

于 2014-03-07T09:13:08.433 に答える