图像处理项目——人脸检测—训练

训练模型

*开发环境为visual studio2010
*使用的数据集是face.txt
*用到Facerecognizer类。opencv中所有的人脸识别模型都是来源于这个类。

一:主要步骤
1.创建了一个特征脸模型用于人脸识别
2.通过CSV文件face.txt读取的图像和标签训练它 
3.创建一个PCA人脸分类器,T这里是一个完整的PCA变换
4.调用其中的成员函数train()来完成分类器的训练

二:代码
  1 #include <opencv2/opencv.hpp>
  2 #include <opencv2/core/core.hpp>
  3 #include "opencv2/face/facerec.hpp"
  4 #include "opencv2/face.hpp"
  5 #include "opencv2/core.hpp"
  6 #include "opencv2/highgui.hpp"
  7 #include "opencv2/imgproc.hpp"
  8 #include <iostream>
  9 #include <fstream>                    
 10 #include <sstream>                    
 11 #include <math.h>                     
 12 using namespace cv;
 13 using namespace cv::face;
 14 using namespace std;
 15 
 16 static Mat norm_0_255(InputArray _src)
 17 {
 18    Mat src = _src.getMat();                
 19    // 创建和返回一个归一化后的图像矩阵: 
 20    Mat dst;
 21    switch (src.channels())
 22    {
 23      case 1:
 24        cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
 25        break;
 26      case 3:
 27        cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
 28        break;
 29      default:
 30        src.copyTo(dst);
 31        break;
 32    }
 33    return dst;
 34 }
 35 
 36 //使用CSV文件去读图像和标签,主要使用stringstream和getline方法  
 37 static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';')
 38 {
 39     std::ifstream file(filename.c_str(), ifstream::in);//c_str()函数可用可不用,无需返回一个标准C类型的字符串
 40     if(!file)
 41     {
 42       string error_message = "No valid input file was given, please check the given filename.";
 43       CV_Error(CV_StsBadArg, error_message);
 44     }
 45     string line, path, classlabel;
 46     while(getline(file,line))                   //从文本文件中读取一行字符,未指定限定符默认限定符为“/n”
 47     {
 48        stringstream liness(line);
 49        getline(liness, path, separator);      //这里采用stringstream主要作用是做字符串的分割
 50        getline(liness,classlabel);             //读入图片文件路径以分好作为限定符
 51        if (!path.empty() && !classlabel.empty())
 52        {
 53           images.push_back(imread(path,0));
 54           labels.push_back(atoi(classlabel.c_str()));///如果读取成功,则将图片和对应标签压入对应容器中
 55 
 56        }
 57 
 58     }
 59 }
 60 
 61 int main()
 62 {
 63  //读取你的CSV文件路径. 
 64   string fn_csv = "face.txt";
 65   
 66   // 2个容器来存放图像数据和对应的标签
 67   vector<Mat> images;
 68   vector<int> labels;
 69 
 70   // 读取数据. 如果文件不合法就会出错  
 71 
 72   try 
 73   {
 74     read_csv(fn_csv, images, labels);
 75   }
 76   catch (cv::Exception& e)
 77   {
 78     cerr << "Error opening file \"" << fn_csv << "\".Reason: " << e.msg << endl;
 79     exit(1);
 80   }
 81   // 如果没有读取到足够图片,也退出.  
 82   if(images.size() <= 1)
 83   {
 84     string error_message = " Please add more images to your data set!";
 85     CV_Error(CV_StsError, error_message);
 86   }
 87   
 88   for (int i = 0; i < images.size(); i++)
 89   {
 90        if(images[i].size() != Size(92, 112))
 91        {
 92            cout << i << endl;
 93            cout << images[i].size() << endl;
 94        }
 95   }
 96   // 下面的几行代码仅仅是从你的数据集中移除最后一张图片,作为测试图片  
 97   //[gm:自然这里需要根据自己的需要修改,他这里简化了很多问题]  
 98   Mat testSample = images[images.size() - 1];
 99   int testLabel = labels[labels.size() - 1];
100   images.pop_back();    //删除最后一张照片,此照片作为测试图片
101   labels.pop_back();    //删除最有一张照片的labels
102 
103     // 创建了一个特征脸模型用于人脸识别,  
104     // 通过CSV文件读取的图像和标签训练它。  
105     // T这里是一个完整的PCA变换  
106     //创建一个PCA人脸分类器,
107     //调用其中的成员函数train()来完成分类器的训练
108   Ptr<BasicFaceRecognizer> model0 = createEigenFaceRecognizer();
109   model0->train(images,labels);
110 
111   //save the model to .xml
112   model0->save("MyEigenFaces.xml");
113 
114   Ptr<BasicFaceRecognizer> model1 = createFisherFaceRecognizer();
115   model1->train(images,labels);
116   model1->save("MyFaceModel.xml");
117 
118     // 还有一种调用方式,可以获取结果同时得到阈值:  
119     // int predictedLabel = -1;  
120     // double confidence = 0.0;  
121     //  model->predict(testSample, predictedLabel, confidence); 
122     
123   int predictedLabel0 = model0->predict(testSample);
124   int predictedLabel1 = model1->predict(testSample);
125   int predictedLabel2 = model2->predict(testSample);
126  
127   string result_message0 = format("Predicted class = %d / Actual class = %d.",predictedLabel0, testLabel);
128   string result_message1 = format("Predicted class = %d / Actual class = %d.",predictedLabel1, testLabel);
129   string result_message2 = format("Predicted class = %d / Actual class = %d.",predictedLabel2, testLabel);
130 
131   cout << result_message0 << endl;
132   cout << result_message1 << endl;
133   cout << result_message2 << endl;
134 
135   waitKey(0);
136   return 0;
137 }

 

三:训练结果

生成了MyFaceModel.xml文件,可以直接使用进行人脸识别

 

 

 

posted on 2019-03-18 09:24  AI大道理  阅读(958)  评论(0编辑  收藏  举报

导航