问题
I'm using SVM to do classification, and I do the training in one project, testing in another, in order to train only once.
The TRAINing part is as follows:
classifier->trainAuto(trainData);
string svmDir = "/File/Dir/";
string svmFile = "svmClassifier.xml";
classifier->save(svmDir+svmFile);
And the TESTing part is:
string svmDir = "/File/Dir/";
string svmFile = "svmClassifier.xml";
Ptr<ml::SVM> classifier = ml::SVM::load<ml::SVM>(svmDir+svmFile);
...
float response = classifier->predict(tDescriptor);
The prediction gives all 0s (all negative). But when I do the prediction right after the SVM training in the Training Project, the predictions are correct (I used breakpoint before "predict", the tDescriptor passed to predict are the same in both projects.) So I think there might be something wrong with saving and loading process..
Can the auto trained SVM be saved and loaded? Or it must be in the statModel?
Thanks for help!
回答1:
The flowing code was taken and modified from Introduction to Support Vector Machines for open CV. I saved the SVM parameters from the object svmOld "trainedSVM.xml". Then loaded the XML file and used them to create the object 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);
}
来源:https://stackoverflow.com/questions/32863392/opencv-3-c-auto-trained-svm-loading-issue