13

So I have a matrix with my sample images (all turned into vectors) which was run trough PCA/LDA, and a vector which denotes the class each images belongs to. Now I want to use the OpenCV SVM class to train my SVM (I am using Python, OpenCV 2.3.1). But I have a problem with defining the parameters:

test = cv2.SVM()
test.train(trainData, responses, ????)

I am stuck on how to define the type of SVM (linear, etc.) and other stuff. In C++ you define it by stating for example: svm_type=CvSVM::C_SVC...Python doesn't have that. C++ also has a special class to store these parameters -> CvSVMParams. Can someone give me an example of this in Python? Like defining the SVM type, gamma, etc.

The 2.3.1 docs says it like this:

Python: cv2.SVM.train(trainData, responses[, varIdx[, sampleIdx[, params]]]) → retval

What are varIdx and sampleIdx, and how to define the params?

Veles
  • 1,512
  • 4
  • 14
  • 28
  • 1
    I am currently reading docs, but meanwhile, you can use alternative solution: convert your matrix to numpy and use sk-learn for machine learning task. – timgluz Jan 01 '12 at 00:23
  • Hi! Try those examples: https://code.ros.org/svn/opencv/trunk/opencv/samples/python2/letter_recog.py – timgluz Jan 01 '12 at 00:59
  • timgluz THX that's exactly what I was looking for...could you please copy the SVM part from the link in an answer so I can accept it (so that other people can find the answer right away and u get credit)...the SVM part is from line 79 to 91... – Veles Jan 01 '12 at 10:41

2 Answers2

20

To use OpenCV machine learning algorithms, you have to write some wrapper classes:

1. First parent class

class StatModel(object):
    '''parent class - starting point to add abstraction'''    
    def load(self, fn):
        self.model.load(fn)
    def save(self, fn):
        self.model.save(fn)

2. Finally SvM wrapper:

class SVM(StatModel):
    '''wrapper for OpenCV SimpleVectorMachine algorithm'''
    def __init__(self):
        self.model = cv2.SVM()

    def train(self, samples, responses):
        #setting algorithm parameters
        params = dict( kernel_type = cv2.SVM_LINEAR, 
                       svm_type = cv2.SVM_C_SVC,
                       C = 1 )
        self.model.train(samples, responses, params = params)

    def predict(self, samples):
        return np.float32( [self.model.predict(s) for s in samples])

3.Example usage:

import numpy as np
import cv2

samples = np.array(np.random.random((4,2)), dtype = np.float32)
y_train = np.array([1.,0.,0.,1.], dtype = np.float32)

clf = SVM()
clf.train(samples, y_train)
y_val = clf.predict(samples)

Setting parameters

Setting parameters is simple - just write a dictionary that holds the parameters as keys. You should look original documentation to see all possible parameters and allowed values: http://opencv.itseez.com/modules/ml/doc/support_vector_machines.html#cvsvmparams

Yes, possible values for svm_type and kernel_type are in C++, but there is easy way to convert those constants into Python representation, for example CvSVM::C_SVC is written as cv2.SVM_C_SVC in Python.

Prelude To get more wrappers for machine learning algorithms, look into letter-recog.py example in your opencv examples on disk or open url of OpenCV repository: https://github.com/Itseez/opencv/tree/master/samples/python2

rafaelcosman
  • 2,569
  • 7
  • 23
  • 39
timgluz
  • 1,054
  • 11
  • 14
  • This looks very promising. I have registered at ros.org but when I enter my name and password for the link to python samples, I get this dialog box and cannot get past it. "To view this page, you must log in to this area on code.ros.org:443:" Is there a special name/password for this svn area, beyond my own? – zerowords Nov 12 '12 at 15:29
  • Hi! Sadly they cancelled public view for this repository. I'll post some workaround very soon. – timgluz Nov 13 '12 at 08:57
  • This code works only for OpenCV 2. In OpenCV 3, the SVM functions have been moved from cv2 to cv2.ml, and to create the model, the new function is cv2.ml.SVM_create() – jpyams Apr 25 '17 at 13:35
1

Adapted from timgluz version, but uses "train_auto" instead of "train". cv2 will find parameters "C", "gamma", ... for us.

import cv2
import numpy as np

class Learn:
    def __init__(self, X, y):
        self.est = cv2.SVM()
        params = dict(kernel_type=cv2.SVM_LINEAR, svm_type=cv2.SVM_C_SVC)
        self.est.train_auto(X, y, None, None, params, 3) #kfold=3 (default: 10)

    def guess(self, X):
        return np.float32( [self.est.predict(s) for s in X])

X = np.array(np.random.random((6,2)), dtype = np.float32)
y = np.array([1.,0.,0.,1.,0.,1.], dtype = np.float32)
g = Learn(X,y).guess(X)
santiwk
  • 11
  • 1