SVM樣本訓練步驟

SVM樣本訓練步驟

本文轉載,本文轉載!!!!!

尊重原創,轉載本文請說明出處:http://blog.csdn.net/xw20084898/article/details/21389885

1、引言

近期在做飛形體目標識別的研究,需要做SVM訓練來生成識別的分類器。從網上找了大量的參考文章,但是發現很多文章都講的比較零散。鑑於此原因,本文對SVM訓練過程做一個較爲系統的總結,希望對廣大初學者有所幫助。

2、步驟

(1)生成SVM描述文件;

將需要訓練的樣本文件的路徑和對應的分類類別號寫入txt文檔,如:
plane/飛機訓練正樣本Normalize/0.jpg
1
plane/飛機訓練正樣本Normalize/1.jpg            命名爲:SVM_DATA.txt
1

(2)將描述文件讀入容器中;

定義兩個容器,用於保存樣本路徑和分類標號,如:

 vector<string> img_path;  
     
   vector<int> img_catg;  

讀入數據:

         int nLine = 0;  
   string buf;  
   ifstream svm_data( "SVM_DATA.txt" ); 

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1.  while( svm_data )    
  2.         {    
  3.             if( getline( svm_data, buf) )   
  4.         /*原型 
  5.   istream& getline ( istream &is , string &str , char delim );   istream& getline ( istream& , string& ); 
  6. 參數  is 進行讀入操作的輸入流   str 存儲讀入的內容   delim 終結符    返回值 與參數is是一樣的 
  7. 功能  將輸入流is中讀到的字符存入str中,直到遇到終結符delim才結束。 
  8.   對於第一個函數delim是可以由用戶自己定義的終結符;對於第二個函數delim默認爲 '\n'(換行符)。    
  9.   函數在輸入流is中遇到文件結束符(EOF)或者在讀入字符的過程中遇到錯誤都會結束。    
  10.   在遇到終結符delim後,delim會被丟棄,不存入str中。在下次讀入操作時,將在delim的下個字符開始讀入。*/   
  11.             {    
  12.             nLine ++;    
  13.             if( nLine % 2 == 0 )    
  14.                 {    
  15.                      img_catg.push_back( atoi( buf.c_str() ) );//atoi將字符串轉換成整型,值爲0或1  用0,1區分正負樣本  
  16.                      //功 能: 把字符串轉換成整型數。   名字來源:array to integer 的縮寫。     
  17.                      //原型: int atoi(const char *nptr);     
  18. //函數說明: 參數nptr字符串,如果第一個非空格字符不存在或者不是數字也不是正負號則返回零,否則開始做類型轉換,  
  19. //之後檢測到非數字(包括結束符 \0) 字符時停止轉換,返回整型數。   
  20.                     // 函數聲明:const char *c_str();   c_str()函數返回一個指向正規C字符串的指針, 內容與本string串相同.   
  21.             }    
  22.             else    
  23.                 {    
  24.                 img_path.push_back( buf );//圖像路徑     
  25.                 }    
  26.             }    
  27.         }    
  28.         svm_data.close();//關閉文件     

3)讀入樣本數量,生成樣本矩陣和類型矩陣

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. CvMat *data_mat, *res_mat;    
  2.         int nImgNum = nLine / 2;            //讀入樣本數量     
  3.     ////樣本矩陣,nImgNum:橫座標是樣本數量, WIDTH * HEIGHT:樣本特徵向量,即圖像大小     
  4.         data_mat = cvCreateMat( nImgNum, 144, CV_32FC1 );    
  5.         cvSetZero( data_mat );    
  6.         //類型矩陣,存儲每個樣本的類型標誌     
  7.         res_mat = cvCreateMat( nImgNum, 1, CV_32FC1 );    
  8.         cvSetZero( res_mat );    

