SVM write/load problems with kernels other than linear (Bug #4455)
Description
Within the implementation of the SVMs write and read methods (modules/ml/src/svm.cpp, lines 2022 ff and 2139 ff), the author makes the assumption, that support vector indices are not required in 2-class problems. That is probably correct if a linear kernel is used (i.e., when you have only one support vector). But with other kernels (in my case with an RBF kernel), the support vector indices are definitly required.
I've added a git diff where this questionable conditions are commented out. Without these lines everything works fine.
IMHO the lines should be removed.
History
Updated by Hyunjun Kim over 9 years ago
Hi, I was able to reproduce the error. I confirmed that cv::Algorithm::load() works well only with SVM::LINEAR kernel.
#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; int main(int, char**) { // Data for visual representation int width = 512, height = 512; Mat image = Mat::zeros(height, width, CV_8UC3); // Set up training data int labels[4] = {1, -1, -1, -1}; Mat labelsMat(4, 1, CV_32SC1, labels); 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<ml::SVM> svm = ml::SVM::create(); svm->setType(ml::SVM::C_SVC); svm->setKernel(SVM::INTER); // Algorithm::load() works well with SVM::LINEAR svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6)); // Train the SVM svm->train(ml::TrainData::create(trainingDataMat, ml::ROW_SAMPLE, labelsMat)); // Save and load SVM svm->save("ex_svm.xml"); svm= cv::Algorithm::load<ml::SVM>("ex_svm.xml"); // something is wrong 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 = svm->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 = svm->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); }
Updated by Maksim Shabunin over 9 years ago
- Assignee set to Maksim Shabunin
Updated by Maksim Shabunin over 9 years ago
Issue has been transferred to GitHub: https://github.com/Itseez/opencv/issues/5054