How to train a Support Vector Machine(svm) classifier with openCV with facial features?

MMH picture MMH · Sep 26, 2014 · Viewed 9.9k times · Source

I want to use the svm classifier for facial expression detection. I know opencv has a svm api, but I have no clue what should be the input to train the classifier. I have read many papers till now, all of them says after facial feature detection train the classifier.

so far what I did,

  1. Face detection,
  2. 16 facial points calculation in every frame. below is an output of facial feature detection![enter image description
  3. A vector which holds the features points pixel addresshere

Note: I know how I can train the SVM only with positive and negative images, I saw this codehere, But I don't know how I combine the facial feature information with it.

Can anybody please help me to start the classification with svm.

a. what should be the sample input to train the classifier?

b. How do I train the classifier with this facial feature points?

Regards,

Answer

berak picture berak · Sep 29, 2014

the machine learning algos in opencv all come with a similar interface. to train it, you pass a NxM Mat offeatures (N rows, each feature one row with length M) and a Nx1 Mat with the class-labels. like this:

//traindata      //trainlabels

f e a t u r e    1 
f e a t u r e    -1
f e a t u r e    1
f e a t u r e    1
f e a t u r e    -1

for the prediction, you fill a Mat with 1 row in the same way, and it will return the predicted label

so, let's say, your 16 facial points are stored in a vector, you would do like:

Mat trainData; // start empty
Mat labels;

for all facial_point_vecs:
{
    for( size_t i=0; i<16; i++ )
    {
        trainData.push_back(point[i]);
    }
    labels.push_back(label); // 1 or -1
}
// now here comes the magic:
// reshape it, so it has N rows, each being a flat float, x,y,x,y,x,y,x,y... 32 element array
trainData = trainData.reshape(1, 16*2); // numpoints*2 for x,y

// we have to convert to float:
trainData.convertTo(trainData,CV_32F);

SVM svm; // params omitted for simplicity (but that's where the *real* work starts..)
svm.train( trainData, labels );


//later predict:
vector<Point> points;
Mat testData = Mat(points).reshape(1,32); // flattened to 1 row
testData.convertTo(testData ,CV_32F);
float p = svm.predict( testData );