How to use a custom SVM with HOGDescriptor, in Python [closed]
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
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!
One question: what is ET? Guess some xml parser, but for completeness please add your import to the example. Thx!
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.
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?
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!
Questions. What is re in the line: 'svmvec = [float(x) for x in re.sub( '\s+', ' ', SVs.text ).strip().split(' ')]'?
The regexpression submodule, s. https://docs.python.org/2/library/re....
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, make sure that the winSize that you're using for your hog detector has the same dimensions as the training images you are using
@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.