How to use a custom SVM with HOGDescriptor, in Python

asked 2015-03-03 07:30:24 -0500

NebuK gravatar image

updated 2015-03-16 04:10:09 -0500

Hi,

this is a bit against the Idea here, but as its a topic i struggeled quite a bit, i’ll post it here anyways.

The problem is using a custom SVM in HOGDescriptor.detect[MultiScale]. Now, HOGDescriptor wants a float numpy array with mystery content for setSVMDetector(…). As to what the mystery-content is, we can look at the source: https://github.com/Itseez/opencv/blob...

Now the problem is how to get the list of SVs and rho — while CvSVM seems to have facilities for this, they’re not exposed to Python. This is where a dirty but working hack comes in: Saving the SVM to XML, then parsing that file to get the parameters. Something like:

<collect your training data in descs and labels in resps as usual>
import xml.etree.ElementTree as ET
svm = cv2.SVM()
svm.train_auto(descs, resps, None, None, params=svm_params, k_fold=5)

svm.save("svm.xml")
tree = ET.parse('svm.xml')
root = tree.getroot()
# now this is really dirty, but after ~3h of fighting OpenCV its what happens :-)
SVs = root.getchildren()[0].getchildren()[-2].getchildren()[0] 
rho = float( root.getchildren()[0].getchildren()[-1].getchildren()[0].getchildren()[1].text )
svmvec = [float(x) for x in re.sub( '\s+', ' ', SVs.text ).strip().split(' ')]
svmvec.append(-rho)
pickle.dump(svmvec, open("svm.pickle", 'w'))

And for using it:

img = cv2.imread(inp)
hog = cv2.HOGDescriptor((32,64), (16,16), (8,8), (8,8), 9)
svm = pickle.load(open("svm.pickle"))
hog.setSVMDetector( np.array(svm) )
del svm
found, w = hog.detectMultiScale(img)

this seems to work for me — so if anyone ever needs a custom SVM for HOG in OpenCV-Python without touching C++, i hope you can find this post!

Best Regards, hope this helps! Dario Ernst

edit retag flag offensive close merge delete

Comments

Thank you! I've been searching for a solution to training a SVM for the python HOG descriptors but I wasn't getting much.

You're a lifesaver!

crd319 gravatar imagecrd319 ( 2015-03-03 19:01:27 -0500 )edit

One question: what is ET? Guess some xml parser, but for completeness please add your import to the example. Thx!

Guanta gravatar imageGuanta ( 2015-03-04 07:36:12 -0500 )edit
1

Guanta: The ET stands for ElementTree, which is a very useful python XML parser. They typical import call is:

import xml.etree.ElementTree as ET.

crd319 gravatar imagecrd319 ( 2015-03-04 14:54:24 -0500 )edit

Dario: I tried implementing the code you suggested, but instead of getting actual targets I always seem to get a single return in the center of the image, regardless of the input. Do you know anything that might cause such a thing to happen?

crd319 gravatar imagecrd319 ( 2015-03-09 17:45:19 -0500 )edit

Added the import — crd319 was right, thanks for telling quicker than me :-). @crd319: What exactly happens with those svm vectors in the depths of HOG.detectMultiScale is a big mytho for me too — i fear i can not be of much help. A few things i would check is the strides, meanShift can get funky results too. Also, i had „glitches” with too small scales happening where i’d always get full-frame BBoxes. But … all of those i didn’t understand why. Sorry!

NebuK gravatar imageNebuK ( 2015-03-16 04:13:58 -0500 )edit

Questions. What is re in the line: 'svmvec = [float(x) for x in re.sub( '\s+', ' ', SVs.text ).strip().split(' ')]'?

ljcljc gravatar imageljcljc ( 2015-04-11 22:35:21 -0500 )edit

The regexpression submodule, s. https://docs.python.org/2/library/re....

Guanta gravatar imageGuanta ( 2015-04-13 06:02:57 -0500 )edit

Hi, I'm following your tutorial and it works(only training), when it came to testing, I got error at hog.setSVMDetector( np.array(svm) , " hog.setSVMDetector(np.array(svm)) cv2.error: C:\build\master_winpack-bindings-win32-vc14-static\opencv\modules\objdetect\src\hog.cpp:117: error: (-215) checkDetectorSize() in function cv::HOGDescriptor::setSVMDetector) " My system opencv : 3.2.0 os : windows 7 64 bit python : 2.7

adamaulia gravatar imageadamaulia ( 2017-04-26 06:11:38 -0500 )edit

@adamaulia, make sure that the winSize that you're using for your hog detector has the same dimensions as the training images you are using

mechaddict gravatar imagemechaddict ( 2017-08-23 19:19:45 -0500 )edit

@gravatar, I too got the same error as "penCV Error: Assertion failed (checkDetectorSize())", i had made sure that the winSize of hog is same dimension as the training image, and i also checked the size of np.array(svm) it shows 15553, while the trained descriptor of train image sample size is 15552, i think adding rho increased the length of np.array(svm), can you suggest a solution for the error.

krishnasai gravatar imagekrishnasai ( 2018-02-08 03:33:40 -0500 )edit