1. 程式人生 > >opencv 人臉識別 二 訓練和識別

opencv 人臉識別 二 訓練和識別

               

上一篇中我們對訓練資料做了一些預處理,檢測出人臉並儲存在\pic\color\x資料夾下(x=1,2,3,...類別號),本文做訓練和識別。為了識別,首先將人臉訓練資料 轉為灰度、對齊、歸一化,再放入分類器(EigenFaceRecognizer),最後用訓練出的model進行predict。

-----------------------------------------

環境:vs2010+opencv 2.4.6.0

特徵:eigenface

Input:一個人臉資料庫,15個人,每人20個樣本(左右)。

Output:人臉檢測,並識別出每張檢測到的人臉。

-----------------------------------------

1. 為訓練資料預處理( 轉為灰度、對齊、歸一化 

  • 轉為灰度和對齊是後面做訓練時EigenFaceRecognizer的要求;
  • 歸一化是防止光照帶來的影響

在上一篇的 2.2 Prehelper.cpp檔案中加入函式

void resizeandtogray(char* dir,int k, vector<Mat> &images, vector<int> &labels,vector<Mat> &testimages, vector<int> &testlabels);

void resizeandtogray(char
* dir,int K, vector<Mat> &images, vector<int> &labels, vector<Mat> &testimages, vector<int> &testlabels)
{ IplImage* standard = cvLoadImage("D:\\privacy\\picture\\photo\\2.jpg",CV_LOAD_IMAGE_GRAYSCALE); string cur_dir; char id[5]; int i,j; for(int i=1; i<=K; i++) {  cur_dir = dir;  cur_dir.append("gray\\"
);   _itoa(i,id,10);  cur_dir.append(id);  const char* dd = cur_dir.c_str();  CStatDir statdir;  if (!statdir.SetInitDir(dd))  {   puts("Dir not exist");   return;  }  cout<<"Processing samples in Class "<<i<<endl;  vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*");  for (j=0;j<file_vec.size();j++)  {   IplImage* cur_img = cvLoadImage(file_vec[j],CV_LOAD_IMAGE_GRAYSCALE);   cvResize(cur_img,standard,CV_INTER_AREA);   Mat cur_mat = cvarrToMat(standard,true),des_mat;   cv::normalize(cur_mat,des_mat,0, 255, NORM_MINMAX, CV_8UC1);   cvSaveImage(file_vec[j],cvCloneImage(&(IplImage) des_mat));   if(j!=file_vec.size())   {     images.push_back(des_mat);     labels.push_back(i);   }   else   {    testimages.push_back(des_mat);    testlabels.push_back(i);   }  }  cout<<file_vec.size()<<" images."<<endl; }}

並在main中呼叫:

int main( ){ CvCapture* capture = 0; Mat frame, frameCopy, image; string inputName;  int mode; char dir[256] = "D:\\Courses\\CV\\Face_recognition\\pic\\";  //preprocess_trainingdata(dir,K); //face_detection and extract to file vector<Mat> images,testimages; vector<int> labels,testlabels; resizeandtogray(dir,K,images,labels,testimages,testlabels); //togray, normalize and resize  system("pause"); return 0;}

2. 訓練

有了vector<Mat> images,testimages;vector<int> labels,testlabels; 可以開始訓練了,我們採用EigenFaceRecognizer建模。

在Prehelper.cpp中加入函式

Ptr<FaceRecognizer> Recognition(vector<Mat> images, vector<int> labels,vector<Mat> testimages, vector<int> testlabels);

Ptr<FaceRecognizer> Recognition(vector<Mat> images, vector<int> labels, vector<Mat> testimages, vector<int> testlabels){ Ptr<FaceRecognizer> model = createEigenFaceRecognizer(10);//10 Principal components cout<<"train"<<endl; model->train(images,labels); int i,acc=0,predict_l; for (i=0;i<testimages.size();i++) {  predict_l = model->predict(testimages[i]);  if(predict_l != testlabels[i])  {   cout<<"An error in recognition: sample "<<i+1<<", predict "<<    predict_l<<", groundtruth "<<testlabels[i]<<endl;   imshow("error 1",testimages[i]);   waitKey();  }  else   acc++; } cout<<"Recognition Rate: "<<acc*1.0/testimages.size()<<endlreturn model;}
Recognization()輸出分錯的樣本和正確率,最後返回建模結果Ptr<FaceRecognizer> model

主函式改為:

int main( ){ CvCapture* capture = 0; Mat frame, frameCopy, image; string inputName;  int mode; char dir[256] = "D:\\Courses\\CV\\Face_recognition\\pic\\";  //preprocess_trainingdata(dir,K); //face_detection and extract to file vector<Mat> images,testimages; vector<int> labels,testlabels; //togray, normalize and resize; load to images,labels,testimages,testlabels resizeandtogray(dir,K,images,labels,testimages,testlabels);  //recognition Ptr<FaceRecognizer> model = Recognition(images,labels,testimages,testlabels); char* dirmodel = new char [256]; strcpy(dirmodel,dir); strcat(dirmodel,"model.out"); FILE* f = fopen(dirmodel,"w"); fwrite(model,sizeof(model),1,f); system("pause"); return 0;}

最終結果:一個錯分樣本,正確率93.3%

關於Computer Vision更多的學習資料將繼續更新,敬請關注本部落格和新浪微博Rachel Zhang