Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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);
like image 871
tuck Avatar asked Nov 09 '12 08:11

tuck


1 Answers

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.

like image 142
solvingPuzzles Avatar answered Oct 21 '22 10:10

solvingPuzzles