2013-06-01 7 views
6

Ho una cartella di positivi e un altro di immagini negativi in ​​formato JPG, e voglio formare una SVM in base a che le immagini, ho fatto il seguente, ma ricevo un errore:Come addestrare un SVM con opencv basato su un set di immagini?

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

Quando ho prova a eseguire quello che ottengo:

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) 

Non riesco ad allenare l'SVM, qualche idea? Grazie

+0

Sto cercando di classificare i piatti a base di segmets ho già ottenuto, il mio codice si basa su questo esempio: https: // GitHub .com/MasteringOpenCV/code/blob/master/Chapter5_NumberPlateRecognition/trainSVM.cpp –

+0

Hai provato a utilizzare CV_64F? E tu, per essere assolutamente sicuro, controlla qual è il tipo di "trainingData" prima che venga passato a CvSVM? – morynicz

+0

grazie @morynicz, 'CvType.typeToString (trainingData.type())' restituirebbe "CV_32FC3" .. Ho anche provato a convertire in CV_64F con lo stesso errore –

risposta

11

Supponendo che si sa cosa si sta facendo da rimodellare un'immagine e utilizzarla per addestrare SVM, la causa più probabile di questo è che il vostro

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

non riesce a leggere in realtà un'immagine, generando una matrice img con null data proprietà, che finirà per innescare la seguente nel codice OpenCV:

// 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"); 

Fondamentalmente train_data fallisce la prima condizione (essendo una matrice valido) piuttosto che in mancanza del secondo condizione (essendo di tipo CV_32FC1).

Inoltre, anche se la risagoma funziona sull'oggetto *this, si comporta come un filtro e il suo effetto non è permanente. Se viene utilizzato in una singola istruzione senza essere immediatamente utilizzato o assegnato a un'altra variabile, sarà inutile. Modificare le seguenti righe nel codice:

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

a:

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

Proprio come dice l'errore, è necessario modificare il tipo di matrice, dal tipo intero, probabilmente CV_8U, al punto mobile uno, CV_32F o CV_64F. Per farlo È possibile utilizzare cv::Mat::convertTo(). Here è un po 'di profondità e tipi di matrici.

+0

attualmente: 'trainingData.convertTo (trainingData, CvType.CV_32FC1); ' e le mie 'classi' sono popolate con [1] matrice CV_32FC1 –

+0

Oops. Scusa, non l'ho visto. – morynicz