2012-11-09 32 views
5

Utknąłem na tym.Wyjątek wyrzucania OpenMV SVM w pociągu, "Zła argumentacja (istnieje tylko jedna klasa)"

Próbuję dokonać klasyfikacji obiektów za pomocą architektury OpenFV 2d, ale mam problemy z treningiem mojego SVM.

Jestem w stanie wyodrębnić słowników i grupować je za pomocą BowKMeansTrainer, ale po tym jak wyciągnę funkcje z danych treningowych, aby dodać do trenera i uruchomić metodę SVM.train, otrzymuję następujący wyjątek.

OpenCV Error: Bad argument (There is only a single class) in  cvPreprocessCategoricalResponses, file /home/tbu/prog/OpenCV-2.4.2/modules/ml/src /inner_functions.cpp, line 729 
terminate called after throwing an instance of 'cv::Exception' 
what(): /home/tbuchy/prog/OpenCV-2.4.2/modules/ml/src/inner_functions.cpp:729: error:  (-5) There is only a single class in function cvPreprocessCategoricalResponses 

Próbowałem modyfikowania rozmiaru słownika, używając różnych trenerów, zapewniając moje typy macierzy są poprawne (na miarę moich możliwości, wciąż nowe do OpenCV).

Czy widziałeś ten błąd lub masz jakieś wskazówki, jak to naprawić?

Mój kod wygląda następująco:

trainingPaths = getFilePaths(); 
extractTrainingVocab(trainingPaths); 
cout<<"Clustering..."<<endl; 
Mat dictionary = bowTrainer.cluster(); 
bowDE.setVocabulary(dictionary); 


Mat trainingData(0, dictionarySize, CV_32FC1); 
Mat labels(0, 1, CV_32FC1); 
extractBOWDescriptor(trainingPaths, trainingData, labels); 


//making the classifier 
CvSVM classifier; 
CvSVMParams params; 
params.svm_type = CvSVM::C_SVC; 
params.kernel_type = CvSVM::LINEAR; 
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); 

classifier.train(trainingData, labels, Mat(), Mat(), params); 
+0

Co dokładnie robi funkcja 'extractBOWDescriptor'? A jaki jest rozmiar "trainingData" i "labels"? – luhb

+0

extractBOWDescriptor po prostu przegląda listę plików, znajduje funkcje (za pomocą detektora funkcji SURF), wyodrębnia te funkcje, przesyła je do pliku trainingData, a następnie przesyła wpis do etykiet. – tuck

+0

rozmiar danych treningowych to dictionary_size x 2, a etykiety to number_of_images x 2 – tuck

Odpowiedz

10

podstawie błędu, to wygląda jak labels zawiera tylko jedną kategorię danych. Oznacza to, że wszystkie funkcje urządzenia trainingData mają tę samą etykietę.

Załóżmy na przykład, że próbujesz użyć maszyny SVM, aby określić, czy obraz zawiera kota, czy nie. Jeśli każdy wpis w labels jest taka sama, to albo ...

  • wszystkie zdjęcia szkoleniowe są oznaczone jako „tak to jest kot”
  • lub wszystkie obrazy szkoleniowe są oznaczone jako „nie, to nie jest kot. "

Maszyny SVM próbują oddzielić dwie (lub czasem więcej) klasy danych, więc biblioteka SVM skarży się, że podajesz tylko jedną klasę danych.

Aby sprawdzić, czy to jest problem, zalecam dodanie instrukcji print, aby sprawdzić, czy labels zawiera tylko jedną kategorię. Oto niektóre kodu, aby to zrobić:

//check: are the printouts all the same? 
for(int i=0; i<labels.rows; i++) 
    for(int j=0; j<labels.cols; j++) 
     printf("labels(%d, %d) = %f \n", i, j, labels.at<float>(i,j)); 

Po wczytaniu danych extractBOWDescriptor() do labels, jestem przy założeniu, że labels jest wielkości (trainingData.rows, trainingData.cols). Jeśli nie, może to stanowić problem.