打赏

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\r\n", img_tst_path[j].c_str(), ret);
43         printf("%s %d\r\n", 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的识别分类流程基本是这样了。

有问题欢迎讨论~

posted @ 2017-10-14 16:54  巴尔扎克_S  阅读(4980)  评论(0编辑  收藏  举报