码迷,mamicode.com
首页 > 其他好文 > 详细

opencv中SVM的那些事

时间:2015-04-18 15:48:45      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:

  最近在搞人脸性别识别,用到了opencv中封装的SVM分类器,遇到了一些小问题,解决之后感觉对其理解更深一点了,总结下。

  首先,理解下SVM得输入格式。SVM的train()函数主要包含两个输入数据:训练数据矩阵以及对应标签组成的矩阵。其中训练数据为行向量,标签矩阵为列向量。举个例子吧,比如在实验里一共用到300张图片作为训练数据,其中150张为正例样本,150张为负例样本,那么最终得到的训练数据矩阵大小应为150行n列,这里的n代表的就是每一张图片进行特征提取(包括下采样的方法)之后的特征维数,一般在一两千左右。对应的,标签矩阵应为300行1列,存储的内容为对应行特征向量所代表的正负标签,一般去+1和-1,当然取成别的数也可以。

  其次需要说明的是就是SVM对于输入的数据类型是有要求的,即mTrainData(训练数据矩阵)以及mFlagPosNeg(标签矩阵)都必须为CV_32FC1类型,因此需要进行类型转换,而且必须保证转换完之后数值都不能大于1,这就给我们了两点启示:1、不能直接用下采用后的图像像素作为训练数据的输入,需要进行类型的归一化。2、类型转换时要使用normlize()函数,保证其数值范围不大于1,而不能简单的使用Mat的成员函数coverto,只变类型不变数值范围。

  最后,把之前找的代码贴在这里,与网上的差不多,大家参考吧,是Hog+SVM的一段代码,批量读取图片时采用的是Csv文件的方法:

    String stCsvFilePos = "E:\\Gender_Reognition_Database\\训练样本\\发型区域\\最终训练样本\\正样本-男性短发\\pos_man.txt";
    String stCsvFileNeg = "E:\\Gender_Reognition_Database\\训练样本\\发型区域\\最终训练样本\\中性负样本\\negative.txt";
    ifstream ifstCsvFilePos(stCsvFilePos,ifstream::in);
    String stImagePath;
    Mat mImageTemp;
    Mat mTrainData;
    int iTrainOrder = 0;
    int iNumCurrent = 0;

    while (getline(ifstCsvFilePos,stImagePath))
    {
        mImageTemp = imread(stImagePath,0);
        resize(mImageTemp,mImageTemp,cv::Size(64,64));

        HOGDescriptor *hog=new HOGDescriptor(cvSize(64,64),cvSize(16,16),cvSize(8,8),cvSize(8,8), 9);  //具体意思见参考文章1,2       
        vector<float>descriptors;//结果数组       
        hog->compute(mImageTemp, descriptors, Size(1,1), Size(0,0)); //调用计算函数开始计算
        if (iNumCurrent==0)  
        {  
            mTrainData = Mat::zeros( 300,descriptors.size(), CV_32FC1 ); //根据输入图片大小进行分配空间   
        }  

        int n=0;    
        for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)    
        {    
            mTrainData.at<float>(iNumCurrent,n) = *iter;    
            n++;    
        }   
        ++iNumCurrent;
    }

    ifstream ifstCsvFileNeg(stCsvFileNeg,ifstream::in);
    while (getline(ifstCsvFileNeg,stImagePath))
    {
        mImageTemp = imread(stImagePath,0);
        resize(mImageTemp,mImageTemp,cv::Size(64,64));

        HOGDescriptor *hog=new HOGDescriptor(cvSize(64,64),cvSize(16,16),cvSize(8,8),cvSize(8,8), 9);  //具体意思见参考文章1,2       
        vector<float>descriptors;//结果数组       
        hog->compute(mImageTemp, descriptors, Size(1,1), Size(0,0)); //调用计算函数开始计算
        if (iNumCurrent==0)  
        {  
            mTrainData = Mat::zeros( 300,descriptors.size(), CV_32FC1 ); //根据输入图片大小进行分配空间   
        }  

        int n=0;    
        for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)    
        {    
            mTrainData.at<float>(iNumCurrent,n) = *iter;    
            n++;    
        }   
        ++iNumCurrent;
    }

    Mat mFlagPosNeg = Mat::zeros( 300, 1, CV_32FC1 );
    for (int i = 0; i < 150; i++)
    {
        mFlagPosNeg.at<float>(i,0) = 1;
    }
    for (int i = 150; i < 300; i++)
    {
        mFlagPosNeg.at<float>(i,0) = 2;
    }

    CvSVM svm;  
    CvSVMParams param;    
    CvTermCriteria criteria;      
    criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON );      
    param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria );     

    svm.train(mTrainData,mFlagPosNeg,Mat(),Mat(),param);
    svm.save("E:\\Gender_Reognition_Database\\训练样本\\SVM分类器\\ManShortHairModel.xml");

 

opencv中SVM的那些事

标签:

原文地址:http://www.cnblogs.com/junling/p/4437426.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!