opencv 3 (C++) 自动训练的 SVM 加载问题

Posted

技术标签:

【中文标题】opencv 3 (C++) 自动训练的 SVM 加载问题【英文标题】:opencv 3 (C++) auto trained SVM loading issue 【发布时间】:2015-12-28 01:55:07 【问题描述】:

我正在使用 SVM 进行分类,我在一个项目中进行训练,在另一个项目中进行测试,以便只训练一次。

TRAINing部分如下:

classifier->trainAuto(trainData);
string svmDir = "/File/Dir/";
string svmFile = "svmClassifier.xml";
classifier->save(svmDir+svmFile);

测试部分是:

string svmDir = "/File/Dir/";
string svmFile = "svmClassifier.xml";
Ptr<ml::SVM> classifier = ml::SVM::load<ml::SVM>(svmDir+svmFile);
...
float response = classifier->predict(tDescriptor);

预测结果全为 0(全为负数)。但是当我在训练项目中的 SVM 训练之后立即进行预测时,预测是正确的(我在“预测”之前使用了断点,传递给预测的 tDescriptor 在两个项目中都是相同的。) 所以我认为保存和加载过程可能有问题..

自动训练的 SVM 可以保存和加载吗?还是必须在statModel中?

感谢您的帮助!

【问题讨论】:

保存后尝试添加这些行:cv::FileStorage fs(svmDir+svmFile, cv::FileStorage::APPEND); fs &lt;&lt; "format" &lt;&lt; 3; 。可能和here是同一个问题 @Miki 嗨,我添加了那行并重新训练/重新测试,但它对我不起作用 这只是一个猜测。事实上,这个问题是针对随机树的,而不是 svm。如果您发布带有虚拟数据的 mvce,就像我发布的问题一样,我们可以检查 @Miki 感谢您的回复!这种情况下svm的参数是自己自动选择的,不会出现编译错误,真不知道还要包括什么? 复制另一个问题中的代码,并用你的替换随机树的东西。如果你能设置一个我们可以复制&粘贴&运行的代码,你会很快得到答案。 【参考方案1】:

流动代码取自 Introduction to Support Vector Machines for open CV 并进行了修改。我从对象 svmOld“trainedSVM.xml”中保存了 SVM 参数。然后加载 XML 文件并使用它们创建对象 svmNew。

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
using namespace std;

int main()




    // Data for visual representation
    int width = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // Set up training data
    int Lable[] =  1, -1, -1, -1 ;
    Mat labelsMat(4, 1, CV_32S, Lable);


    float trainingData[4][2] =   501, 10 , 255, 10 , 501, 255 , 10, 501  ;
    Mat trainingDataMat(4, 2, CV_32FC1, trainingData);

    // Set up SVM's parameters
    Ptr<SVM> svmOld = SVM::create();
    svmOld->setType(SVM::C_SVC);
    svmOld->setKernel(SVM::LINEAR);
    svmOld->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

    // Train the SVM with given parameters
    Ptr<TrainData> td = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
    svmOld->train(td);
    //same svm 
    svmOld->save("trainedSVM.xml");


    //Initialize SVM object   
    Ptr<SVM> svmNew = SVM::create();
    //Load Previously saved SVM from XML 

    svmNew = SVM::load<SVM>("trainedSVM.xml");



    Vec3b green(0, 255, 0), blue(255, 0, 0);
    // Show the decision regions given by the SVM
    for (int i = 0; i < image.rows; ++i)
        for (int j = 0; j < image.cols; ++j)
        
            Mat sampleMat = (Mat_<float>(1, 2) << j, i);
            float response = svmNew->predict(sampleMat);

            if (response == 1)
                image.at<Vec3b>(i, j) = green;
            else if (response == -1)
                image.at<Vec3b>(i, j) = blue;
        

    // Show the training data
    int thickness = -1;
    int lineType = 8;
    circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);
    circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);

    // Show support vectors
    thickness = 2;
    lineType = 8;
    Mat sv = svmNew->getSupportVectors();

    for (int i = 0; i < sv.rows; ++i)
    
        const float* v = sv.ptr<float>(i);
        circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
    

    imwrite("result.png", image);        // save the image

    imshow("SVM Simple Example", image); // show it to the user
    waitKey(0);
    return(0);

【讨论】:

您好,svm在线性时可以正确保存和加载,但是在使用非线性内核时会出现一些问题。这是由于在读取过程中保存的 SVM 中没有正确获取格式

以上是关于opencv 3 (C++) 自动训练的 SVM 加载问题的主要内容,如果未能解决你的问题,请参考以下文章

SVM 训练 C++ OpenCV

如何在 Python 中使用 OpenCV 3.0 中的 HOG 功能训练 SVM 分类器?

C++ OpenCV SVM 预测不工作

Opencv 3 SVM 训练

Opencv 3 SVM 训练

将经过训练的 SVM 从 scikit-learn 导入到 OpenCV