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的識別分類流程基本是這樣了。

有問題歡迎討論~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM