opencv中SVM的那些事

  最近在搞人脸性别识别,用到了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");
时间: 2024-08-06 07:08:15

opencv中SVM的那些事的相关文章

OpenCV中的SVM参数优化

OpenCV中的SVM参数优化 标签: svm参数优化opencv SVMSVR参数优化CvSVMopencv CvSVM 2014-08-19 10:31 2995人阅读 评论(8) 收藏 举报  分类: 机器学习(11)  opencv(18)  版权声明:本文为博主原创文章,未经博主允许不得转载. SVM(支持向量机)是机器学习算法里用得最多的一种算法.SVM最常用的是用于分类,不过SVM也可以用于回归,我的实验中就是用SVM来实现SVR(支持向量回归). 对于功能这么强的算法,OpenC

OpenCV中的SVM參数优化

SVM(支持向量机)是机器学习算法里用得最多的一种算法.SVM最经常使用的是用于分类,只是SVM也能够用于回归,我的实验中就是用SVM来实现SVR(支持向量回归). 对于功能这么强的算法,opencv中自然也是有集成好了,我们能够直接调用.OpenCV中的SVM算法是基于LibSVM软件包开发的,LibSVM是台湾大学林智仁(Lin Chih-Jen)等开发设计的一个简单.易于使用和高速有效的SVM模式识别与回归的软件包. 网上讲opencv中SVM使用的文章有非常多,但讲SVM參数优化的文章却

opencv使用svm

作者 群号 C语言交流中心 240137450  微信 15013593099 OpenCV开发SVM算法是基于LibSVM软件包开发的,LibSVM是台湾大学林智仁(LinChih-Jen)等开发设计的一个简单.易于使用和快速有效的SVM模式识别与回归的软件包.用OpenCV使用SVM算法的大概流程是 1)设置训练样本集 需要两组数据,一组是数据的类别,一组是数据的向量信息. 2)设置SVM参数 利用CvSVMParams类实现类内的成员变量svm_type表示SVM类型: CvSVM::C_

opencv中的SVM图像分类(二)

opencv中的SVM图像分类(二) 标签: svm图像 2015-07-30 08:45 8296人阅读 评论(35) 收藏 举报  分类: [opencv应用](5)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 原创作品 转载请注明出http://blog.csdn.net/always2015/article/details/47107129 上一篇博文对图像分类理论部分做了比较详细的讲解,这一篇主要是对图像分类代码的实现进行分析.理论部分我们谈到了使用BOW

OpenCV 中使用SVM

分类器 分类器是一种计算机程序. 他的设计目标是在通过学习后,可自动将数据分到已知类别. 平面线性分类器 一个简单的分类问题,如图有一些圆圈和一些正方形,如何找一条最优的直线将他们分开? 我们可以找到很多种方法画出这条直线,但怎样的直线才是最优的呢? 距离样本太近的直线不是最优的,因为这样的直线对噪声敏感度高,泛化性较差. 因此我们的目标是找到一条直线,离最近的点距离最远. 怎么寻找距离最远的直线?枚举所有直线,然后计算其样本最小距离?这样显然不是一个好办法,这将产生大量的计算开销. 我们利用另

opencv中的 HOGDescriptor 类

其定义在  object.hpp中找到的: [cpp] view plain copy struct CV_EXPORTS_W HOGDescriptor { public: enum { L2Hys=0 }; enum { DEFAULT_NLEVELS=64 }; CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8), cellSize(8,8), nbins(9), derivApertu

opencv的svm学习_1

概述 本篇是对opencv的svm学习笔记,基于对opencv官方svm教程的修改和记录.opencv的svm教程如下: 官网原版:http://docs.opencv.org/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html#introductiontosvms 汉语翻译版:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/ml/introductio

[OpenCV-Python] OpenCV 中的图像处理 部分 IV (六)

部分 IVOpenCV 中的图像处理 23 图像变换 23.1 傅里叶变换目标本小节我们将要学习: ? 使用 OpenCV 对图像进行傅里叶变换 ? 使用 Numpy 中 FFT(快速傅里叶变换)函数 ? 傅里叶变换的一些用处 ? 我们将要学习的函数有:cv2.dft(),cv2.idft() 等原理 傅里叶变换经常被用来分析不同滤波器的频率特性.我们可以使用 2D 离散傅里叶变换 (DFT) 分析图像的频域特性.实现 DFT 的一个快速算法被称为快速傅里叶变换(FFT).关于傅里叶变换的细节知

[OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V (一)

部分 V图像特征提取与描述 29 理解图像特征 目标本节我会试着帮你理解什么是图像特征,为什么图像特征很重要,为什么角点很重要等.29.1 解释 我相信你们大多数人都玩过拼图游戏吧.首先你们拿到一张图片的一堆碎片,要做的就是把这些碎片以正确的方式排列起来从而重建这幅图像.问题是,你怎样做到的呢?如果把你做游戏的原理写成计算机程序,那计算机就也会玩拼图游戏了.如果计算机可以玩拼图,我们就可以给计算机一大堆自然图片,然后就可以让计算机把它拼成一张大图了.如果计算机可以自动拼接自然图片,那我们是不是可