Using SVM with HOG object detector in OpenCV

Hi everyone! For this post I will give you guys a quick and easy tip on how to use a trained SVM classifier on the HOG object detector from OpenCV. But first, one big shout-out to Dalal and Triggs for their great work on the HOG (Histogram of Oriented Gradients) descriptor! If you still don’t know about it, it is worth to check it out.

But back to the subject: why am I writing about this, since the OpenCV already have the implementations of both SVM and HoG which are quite easy to use? Well, they may be easy to use, but they don’t work very well together. The HoG object detector may be called with an SVM classifier, but not in the format that the SVM classifier from OpenCV works. That really means that if you train a SVM using HoG features, it is not possible to use it on the cv::HOGDescriptor::detect() function.

Fortunately, this is easy to solve: we just need to convert the trained SVM classifier to the Primal Form. This can be done by first creating the class PrimalSVM, which is an inheritance from the the class SVM:

class PrimalSVM: public cv::SVM {
    void getSupportVector(std::vector<float>& support_vector) const;

And then, to the magical part:

void PrimalSVM::getSupportVector(std::vector<float>& support_vector) const {
   int sv_count = get_support_vector_count();
   const CvSVMDecisionFunc* df = decision_func;
   const double* alphas = df[0].alpha;

   double rho = df[0].rho;
   int var_count = get_var_count();
   support_vector.resize(var_count, 0);

   for (unsigned int r = 0; r < (unsigned)sv_count; r++) {
       float myalpha = alphas[r];
       const float* v = get_support_vector(r);
       for (int j = 0; j < var_count; j++,v++)
           support_vector[j] += (-myalpha) * (*v);

Now you can use the PrimalSVM to train a classifier just like you would do with cv::SVM, and then call getSupportVector that will give you the support vectors in the format that cv::HOGDescriptor::setSVMDetector expects. And here you go! Now you can easily create an object detector entirely on OpenCV, and using only a few lines of codes :D! You may be surprised with the results that you can achieve when training with only a handful of images. Actually, I may get into more details on the process of creating an object detector in the future…

And last but not least, another shout-out goes to DXM from Stack Overflow, which was, as far as I know, the first one to propose this solution.


PS: For the ones with more attention to details, you will notice that the signals of rho and the alphas are not the same. This may be due to some characteristics of the (older) libSVM, which was the base of the SVM OpenCV code. I don’t quite understands this particular SVM implementation details, but I don’t lose sleep over it :P.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s