zoukankan      html  css  js  c++  java
  • opencv SVM多分类 人脸识别

      上一篇介绍了OPENCV中SVM的简单使用,以及自带的一个二分类问题。

      例子中的标签是程序手动写的,输入也是手动加的二维坐标点。  

      对于复杂问题就必须使用数据集中的图片进行训练,标签使用TXT文件或程序设置好,下面以 IMM Face Database 中的人脸数据作为示例,

    实现人脸的HOG特征提取及SVM识别人脸。

      数据集参考我的http://www.cnblogs.com/chenzhefan/p/7624811.html;只选取其中5类人,每类5副图片作为训练。

      提取人脸HOG特征的维数为1764,具体见代码设置。

     1 void HogSVM()
     2 {
     3     int ImgWidht = 64;
     4     int ImgHeight = 64;
     5     vector<string> img_path;
     6     vector<int> img_catg;
     7     int nLine = 0;
     8     string buf;
     9     ifstream svm_data("E:\vswork\car3\train\train.txt");
    10     unsigned long n;
    11 
    12     for (int catg = 0; catg < 5; catg++)
    13     {
    14         for (int num = 0; num < 5; num++)
    15         {
    16             if (getline(svm_data, buf))
    17             {
    18                 img_catg.push_back(catg);//图像类别
    19                 img_path.push_back(buf);//图像路径
    20                 nLine++;
    21             }
    22         }
    23 
    24     }
    25 
    26     svm_data.close();//关闭文件  
    27 
    28     Mat data_mat, res_mat;
    29     int nImgNum = nLine;            //读入样本数量  
    30     //样本矩阵,nImgNum:行数代表样本的数量,每一行就是由一张图片计算得到HOG的特征向量,
    31     data_mat = Mat::zeros(nImgNum, 1764, CV_32FC1);
    32     res_mat = Mat::zeros(nImgNum, 1, CV_32FC1);
    33 
    34     Mat src;
    35     Mat trainImg = Mat::zeros(ImgHeight, ImgWidht, CV_8UC3);//需要分析的图片  
    36 
    37     for (string::size_type i = 0; i != img_path.size(); i++)
    38     {
    39         src = imread(img_path[i].c_str(), 1);
    40 
    41         cout << " processing " << img_path[i].c_str() << endl;
    42 
    43         resize(src, trainImg, cv::Size(ImgWidht, ImgHeight), 0, 0, INTER_CUBIC);
    44         HOGDescriptor *hog = new HOGDescriptor(cvSize(ImgWidht, ImgHeight), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);  //构造HOG,具体意思见参考文章1,2     
    45         vector<float>descriptors;//结果数组     
    46         hog->compute(trainImg, descriptors, Size(1, 1), Size(0, 0)); //调用计算函数开始计算
    47         if (i == 0)
    48         {
    49             data_mat = Mat::zeros(nImgNum, descriptors.size(), CV_32FC1); //根据输入图片大小进行分配空间 
    50         }
    51         cout << "HOG dims: " << descriptors.size() << endl;
    52         n = 0;
    53         for (vector<float>::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++)
    54         {
    55             data_mat.at<float>(i, n) = *iter;
    56             n++;
    57         }
    58         res_mat.at<float>(i, 0) = img_catg[i];
    59         cout << " end processing " << img_path[i].c_str() << " " << img_catg[i] << endl;
    60     }
    61 
    62     CvSVM svm;
    63     CvSVMParams param;
    64     CvTermCriteria criteria;
    65     criteria = cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);
    66     param = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria);
    67 
    68     svm.train(data_mat, res_mat, Mat(), Mat(), param);
    69     svm.save("SVM_DATA.xml");
    70 
    71     return;
    72 }

    上述函数主要完成提取训练图片的HOG特征,并用SVM训练模型,保存为XML文件方便快速使用。

    训练结果如图:

    训练完成后即可以使用测试图片进行图片识别了:

     1 void HogSVMPre()
     2 {
     3     //检测样本  
     4     vector<string> img_tst_path;
     5     string buf;
     6     unsigned long n;
     7     int ImgWidht = 64;
     8     int ImgHeight = 64;
     9     Mat TestImg = Mat::zeros(ImgHeight, ImgWidht, CV_8UC3);
    10     ifstream img_tst("E:\vswork\car3\val\val.txt");
    11     while (img_tst)
    12     {
    13         if (getline(img_tst, buf))
    14         {
    15             img_tst_path.push_back(buf);
    16         }
    17     }
    18     img_tst.close();
    19     CvSVM svm;
    20     svm.load("SVM_DATA.xml");
    21     Mat test;
    22     char line[512];
    23     ofstream predict_txt("SVM_PREDICT.txt");
    24     for (string::size_type j = 0; j != img_tst_path.size(); j++)
    25     {
    26         test = imread(img_tst_path[j].c_str(), 1);//读入图像   
    27         resize(test, TestImg, cv::Size(ImgWidht, ImgHeight), 0, 0, INTER_CUBIC);//要搞成同样的大小才可以检测到       
    28         HOGDescriptor *hog = new HOGDescriptor(cvSize(ImgWidht, ImgHeight), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);  //窗口大小,块大小,块滑动增量,cell的大小,bins的个数
    29         vector<float>descriptors;//结果数组     
    30         hog->compute(TestImg, descriptors, Size(1, 1), Size(0, 0)); //调用计算函数开始计算 
    31         cout << "The Detection Result:" << endl;
    32         cout << "HOG dims: " << descriptors.size() << endl;
    33         Mat SVMtrainMat = Mat::zeros(1, descriptors.size(), CV_32FC1);
    34         n = 0;
    35         for (vector<float>::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++)
    36         {
    37             SVMtrainMat.at<float>(0, n) = *iter;
    38             n++;
    39         }
    40 
    41         int ret = svm.predict(SVMtrainMat);
    42         std::sprintf(line, "%s %d
    ", img_tst_path[j].c_str(), ret);
    43         printf("%s %d
    ", img_tst_path[j].c_str(), ret);//输出预测的结果,ret的值就代表类别
    44         //getchar();
    45         predict_txt << line;
    46     }
    47     predict_txt.close();
    48     system("PAUSE");
    49     return;
    50 }

    预测结果:

    小样本图片SVM的识别结果还是很不错的。本文的测试图片较少,也不能说明模型到底有多好,但基于opencv SVM的识别分类流程基本是这样了。

    有问题欢迎讨论~

  • 相关阅读:
    Vulnhub-靶机-DJINN: 1
    8.8-9 sqlmap从入门到精通-其中小技巧-分析大文件日志技巧
    Vulnhub-靶机-EVM: 1
    8.7 sqlmap从入门到精通-Linux服务器登录连接日志分析
    Linux操作系统常规的分析SSH登录日志需要使用的命令和记录
    CentOS最小安装无法使用ifconfig命令
    CentOS7下安装FTP服务
    解决Centos7安装后无法联网的问题
    Maven引入本地jar包
    Tomcat下安装solr6.x
  • 原文地址:https://www.cnblogs.com/chenzhefan/p/7667812.html
Copyright © 2011-2022 走看看