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()<<endl; return 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。