如何使用具有面部特征的openCV训练支持向量机(svm)分类器?

时间:2014-09-26 08:57:36

标签: c opencv svm face-detection feature-detection

我想使用svm分类器进行面部表情检测。我知道opencv有一个svm api,但我不知道应该用什么来训练分类器。到目前为止,我已经阅读了很多论文,所有这些都是在面部特征检测后训练分类器时说的。

到目前为止,我做了什么,

  1. 人脸检测,
  2. 每帧中16个面部点计算。下面是面部特征检测的输出![输入图像描述
  3. 保存要素的向量指向像素地址here
  4. 注意:我知道如何仅使用正面和负面图像训练SVM,我看到了这段代码here,但我不知道如何将面部特征信息与它结合起来。

    有人可以帮我用svm开始分类。

    一个。什么应该是训练分类器的样本输入?

    湾如何使用此面部特征点训练分类器?

    此致

2 个答案:

答案 0 :(得分:16)

opencv中的机器学习算法都带有类似的界面。为了训练它,你传递一个NxM Mat offeatures(N行,每个特征一行长度为M)和一个带有类标签的Nx1 Mat。像这样:

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

对于预测,你以相同的方式用1行填充Mat,它将返回预测的标签

所以,让我们说,你的16个面部点存储在一个矢量中,你会这样做:

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

答案 1 :(得分:3)

面部姿势识别是一个广泛研究的问题,您需要使用的适当功能可以通过对现有文献的深入研究找到。一旦你拥有了你认为很好的特征描述符,你就可以继续训练SVM。一旦您使用最佳参数(通过交叉验证找到)训练SVM,就可以开始在看不见的数据上测试SVM模型,并报告准确性。一般来说,这就是管道。

现在关于SVM的部分:

SVM是一个二元分类器 - 它可以区分两个类(尽管它也可以扩展到多个类)。 OpenCV在ML库中有SVM的内置模块。 SVM类有两个函数:train(..)predict(..)。要训​​练分类器,您可以在输入中输入大量的样本特征描述符及其类标签(通常为-1和+1)。请记住OpenCV支持的格式:每个训练样本都必须是行向量。并且每行在标签向量中将具有一个对应的类标签。因此,如果您有一个长度为n的描述符,并且您有m个样本描述符,那么您的训练矩阵将为m x nm行,每行长度为{{1} }}),标签向量的长度为n。还有一个m对象,其中包含SVM类型等属性以及您必须指定的SVMParams等参数值。

训练后,您从图像中提取特征,将其转换为单行格式,并提供给C,它将告诉您它属于哪个类(+1或-1)。

还有一个predict()具有相似的参数,格式相似,可以为您提供SVM参数的最佳值。

另请查看此detailed SO answer以查看示例。

编辑: 假设您有一个返回特征向量的特征描述符,算法将类似于:

train_auto()

我不认为Mat trainingMat, labelsMat; for each image in training database: feature = extractFeatures( image[i] ); Mat feature_row = alignAsRow( feature ); trainingMat.push_back( feature_row ); labelsMat.push_back( -1 or 1 ); //depending upon class. mySvmObject.train( trainingMat, labelsMat, Mat(), Mat(), mySvmParams ); extractFeatures()是现有函数,您可能需要自己编写它们。