I need to form HOGDescriptor::setSVMDetector()
input.
I compute descriptors with openCV then use libSVM to get model file. To form input i know that i need
But why do you want to classify this "by hand"? OpenCv has a classification routine called predict
, which uses found SVs' and alphas'
float response = SVM.predict(sampleMat);
If you really want to do it by yourself you would not only need SVs and alphas but also a kernel function used for training and comput
SUM alpha_i K( support_vector_i , data_point ) - rho
I am not sure whether it is possible to extract alphas "by hand" without extending the SVM class, as one can see in the sources - alphas are stored in the CvSVMDecisionFunc
structure:
struct CvSVMDecisionFunc
{
double rho;
int sv_count;
double* alpha;
int* sv_index;
};
while the only reference to this structure is in the protected
section:
protected:
(...)
CvSVMDecisionFunc* decision_func;
From the source code of svm.cpp
we can find, that it is only publically accesible through the save
routine. So some "hack" would be to save the model and extract alphas from there (it will be located in the "Decision function" section, written in human readable format).
The simplest extracion technique seems to extent the CvSVM
class and include method like
public:
CvSVMDecisionFunc* get_decision_function() { return decision_func; }
after clarification, that OP actually is trying to use externaly trained model in opencv - the easiest way is to convert the libsvm model crated by other method (libsvm, linearsvm etc.) into opencv compatible format and load it using read
method
void CvSVM::read( CvFileStorage* fs, CvFileNode* svm_node )
see source for more details.
Ok, it seems things are clear now. Alphas are the first column in my case. Since i had all of them equal to -1 or 1 (dunno why) in my test model, i thought these were labels.
Anyway, here is my parser (but you need to leave only SVs in file):
std::ifstream ifs("cars_model.model");
const int nsv = 90;
const int nfeatures = 144;
float rho = 12.5459;
char ts[4000] = ""; // !
std::vector<float> res(nfeatures,0);
std::vector<float> alphas;
Mat_<float> temp(nsv, nfeatures);
int c = 0;
std::cout << "Loading model file...\n";
for (int i=0; i<nsv; i++) {
float al = 0;
ifs >> al;
alphas.push_back(al);
for (int j=0; j<nfeatures; j++) {
float ind, s;
char junk;
ifs >> ind >> junk >> s;
temp.at<float>(c, j) = s;
//std::cout << f << ' ' << s << '\n';
}
c++;
}
ifs.close();
std::cout << "Computing primal form...\n";
for (int i=0; i<nsv; i++) {
float alpha = alphas[i];
for (int j=0; j<nfeatures; j++) {
res[j] += (temp.at<float>(i,j) * alpha);
}
}
//res.push_back(-rho);
std::ofstream ofs("primal.txt");
for (int i=0; i<res.size(); i++)
ofs << res[i] << ' ';
ofs.close();
And you know, it works. You can set rho as threshold of the detector.