c++ - openCV c++ : Problems working with CvBoost (Adaboost classifer)

标签 c++ opencv adaboost

我正在创建一个应用程序,用于对城市环境图像中的人物进行分类。

我通过以下方式训练分类器:

int main (int argc, char **argv)
{

/* STEP 2. Opening the file */
//1. Declare a structure to keep the data
  CvMLData cvml;
//2. Read the file
  cvml.read_csv ("directory/train_rand.csv");
//3. Indicate which column is the response
  cvml.set_response_idx (0);

/* STEP 3. Splitting the samples */
//1. Select 4000 for the training
  CvTrainTestSplit cvtts (4000, true);
//2. Assign the division to the data
  cvml.set_train_test_split (&cvtts);

  printf ("Training ... ");
/* STEP 4. The training */
//1. Declare the classifier
  CvBoost boost;
//2. Train it with 100 features
  boost.train (&cvml, CvBoostParams (CvBoost::REAL,100, 0, 1, false, 0),
           false);

/* STEP 5. Calculating the testing and training error */
// 1. Declare a couple of vectors to save the predictions of each sample
  std::vector<float> train_responses, test_responses;
// 2. Calculate the training error
  float fl1 = boost.calc_error (&cvml, CV_TRAIN_ERROR, &train_responses);
// 3. Calculate the test error
  float fl2 = boost.calc_error (&cvml, CV_TEST_ERROR, &test_responses);

  cout<<"Error train: "<<fl1<<endl;

  cout<<"Error test: "<<fl2<<endl;

/* STEP 6. Save your classifier */
// Save the trained classifier
  boost.save ("./trained_boost_4000samples-100ftrs.xml", "boost");

  return 0;
}

train_rand.csv 是一个文件,其中第一列是类别。其余的列将是问题的特征。例如,我可以使用三个功能。它们各自代表图像中每个像素的红色、蓝色和绿色的平均值。所以我的 csv 文件应该如下所示。请注意,在第一列中我使用了一个字符,因此 OpenCV 将其识别为一个类别。

B,124.34,45.4,12.4
B,64.14,45.23,3.23
B,42.32,125.41,23.8
R,224.4,35.34,163.87
R,14.55,12.423,89.67
...

对于我的实际问题,我使用了 100 个特征和 8000 个样本。我用一半的数据训练分类器,并用其余的数据进行测试。

训练后,我得到的测试误差约为 5%(这对于只有 100 个特征来说已经相当不错了)。

现在我想在新数据中使用分类器:

CvBoost boost

boost.load("directory/trained_boost_4000samples-100ftrs.xml");

float x = boost.predict(SampleData,Mat(),Range::all(),false,false);
cout<<x;

我在数千个样本上运行此代码,它总是输出相同的值,即 2。我真的不明白我在这里做错了什么,但即使我训练过如果以错误的方式对分类器进行分类,它不会以同样的方式 100% 地分类,而且,我之前计算的测试误差表明分类器应该可以正常工作。

困扰我的一件事是 SampleData 必须具有与我用来训练的样本相同数量的列。问题是,用于训练的数据有 100 列 + 1 个响应,如果我尝试仅使用 100 个特征运行分类器,它会抛出一个异常,指出大小不匹配。如果我运行具有 101 个特征的分类器(这绝对是任意的),它会起作用,但结果没有任何意义。

有人可以帮我解决这个问题吗?预先感谢!

问候

最佳答案

我通过调整 code from the SVM documentation 设法让 adaBoost 正常工作。唯一的技巧是确保有足够的样本数据 (>= 11)。

来自the blog where your code is copied from :

NOTE: For a very strange reason the OpenCV implementation does not work with less than 11 samples.

// Training data
float labels[11] = { 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0};
Mat labelsMat(11, 1, CV_32FC1, labels);

float trainingData[11][2] = {
    {501, 10}, {508, 15},
    {255, 10}, {501, 255}, {10, 501}, {10, 501}, {11, 501}, {9, 501}, {10, 502}, {10, 511}, {10, 495} };
Mat trainingDataMat(11, 2, CV_32FC1, trainingData);

// Set up SVM's parameters
CvSVMParams params;
params.svm_type    = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

// Train a SVM classifier
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

// Train a boost classifier
CvBoost boost;
boost.train(trainingDataMat,
            CV_ROW_SAMPLE,
            labelsMat);

// Test the classifiers
Mat testSample1 = (Mat_<float>(1,2) << 251, 5);
Mat testSample2 = (Mat_<float>(1,2) << 502, 11);

float svmResponse1 = SVM.predict(testSample1);
float svmResponse2 = SVM.predict(testSample2);

float boostResponse1 = boost.predict(testSample1);
float boostResponse2 = boost.predict(testSample2);

std::cout << "SVM:   " << svmResponse1 << " " << svmResponse2 << std::endl;
std::cout << "BOOST: " << boostResponse1 << " " << boostResponse2 << std::endl;

// Output:
//  > SVM:   -1 1
//  > BOOST: -1 1

关于c++ - openCV c++ : Problems working with CvBoost (Adaboost classifer),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15869954/

相关文章:

.net - 为 OCR 连接附近的点(询问一些提示,例如使用形态学操作)

python - 在 OpenCv、Python 中保存相同图像时无法获得与原始图像相同的颜色

c++ - 如何使用Opencv轮廓单向描述线点

machine-learning - Adaboost 与神经网络

machine-learning - weka AdaBoost 没有改善结果

c++ - 有关实现游戏多人游戏的信息?

c++ - 改进极小极大算法

c++ - 与虚拟析构函数相比,shared_ptr 用于子类析构的运行时开销

c++ - 确定文件是否可以在 C++ 中创建/不是只读

python - 如何解释 sklearn.tree.tree_tree.value 属性的(意外)值?