SVM OpenCV c++ 预测只返回1

我相信我已经成功训练了一个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); // -- 测试图像的数量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输出: " << predictFloat << endl; }

但它只返回1。

enter image description here

哪里出了问题?


回答:

所以,词汇表已经创建好了(例如通过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;    // 对词汇表的响应    cv::Mat imgDescriptor;    bowide.compute(image, keypoints, imgDescriptor);    if(imgDescriptor.empty()) continue;    if(samples.empty())    {        samples.create(0, imgDescriptor.cols, imgDescriptor.type());    }    // 复制类样本和标签    std::cout << "添加 " << imgDescriptor.rows << " 个正样本。" << 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);// 对分类器做一些事情,比如将其保存到文件中

然后进行测试,让我们测试分类器:

for(auto& it : testDir){    cv::Mat image = cv::imread(it);    std::vector<cv::KeyPoint> keypoints;    detector->detect(image, keypoints);    if(keypoints.empty()) continue;    // 对词汇表的响应    cv::Mat imgDescriptor;    bowide.compute(image, keypoints, imgDescriptor);    if(imgDescriptor.empty()) continue;    float res = svm.predict(imgDescriptor, true);    std::cout << "- 预测结果: " << res << std::endl;}

它工作了吗?


更新#1:

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

这个示例对我来说很好地分类了可口可乐/百事可乐的瓶子。我还发布了二进制文件,以便你可以在你的数据库上尝试一下。希望它能工作 🙂

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注