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 << "format" << 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 加载问题的主要内容,如果未能解决你的问题,请参考以下文章