(4)讀入樣本圖像

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. IplImage* src;    
  2.     IplImage* trainImg=cvCreateImage(cvSize(64,64),8,3);//需要分析的圖片  
  3.       
  4.    
  5.     for( string::size_type z = 0; z != img_path.size(); z++ )    //整體循環爲z  
  6.     {    
  7.            src=cvLoadImage(img_path[z].c_str(),1);   
  8.         // 函數聲明:const char *c_str();c_str()函數返回一個指向正規C字符串的指針, 內容與本string串相同.    
  9.             if( src == NULL )    
  10.             {    
  11.                 cout<<" can not load the image: "<<img_path[z].c_str()<<endl;    
  12.                continue;    
  13.             }    
  14.     
  15.             cout<<" processing "<<img_path[z].c_str()<<endl;    

5)提取HOG特徵

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1.  //以下爲提取Hog特徵  
  2.                cvResize(src,trainImg);   //讀取圖片,歸一化大小        
  3.                HOGDescriptor *hog=new HOGDescriptor(cvSize(64,64),cvSize(16,16),cvSize(16,16),cvSize(16,16),9);    
  4.   
  5.                 vector<float>descriptors;//結果數組        
  6.                 hog->compute(trainImg, descriptors,Size(8,8), Size(0,0)); //調用計算函數開始計算        
  7.                 cout<<"HOG dims: "<<descriptors.size()<<endl;    
  8.                 //CvMat* SVMtrainMat=cvCreateMat(descriptors.size(),1,CV_32FC1);     
  9.                 n=0;    
  10.                 for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)    //迭代器  
  11.                 {    
  12.                 cvmSet(data_mat,z,n,*iter);   //將HOG特徵 存入data_mat矩陣中  
  13. x=cvmGet(data_mat,z,n);  
  14. cout<<"hog"<<x<<endl;  
  15.                     n++;    
  16.                 }  

6)將HOG特徵寫入txt文件

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. FILE *fp1;  
  2.     int i,j;  
  3.     if((fp1=fopen("Hog.txt","ab"))==NULL)// 讀寫打開一個二進制文件,允許讀或在文件末追加數據。  
  4.     {  
  5.         printf("can not open the hu file\n");  
  6.         exit(0);//正常退出程序  
  7.     }  
  8.     for (i = 0; i <144; ++i)   
  9.     {  
  10.         fprintf(fp1,"%lf ",descriptors[i]);   
  11.     }  
  12.         //fprintf(fp1,"\r\n");  
  13.     fclose(fp1);  
  14.   
  15.                 cvmSet( res_mat, z, 0, img_catg[z] );   //將正負樣本標記存入矩陣res_mat中  
  16.                 cout<<" end processing "<<img_path[z].c_str()<<" "<<img_catg[z]<<endl;    
  17.     }    

7)進行SVM訓練

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. CvSVM svm = CvSVM();      
  2.     CvSVMParams param;      
  3.     CvTermCriteria criteria;      
  4.        criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON );      
  5.     param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria );      
  6. /*     
  7.     SVM種類:CvSVM::C_SVC     
  8.     Kernel的種類:CvSVM::RBF     
  9.     degree:10.0(此次不使用)     
  10.     gamma:8.0     
  11.    coef0:1.0(此次不使用)     
  12.     C:10.0     
  13.     nu:0.5(此次不使用)     
  14.    p:0.1(此次不使用)     
  15.    然後對訓練數據正規化處理,並放在CvMat型的數組裏。     
  16.                                                         */         
  17.     //SVM學習          
  18.     svm.train( data_mat, res_mat, NULL, NULL, param );      
  19.     //利用訓練數據和確定的學習參數,進行SVM學習        
  20.     svm.save( "SVM_DATA1.xml" );     
  21.   
  22.     cvReleaseImage(&src);  
  23.     cvReleaseMat( &data_mat );   
  24.     cvReleaseMat( &res_mat );    
  25.      return 0;  

在以上訓練過程中,要特別注意的是在創建樣本矩陣的時候,其矩陣大小由樣本數量和樣本提取的特徵維數決定的。比如上面創建的樣本矩陣大小爲:
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. int nImgNum = nLine / 2; 行,144列;  144是由提取HOG特徵時,由窗口大小、塊大小、胞元大小和每個抱怨大小中的特徵數共同決定的。  
發佈了49 篇原創文章 · 獲贊 21 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章