Ask Your Question
0

How to choose index in getDecisionFunction for multiclass SVM

asked 2017-04-25 20:21:31 -0600

The objective is to train an SVM to classify up to 10 digits handwritten. So the SVM is a muticlass classifier.

As a result of the training, I have got a yml file which indicates the SVM has a total of 1009 support vectors, a class_count of 10 (because there are 10 digits in the training dataset). It all works very fine. But now I would like to use cv::ml::HOGDescripctor::detectMiltiscale(), in order to detect the digits in any other image or video. My problem arrises when I try to use the HOG::setSVMDetector function, since the SVM model I have just created is not compatible (I tried and it returned errors). So I search on the Internet the way to process the SVM support vectors so as to load it in the setSVMDetector function.

I have found loads of forums pointing to this function:

void get_svm_detector(const Ptr<SVM>& svm, vector< float > & hog_detector ){
// get the support vectors
Mat sv = svm->getSupportVectors();
const int sv_total = sv.rows;
// get the decision function
Mat alpha, svidx;
double rho = svm->getDecisionFunction(0, alpha, svidx);

CV_Assert( alpha.total() == 1 && svidx.total() == 1 && sv_total == 1 );
CV_Assert( (alpha.type() == CV_64F && alpha.at<double>(0) == 1.) ||
           (alpha.type() == CV_32F && alpha.at<float>(0) == 1.f) );
CV_Assert( sv.type() == CV_32F );
hog_detector.clear();

hog_detector.resize(sv.cols + 1);
memcpy(&hog_detector[0], sv.ptr(), sv.cols*sizeof(hog_detector[0]));
hog_detector[sv.cols] = (float)-rho;

}

But I have analize it, and the ASSERT this code have will launch an exception in runtime since the sv_total is not equal to 1 for my SVM model (it is equal to 1009). So I have to get rid of the ASSERTS, but now, the problem I with which index I should ue in the getDecisionFunction(0, alpha, svidx) since according to documentation, 0 is just for one or two-class models, but mine is 10-class model. I tried using 45, since there will be 45 different equations to solve, but it launches and error, I tried with 1, 2, and with 10, but I never finds the correct digits on my test image.

The code I implemented is the following (I try to use my variable names in Spanish, I love my language jejeje):

cv::Mat sv = svm->getSupportVectors();
const int sv_total = sv.rows;
cv::Mat alpha, svidx;
double rho = svm->getDecisionFunction(10, alpha, svidx);
vector<float> svmDetector;
svmDetector.clear();
svmDetector.resize(sv.cols + 1);
memcpy(&svmDetector[0], sv.ptr(), sv.cols * sizeof(svmDetector[0]));
svmDetector[sv.cols] = (float)-rho;

And I use the result, svmDetector, in this way with the rest:

hog.setSVMDetector(svmDetector);
hog.detectMultiScale(imagenPrueba, encontrados, 2);
cout << encontrados.size() << endl;
cv::Mat resultadoImagen;
vector<cv::Mat> grises;
grises.push_back(imagenPrueba);
grises.push_back(imagenPrueba);
grises.push_back(imagenPrueba);
cv::merge(grises, resultadoImagen);
for(int i=0;i<encontrados.size();i++)
    cv::rectangle(resultadoImagen, encontrados[i], cv::Scalar(0, 0, 255));

cv::imshow("RESULTADO", resultadoImagen);
cv::waitKey(0);

I have read a lot about it, but still cannot figure out how to ... (more)

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
1

answered 2017-04-25 23:27:20 -0600

berak gravatar image

updated 2017-04-25 23:31:58 -0600

if you trained your SVM for multi-class classification, you simply cannot use that for the HOGDescriptor, wich requires binary regression (and a single support vector).

so, keep your old SVM model around for later, but make another SVM training run using train_HOG.cpp and the SVR method(regression). you will also need a lot of negative (non-digit) images, all cropped to your desired winSize (20x20).

after that finished successfully, you can extract the single support vector for your HOGDescriptor, and try to detect digits with it.

good luck.

ps: please never use spanish language (it might as well be chinese...) for comments or variable names, you only make it terrible hard for anyone trying to help you.

edit flag offensive delete link more

Comments

Thank you very much... I will try according to your advice. I will also use English for my code... Thank you... I will let you know how it goes... Really... I am very grateful for how quickly your response arrived... I had just posted this question yesterday at night (in Peru it was about 9 p.m., and the time I am writing this is 12.23 midday).

luisb1393 gravatar imageluisb1393 ( 2017-04-26 12:23:34 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2017-04-25 20:21:31 -0600

Seen: 1,138 times

Last updated: Apr 25 '17