2016-04-24 12 views
0

i neuronales Netz zu klassifizieren zwei Arten von Bildern trainieren wollen, aber wenn Zugnetz dieser Fehler aufgetreten:OpenCV Fehler beim Zug ANN_MLP

OpenCV Fehler: Bad Argument (Ausgabe Trainingsdaten sollte eine Floating-Point-Matrix mit der Zahl der Zeilen, die der Anzahl der Trainings-Samples und der Anzahl der Spalten entspricht, die der Größe der letzten (Ausgangs-) Ebene entspricht) in cv :: ml :: ANN_MLPImpl :: prepare_to_train, Datei C: \ Buildslave64 \ win64_amdocl \ master_PackSlave-win64-vc14 -shared \ opencv \ modules \ ml \ src \ ann_mlp.cpp, Linie 675

mein Code:

#include "opencv2\core.hpp" 
#include "opencv2\imgproc.hpp" 
#include "opencv2\imgcodecs.hpp" 
#include "opencv2\highgui.hpp" 
#include "opencv2\ml.hpp" 
#include <string> 
#include "lbp.h" 
using namespace cv; 
using namespace cv::ml; 
void LoadTrainingData(); 

Mat Data; 
Mat Lables; 
//const int numberOfClass1 = 2384; 
//const int numberOfClass2 = 2462; 
const int numberOfClass1 = 23; 
const int numberOfClass2 = 24; 
int Class1 = 1; 
int Class2 = -1; 
const int imageDimention = 22; 

std::string NumberToString(size_t Number) 
{ 
    std::stringstream ss; 
    ss << Number; 
    return ss.str(); 
} 



void main() { 
    LoadTrainingData(); 
    Ptr<ANN_MLP> annClassifier; 
    annClassifier = ANN_MLP::create(); 
    annClassifier->setActivationFunction(ANN_MLP::ActivationFunctions::SIGMOID_SYM); 
    Mat layers(1, 3, CV_32F); 
    layers.at<float>(0) = Data.cols; 
    layers.at<float>(1) = 100; 
    layers.at<float>(2) = 2; 
    annClassifier->setLayerSizes(layers); 
    annClassifier->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6)); 
    annClassifier->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP); 
    bool trained = annClassifier->train(Data,ROW_SAMPLE,Lables); 
    if (trained) 
     annClassifier->save("Ann_sigmoid_eye"); 

} 
void LoadTrainingData() { 

    Data = Mat(numberOfClass1 + numberOfClass2, imageDimention*imageDimention, CV_32FC1); 
    Lables = Mat(numberOfClass1 + numberOfClass2,1 , CV_32SC1); 
    // load openEye 
    Mat img; 
    Mat lbpImg; 
    Mat row; 
    std::string path; 
    for (size_t i = 1; i <= numberOfClass2; i++) 
    { 
     path = "class1 (" + NumberToString(i) + ").jpg"; 
     img = imread(path); 
     if (img.channels() > 1) 
      cvtColor(img, img, CV_BGR2GRAY); 
     lbp::ELBP(img,lbpImg, 1, 16);  
     row = lbpImg.reshape(0, 1); 
     row.convertTo(row, CV_32FC1); 
     Data.push_back(row); 
     Lables.push_back(Class1); 

    } 
    for (size_t i = 1; i <= numberOfClass1; i++) 
    { 
     path ="class2 (" + NumberToString(i) + ").jpg"; 
     img = imread(path); 
     if (img.channels() > 1) 
      cvtColor(img, img, CV_BGR2GRAY); 
     lbp::ELBP(img,lbpImg, 1, 16); 
     row = lbpImg.reshape(0, 1); 
     row.convertTo(row, CV_32FC1); 
     Data.push_back(row); 
     Lables.push_back(Class2); 
    } 
} 

ich weiß nicht, warum das passiert! bitte hilf mir, danke.

Antwort

0

Die Zugantworten für ein Ann unterscheiden sich ein wenig von dem üblichen opencv ml-Ansatz.

Wenn 2 Ausgabe-Neuronen in Ihrem Ann enthalten sind, benötigen Sie 2 Ausgabe-Neuronen für jedes Trainingsmerkmal, nicht ein einzelnes "Klassen-Label" (wie bei z. B. einer SVM).

es sollte wie folgt aussehen:

[train_data]    [train_responses] 

lbpfeature1     -1 1  // class A 
lbpfeature2     -1 1  // class A 
lbpfeature3     1 -1  // class B 
lbpfeature4     1 -1  // class B 

so müssen die Antworten num_features Reihen X 2 cols haben. ein Weg (es gibt endlose ..) wäre:

// leave Labels empty (btw, your original code seems to leave the 1st element empty) 
    // Lables = Mat(numberOfClass1 + numberOfClass2,1 , CV_32SC1); 

    // instead of 
    //Lables.push_back(Class1); 
    Lables.push_back(1.0f); 
    Lables.push_back(-1.0f); 

    // and instead of 
    //Lables.push_back(Class2); 
    Lables.push_back(-1.0f); 
    Lables.push_back(1.0f); 

    // then, before training, reshape to N x 2: 
    Labels = Labels.reshape(1, Labels.rows/2); 
    Data.convertTo(Data, CV_32FC1); 
    Lables.convertTo(Lables, CV_32FC1);