OpenCV SVM 在火车上抛出异常,“错误参数(只有一个类)”

Posted

技术标签:

【中文标题】OpenCV SVM 在火车上抛出异常,“错误参数(只有一个类)”【英文标题】:OpenCV SVM throwing exception on train, "Bad argument (There is only a single class)" 【发布时间】:2012-11-09 08:45:36 【问题描述】:

我被这个卡住了。

我正在尝试通过 OpenCV 功能 2d 框架进行一些对象分类,但在训练我的 SVM 时遇到了麻烦。

我能够提取词汇表并使用 BowKMeansTrainer 对它们进行聚类,但是在我从训练数据中提取特征以添加到训练器并运行 SVM.train 方法后,我得到了以下异常。

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

我尝试过修改字典大小,使用不同的训练器,确保我的矩阵类型正确(尽我所能,对 opencv 来说还是新手)。

有没有人看到这个错误或对如何修复它有任何见解?

我的代码如下所示:

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

【问题讨论】:

extractBOWDescriptor 到底是做什么的? trainingDatalabels 的大小是多少? extractBOWDescriptor 只是遍历文件列表,查找特征(使用 SURF 特征检测器),提取这些特征,将它们推送到 trainingData,然后将条目推送到标签。 训练数据大小为dictionary_size x 2,标签为number_of_images x 2 【参考方案1】:

根据错误,您的labels 似乎只包含一类数据。也就是说,trainingData 中的所有功能都具有相同的标签。

例如,假设您尝试使用 SVM 来确定图像是否包含猫。如果labels 中的每个条目都相同,那么...

您的所有训练图像都标记为“是的,这是一只猫” 或者,您的所有训练图像都标记为“不,这不是猫”。

SVM 会尝试分离两类(或有时更多)数据,因此如果您只提供一类数据,SVM 库就会报错。

要查看是否是这个问题,我建议添加一个打印语句来检查labels 是否仅包含一个类别。这里有一些代码可以做到这一点:

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

一旦您的extractBOWDescriptor() 将数据加载到labels,我假设labels 的大小为(trainingData.rows, trainingData.cols)。如果没有,这可能是个问题。

【讨论】:

以上是关于OpenCV SVM 在火车上抛出异常,“错误参数(只有一个类)”的主要内容,如果未能解决你的问题,请参考以下文章

Junit强制在方法调用上抛出异常

AVAudioRecorder 在 prepareToRecord 上抛出异常

为啥要尝试在已检查的异常上抛出未检查的异常? [复制]

OleDbCommand 在有效的命令文本上抛出异常

在wso2上抛出异常

HSQLDB 在 Windows 上运行,但在 Linux 上抛出异常