OpenCV SVM throwing exception on train, "Bad argument (There is only a single class)"
Asked Answered
K

1

5

I'm stuck on this one.

I am trying to do some object classification through OpenCV feature 2d framework, but am running into troubles on training my SVM.

I am able to extract vocabularies and cluster them using BowKMeansTrainer, but after I extract features from training data to add to the trainer and run SVM.train method, I get the following exception.

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

I have tried modifying dictionary size, using different trainers, ensuring my matrix types are correct (to the best of my ability, still new to opencv).

Has any seen this error or have any insight on how to fix it?

My code looks like this:

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);
Kyat answered 9/11, 2012 at 8:45 Comment(3)
What does extractBOWDescriptor do exactly? And what is the size of trainingData and labels?Safelight
extractBOWDescriptor just itereates through a list of files, finds features (using SURF feature detector), extracts those features, pushs them to trainingData and then pushs an entry to labels.Kyat
the size of training data is dictionary_size x 2 and labels is number_of_images x 2Kyat
Z
10

Based on the error, it looks like your labels only contains one category of data. That is, all of the features in your trainingData have the same label.

For example, say you're trying to use the SVM to determine whether an image contains a cat or not. If every entry in the labels is the same, then either...

  • all your training images are labeled as "yes this is a cat"
  • or, all your training images are labeled as "no, this is not a cat."

SVMs try to separate two (or sometimes more) classes of data, so the SVM library complains if you only only provide one class of data.

To see if this is the problem, I recommend adding a print statement to check whether labels only contains one category. Here's some code to do this:

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

Once your extractBOWDescriptor() loads data into labels, I'm assuming that labels is of size (trainingData.rows, trainingData.cols). If not, this could be a problem.

Zoolatry answered 10/11, 2012 at 5:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.