2013-06-01 2 views
6

Ich habe einen Ordner von Positiven und eine andere von Negativen Bilder im JPG-Format, und ich möchte ein SVM basierend trainieren auf, dass die Bilder, ich habe nach dem getan, aber ich erhalte eine Fehlermeldung:Wie trainiere ich eine SVM mit opencv basierend auf einer Reihe von Bildern?

Mat classes = new Mat(); 
Mat trainingData = new Mat(); 

Mat trainingImages = new Mat(); 
Mat trainingLabels = new Mat(); 

CvSVM clasificador; 

for (File file : new File(path + "positives/").listFiles()) { 
     Mat img = Highgui.imread(file.getAbsolutePath()); 
     img.reshape(1, 1); 

     trainingImages.push_back(img); 
     trainingLabels.push_back(Mat.ones(new Size(1, 1), CvType.CV_32FC1)); 
    } 

    for (File file : new File(path + "negatives/").listFiles()) { 
     Mat img = Highgui.imread(file.getAbsolutePath()); 
     img.reshape(1, 1); 

     trainingImages.push_back(img); 
     trainingLabels.push_back(Mat.zeros(new Size(1, 1), CvType.CV_32FC1)); 
    } 

    trainingImages.copyTo(trainingData); 
    trainingData.convertTo(trainingData, CvType.CV_32FC1); 
    trainingLabels.copyTo(classes); 

    CvSVMParams params = new CvSVMParams(); 
    params.set_kernel_type(CvSVM.LINEAR); 

    clasificador = new CvSVM(trainingData, classes, new Mat(), new Mat(), params); 

Als ich versuche zu laufen das erhalte ich:

OpenCV Error: Bad argument (train data must be floating-point matrix) in cvCheckTrainData, file ..\..\..\src\opencv\modules\ml\src\inner_functions.cpp, line 857 
Exception in thread "main" CvException [org.opencv.core.CvException: ..\..\..\src\opencv\modules\ml\src\inner_functions.cpp:857: error: (-5) train data must be floating-point matrix in function cvCheckTrainData 
] 
    at org.opencv.ml.CvSVM.CvSVM_1(Native Method) 
    at org.opencv.ml.CvSVM.<init>(CvSVM.java:80) 

Ich kann es nicht schaffen, die SVM zu trainieren, keine Ahnung? Danke

+0

Ich versuche, Platten zu klassifizieren basierend auf segmets ich bereits erhalten, ist mein Code auf der Basis dieses Beispiel: https: // Github .com/MasteringOpenCV/code/blob/master/Kapitel5_NumberPlateRecognition/trainSVM.cpp –

+0

Haben Sie versucht, CV_64F zu verwenden? Und haben Sie, um absolut sicher zu sein, kurz vor der Weitergabe an CvSVM überprüft, welche Art von 'Trainingsdaten' vorliegt? – morynicz

+0

danke @morynicz, 'CvType.typeToString (trainingData.type())' würde "CV_32FC3" zurückgeben .. Auch versucht, CV_64F mit dem gleichen Fehler –

Antwort

11

Unter der Annahme, dass Sie wissen, was Sie durch Umformen ein Bild machen und die Verwendung dieser SVM zu trainieren, die wahrscheinlichste Ursache dafür ist, dass Ihr

Mat img = Highgui.imread(file.getAbsolutePath()); 

nicht tatsächlich um ein Bild zu lesen, um eine Matrix zu erzeugen img mit null data Eigenschaft, die in dem Code OpenCV schließlich auslösen folgend wird:

// check parameter types and sizes 
if(!CV_IS_MAT(train_data) || CV_MAT_TYPE(train_data->type) != CV_32FC1) 
    CV_ERROR(CV_StsBadArg, "train data must be floating-point matrix"); 

Grundsätzlich train_data nicht die erste Bedingung (eine gültige Matrix ist), anstatt sie nicht die zweite Bedingung (vom Typ CV_32FC1).

Darüber hinaus funktioniert, obwohl Umformen auf dem *this Objekt funktioniert, es wie ein Filter und seine Wirkung ist nicht dauerhaft. Wenn es in einer einzelnen Anweisung verwendet wird, ohne sofort verwendet oder einer anderen Variablen zugewiesen zu werden, ist es nutzlos. Ändern Sie die folgenden Zeilen im Code:

img.reshape(1, 1); 
trainingImages.push_back(img); 

zu:

trainingImages.push_back(img.reshape(1, 1)); 
0

Genau wie der Fehler sagt, müssen Sie den Typ Ihrer Matrix ändern, vom Integer-Typ, wahrscheinlich CV_8U, zum Gleitkomma, CV_32F oder CV_64F. Um es zu tun Sie können cv::Mat::convertTo() verwenden. Here ist ein bisschen über Tiefen und Arten von Matrizen.

+0

tatsächlich zu konvertieren ich: 'trainingData.convertTo (trainingData, CvType.CV_32FC1); " und meine 'Klassen' ist mit [1] CV_32FC1 Einsen Matrix –

+0

Oops aufgefüllt. Tut mir leid, habe das nicht gesehen. – morynicz