Ask Your Question

Revision history [back]

How to use a custom SVM with HOGDescriptor, in Python

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/master/samples/cpp/train_HOG.cpp#L24

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>
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

How to use a custom SVM with HOGDescriptor, in Python

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/master/samples/cpp/train_HOG.cpp#L24

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