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 {
    public:
    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 &lt; var_count; j++,v++)
           support_vector[j] += (-myalpha) * (*v);
       }
       support_vector.push_back(rho);
}

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.

7 comments

  1. Zed · October 26, 2015

    I guess this is for the OpenCV 2.4.x, looking for the same solution for 3.1.x, can’t seem to find any :/

    • meerkat · October 26, 2015

      Hello Zed, if I am not mistake, such problem does not appear in OpenCV 3.1.

  2. Pingback: Cıvata
  3. zelong · October 26

    Hi, I am struggling with this problem!!
    a couple of hours ago I trained a model that made me so happy, however, I found that I can not use these to set a SVM detector…..
    ———hog = cv2.HOGDescriptor()
    ———hog.setSVMDetector(‘svm_result_first_time.xml’)
    May I ask if there is a python-verision solution to solve it? (I am a IT beginner and do not code C++ ….sad…. ;( )
    Thanks!

    • meerkat · October 26

      What version of OpenCV are you using it?

      If I’m not mistaken, the new 3.1 or 3.2 version have solved this problem. Notice
      that now the SVM is in ml module.

  4. luke · October 26

    “I may get into more details on the process of creating an object detector in the future…”
    when is your next article coming, it’s been around 1.5 years ?

    • meerkat · 30 Days Ago

      Fair enough. Since this post we start to change from SVM/HOG detectors to
      CNN-based ones, in most cases.
      A good reference is the dlib MMOD:
      blog.dlib.net/2016/10/easily-create-high-quality-object.html

      Hope that helps.