【问题标题】:SVM OpenCV c++ Predict returning nothing but 1'sSVM OpenCV c++ Predict 只返回 1
【发布时间】:2015-04-20 19:57:43
【问题描述】:

我相信我已经成功训练了一个SVM,但是当我尝试用它进行预测时,输出完全是 1。

我的训练代码如下所示:

for(size_t i = 0; i < (testPosArraySize); i++){
    testGivenImg = imread(imagePosDir[i]);
    detector->detect(testGivenImg, testKeypointsPos);
    bowDE.compute(testGivenImg, testKeypointsPos, testFeaturesPos);
    testFeaturesPos.reshape(1, 1);
    testFeaturesVec.push_back(testFeaturesPos);
}
for(size_t i = 0; i < (testNegaArraySize); i++){
    testGivenImg = imread(image[i]);
    detector->detect(testGivenImg, testKeypointsNega);
    bowDE.compute(testGivenImg, testKeypointsNega, testFeaturesNega);
    testFeaturesNega.reshape(1, 1);
    testFeaturesVec.push_back(testFeaturesNega);
}

Mat labels(numSamples, 1, CV_32F);
labels.rowRange(0, testPosArraySize).setTo(1);
labels.rowRange(testPosArraySize + 1, numSamples).setTo(-1);
SVM.model.train(fileTestFeat, labels, Mat(), Mat(), SVMParams());

我的预测代码如下所示:

vector<Mat> predictMatVec(predictArraySize); // -- amount of testing images

for(size_t i = 0; i < (predictArraySize); i++){
    predictImg = imread(imageNegaDir[i]);
    detector->detect(predictImg, predictKeypoints);
    bowDE.compute(predictImg, predictKeypoints, predictFeatures);
    predictFeatures.reshape(1, 1);
    predictMatVec[i].push_back(predictFeatures);

    Mat predictMat = Mat(predictMatVec);
    float* predictFloat1D = (float*)predictMat.data;
    Mat predictMat1D(1, fileTestFeat.cols, CV_32FC1, predictFloat1D);
    float predictFloat = model.predict(predictMat1D);
    cout << " -- SVM output: " << predictFloat << endl; 
}

但它只返回 1。

这有什么问题?

【问题讨论】:

  • 如果将模型应用到训练数据库会发生什么?你能“分离”训练数据库吗?
  • 我看不出我会从中获得什么信息?我不关注你的第二个问题......
  • 您将predict() 与默认returnDFVal 一起使用,因此该函数返回一个类标签(分类)或估计的函数值(回归)。我认为你的 1 是类标签,所以你所有的样本都被归类为 1-label 类的元素。如果您对训练数据库执行预测,那么我希望看到其他标签。如果预测对训练数据库不起作用,那么您的训练是错误的。
  • 设置它运行用于训练的图像,只是停止工作......我如何制作一个 2 标签类?我以为我已经

标签: c++ opencv machine-learning svm image-recognition


【解决方案1】:

所以,词汇表已经创建(例如,BOWKMeansTrainer),你开始训练你的 SVM 分类器,对吧?

此时,您有一个特征检测器、提取器、匹配器和一个 BOW 图像描述符提取器(使用视觉词袋计算图像描述符),例如:

cv::Ptr<cv::FeatureDetector> detector = cv::FeatureDetector::create("SURF");
cv::Ptr<cv::DescriptorExtractor> extractor = cv::DescriptorExtractor::create("SURF");
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce ");

cv::BOWImgDescriptorExtractor bowide(extractor, matcher);
bowide->setVocabulary(vocabulary);

首先,我们需要搜索直方图的训练集:

cv::Mat samples;
cv::Mat labels(0, 1, CV_32FC1);

for(auto& it : imagePosDir)
{
    cv::Mat image = cv::imread(it);

    std::vector<cv::KeyPoint> keypoints;
    detector->detect(image, keypoints);

    if(keypoints.empty()) continue;

    // Responses to the vocabulary
    cv::Mat imgDescriptor;
    bowide.compute(image, keypoints, imgDescriptor);

    if(imgDescriptor.empty()) continue;

    if(samples.empty())
    {
        samples.create(0, imgDescriptor.cols, imgDescriptor.type());
    }

    // Copy class samples and labels
    std::cout << "Adding " << imgDescriptor.rows << " positive sample." << std::endl;
    samples.push_back(imgDescriptor);

    cv::Mat classLabels = cv::Mat::ones(imgDescriptor.rows, 1, CV_32FC1);
    labels.push_back(classLabels);
}

imagePosNeg 执行相同操作,但classLabels 将具有零值,例如:

...
cv::Mat classLabels = cv::Mat::zeros(imgDescriptor.rows, 1, CV_32FC1);
labels.push_back(classLabels);
...

注意我是如何构建样本和标签的,我用标签“1”标记了正样本,然后用标签“0”标记了负样本。所以我们在samples 中有每个类的训练数据(这里是正面和负面)。让我们开始训练吧:

cv::Mat samples_32f; 
samples.convertTo(samples_32f, CV_32F);

CvSVM svm; 
svm.train(samples_32f, labels);
// Do something with the classifier, like saving it to file

然后测试让我们开始测试分类器:

for(auto& it : testDir)
{
    cv::Mat image = cv::imread(it);

    std::vector<cv::KeyPoint> keypoints;
    detector->detect(image, keypoints);

    if(keypoints.empty()) continue;

    // Responses to the vocabulary
    cv::Mat imgDescriptor;
    bowide.compute(image, keypoints, imgDescriptor);

    if(imgDescriptor.empty()) continue;

    float res = svm.predict(imgDescriptor, true);

    std::cout << "- Result of prediction: " << res << std::endl;
}

有效吗?


更新 #1:

这里我做了一个关于OpenCV 3.0下BOW+SVM的简单例子: https://github.com/bkornel/OpenCV_BOW_SVM/blob/master/main.cpp

这很适合对可口可乐/百事可乐瓶进行分类。我还发布了二进制文件,以便您可以尝试使用您的数据库。希望它有效:)

【讨论】:

  • 看起来是?输出由-1-0.9xxxxx 组成,对吗?一些0.8xxxxxx 显然是任何一位数)- 将前 4 个图像更改为正训练集中的前 4 个图像,输出为 -1 - -0.993832 - -0.981426 - @987654339 @
  • 它是 2 类分类,predict() 返回决策函数值,即到边距的有符号距离。如果您想知道标签,请将returnDFVal 设置为false,即float res = svm.predict(imgDescriptor, false);
  • 你知道的越多!好吧,我将其更改为false,并且前20个输出再次全部为1,但是速度很慢,所以我输入了If,所以它只会写出floats不返回1's(保存筛选所有的)
  • 它运行了,但输出不应该有变化,即不仅仅是1's? (就像我最初的问题一样)
  • 你应该看到负数为零,正数为一
猜你喜欢
  • 2018-06-02
  • 1970-01-01
  • 2016-02-28
  • 2013-01-29
  • 2013-08-21
  • 2015-04-18
  • 2015-07-11
  • 2015-07-04
  • 1970-01-01
相关资源
最近更新 更多