I want to train a new HoG classifier for heads and shoulders using OpenCV 3.x Python bindings. What is my pipeline for extracting features, training an SVM, and then running it on the test database?
There appears to be such a pipeline for C++ here: SVM classifier based on HOG features for "object detection" in OpenCV and here: https://github.com/DaHoC/trainHOG/wiki/trainHOG-Tutorial . For Python, there's a description of how to extract a HOG feature set here: Get HOG image features from OpenCV + Python? . However, that only works for OpenCV 2.x, because you cannot initialize a classifier with _winSize
and other such variables anymore. Also, that's only for feature extraction, not training or detection using the newly trained classifier.
The output of cv2.HOGdescriptor()
does have an svmDetector
parameter, but I don't know how to use it because OpenCV 3.x does not come with Python documentation, and OpenCV 2.x only lists HoG in its GPU module, even though there is a CPU implementation.
Is it possible to see an end-to-end pipeline and an explanation for some of the parameters?
Currently I have the same issue and I have seen the following document from OpenCV:
OCR of Hand-written Data using SVM
Where you can find part of your answer:
deskewed = [map(deskew,row) for row in train_cells]
hogdata = [map(hog,row) for row in deskewed]
trainData = np.float32(hogdata).reshape(-1,64)
responses = np.float32(np.repeat(np.arange(10),250)[:,np.newaxis])
svm = cv2.ml.SVM_create()
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setType(cv2.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)
svm.train(trainData, cv2.ml.ROW_SAMPLE, responses)
svm.save('svm_data.dat')
That is I am working with. Once I solved it, I will update the answer. But at this moment I hope it help you.
............................................................................
You can find an example called digits.py on this opencv directory:
\opencv\sources\samples\python
Depending on your opencv version, there are some differences in methods for SVM class. This is an example for opencv 3.1.
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_RBF) # cv2.ml.SVM_LINEAR
# svm.setDegree(0.0)
svm.setGamma(5.383)
# svm.setCoef0(0.0)
svm.setC(2.67)
# svm.setNu(0.0)
# svm.setP(0.0)
# svm.setClassWeights(None)
svm.train(samples_train, cv2.ml.ROW_SAMPLE, labels_train)
resp = svm.predict(samples_test)[1].ravel()
print resp, labels_test
err = (labels_test != resp).mean()
print('error: %.2f %%' % (err*100))
confusion = np.zeros((10, 10), np.int32)
for i, j in zip(labels_test, resp):
confusion[i, j] += 1
print('confusion matrix:')
print(confusion)
print()
............................................................................
Finally I got it on this way:
samples = []
labels = []
# Get positive samples
for filename in glob.glob(os.path.join(positive_path, '*.jpg')):
img = cv2.imread(filename, 1)
hist = hog(img)
samples.append(hist)
labels.append(1)
# Get negative samples
for filename in glob.glob(os.path.join(negative_path, '*.jpg')):
img = cv2.imread(filename, 1)
hist = hog(img)
samples.append(hist)
labels.append(0)
# Convert objects to Numpy Objects
samples = np.float32(samples)
labels = np.array(labels)
# Shuffle Samples
rand = np.random.RandomState(321)
shuffle = rand.permutation(len(samples))
samples = samples[shuffle]
labels = labels[shuffle]
# Create SVM classifier
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_RBF) # cv2.ml.SVM_LINEAR
# svm.setDegree(0.0)
svm.setGamma(5.383)
# svm.setCoef0(0.0)
svm.setC(2.67)
# svm.setNu(0.0)
# svm.setP(0.0)
# svm.setClassWeights(None)
# Train
svm.train(samples, cv2.ml.ROW_SAMPLE, labels)
svm.save('svm_data.dat')
Regards.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With