opencv 人脸识别 一 训练样本的处理

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

本文实现基于eigenface的人脸检测与识别。给定一个图像数据库,进行以下步骤:

  • 进行人脸检测,将检测出的人脸存入数据库2
  • 对数据库2进行人脸建模
  • 在测试集上进行recognition

本篇实现第一步:
  • 进行人脸检测,将检测出的人脸存入数据库2


环境:vs2010+opencv 2.4.6.0

特征:eigenface

Input:一个人脸数据库,15个人,每人20个样本(左右)。

Output:人脸检测,并识别出每张检测到的人脸。

===============================


本文完成第一步,数据预处理:自动检测所有文件夹中每个sample中的人脸,作为训练数据。

Input:一个color文件夹,每个文件夹中有1~N这N个子文件夹,每个子文件夹内有n张包括第n类人的照片,如图。

opencv 人脸识别 一 训练样本的处理_第1张图片



最终结果:

opencv 人脸识别 一 训练样本的处理_第2张图片

核心:face detection(detectAndDraw)

辅助:截图并保存部分图片(CutImg),文件夹内图片遍历(read_img),图片转换成相同大小(normalizeone)

括号内分别是函数名,下面分别给出代码及说明。


1. 遍历文件夹:CBrowseDir类和CStatDir类(具体见这篇),三个文件如下:

1.1 BrowseDir.h

#pragma once#include "direct.h"#include "string.h"#include "io.h"#include "stdio.h" #include #include using namespace std;class CBrowseDir{protectedchar m_szInitDir[_MAX_PATH];public: CBrowseDir(); bool SetInitDir(const char *dir)bool BeginBrowse(const char *filespec)vector<char*> BeginBrowseFilenames(const char *filespec);protectedbool BrowseDir(const char *dir,const char *filespec)vector<char*> GetDirFilenames(const char *dir,const char *filespec); virtual bool ProcessFile(const char *filename)virtual void ProcessDir(const char *currentdir,const char *parentdir);};


1.2 BrowseDir.cpp

#include "BrowseDir.h"#include "direct.h"#include "string.h"#include "io.h"#include "stdio.h" #include #include using namespace std;CBrowseDir::CBrowseDir(){ getcwd(m_szInitDir,_MAX_PATH); int len=strlen(m_szInitDir); if (m_szInitDir[len-1] != '\\')  strcat(m_szInitDir,"\\");}bool CBrowseDir::SetInitDir(const char *dir){ if (_fullpath(m_szInitDir,dir,_MAX_PATH) == NULL)  return falseif (_chdir(m_szInitDir) != 0)  return falseint len=strlen(m_szInitDir); if (m_szInitDir[len-1] != '\\')  strcat(m_szInitDir,"\\"); return true;}vector<char*>CBrowseDir:: BeginBrowseFilenames(const char *filespec){ ProcessDir(m_szInitDir,NULL); return GetDirFilenames(m_szInitDir,filespec);}bool CBrowseDir::BeginBrowse(const char *filespec){ ProcessDir(m_szInitDir,NULL); return BrowseDir(m_szInitDir,filespec);}bool CBrowseDir::BrowseDir(const char *dir,const char *filespec){ _chdir(dir); long hFile; _finddata_t fileinfo; if ((hFile=_findfirst(filespec,&fileinfo)) != -1) {  do  {   if (!(fileinfo.attrib & _A_SUBDIR))   {    char filename[_MAX_PATH];    strcpy(filename,dir);    strcat(filename,fileinfo.name);    cout << filename << endl;    if (!ProcessFile(filename))     return false;   }  } while (_findnext(hFile,&fileinfo) == 0);  _findclose(hFile); } _chdir(dir); if ((hFile=_findfirst("*.*",&fileinfo)) != -1) {  do  {   if ((fileinfo.attrib & _A_SUBDIR))   {    if (strcmp(fileinfo.name,".") != 0 && strcmp     (fileinfo.name,"..") != 0)    {     char subdir[_MAX_PATH];     strcpy(subdir,dir);     strcat(subdir,fileinfo.name);     strcat(subdir,"\\");     ProcessDir(subdir,dir);     if (!BrowseDir(subdir,filespec))      return false;    }   }  } while (_findnext(hFile,&fileinfo) == 0);  _findclose(hFile); } return true;}vector<char*> CBrowseDir::GetDirFilenames(const char *dir,const char *filespec){ _chdir(dir); vector<char*>filename_vec; filename_vec.clear(); long hFile; _finddata_t fileinfo; if ((hFile=_findfirst(filespec,&fileinfo)) != -1) {  do  {   if (!(fileinfo.attrib & _A_SUBDIR))   {    char *filename = new char[_MAX_PATH];    strcpy(filename,dir);    //int st = 0; while (dir[st++]!='\0');    strcat(filename,fileinfo.name); //filename[st]='\0';    filename_vec.push_back(filename);   }  } while (_findnext(hFile,&fileinfo) == 0);  _findclose(hFile); } _chdir(dir); if ((hFile=_findfirst("*.*",&fileinfo)) != -1) {  do  {   if ((fileinfo.attrib & _A_SUBDIR))   {    if (strcmp(fileinfo.name,".") != 0 && strcmp     (fileinfo.name,"..") != 0)    {     char subdir[_MAX_PATH];     strcpy(subdir,dir);     strcat(subdir,fileinfo.name);     strcat(subdir,"\\");     ProcessDir(subdir,dir);     return GetDirFilenames(subdir,filespec);    }   }  } while (_findnext(hFile,&fileinfo) == 0);  _findclose(hFile); } return filename_vec;}bool CBrowseDir::ProcessFile(const char *filename){ return true;}void CBrowseDir::ProcessDir(const char  *currentdir,const char *parentdir){}


1.3 StatDir.h

#pragma once#include "browsedir.h"class CStatDir:public CBrowseDir{protectedint m_nFileCount;   //保存文件个数 int m_nSubdirCount; //保存子目录个数public: CStatDir() {  m_nFileCount=m_nSubdirCount=0; } int GetFileCount() {  return m_nFileCount; } int GetSubdirCount() {  return m_nSubdirCount-1; }protectedvirtual bool ProcessFile(const char *filename) {  m_nFileCount++;  return CBrowseDir::ProcessFile(filename); } virtual void ProcessDir  (const char *currentdir,const char *parentdir) {  m_nSubdirCount++;  CBrowseDir::ProcessDir(currentdir,parentdir); }};




2. 辅助函数Prehelper.h, Prehelper.cpp:负责返回文件夹内所有图片(read_img),检测人脸(detectAndDraw并可以在原图中画出),截图(CutImg),提取(DetectandExtract)

2.1 Prehelper.h

//preprocessing helper//@ Author : Rachel-Zhang#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/contrib/contrib.hpp"#include #include #include using namespace cv;using namespace std;void normalizeone(const char* dir,IplImage* standard);void CutImg(IplImage* src, CvRect rect,IplImage* res);vector detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip,bool draw );IplImage* DetectandExtract(Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip);int read_img(const string& dir, vector &images);vectorchar*,Mat>>  read_img(const string& dir);



2.2 Prehelper.cpp

#include "Prehelper.h"#include "BrowseDir.h"#include "StatDir.h"#include #include #include using namespace cv;void normalizeone(const char* dir,IplImage* standard){ CStatDir statdir; if (!statdir.SetInitDir(dir)) {  puts("Dir not exist");  return; } vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*"); int i; for (i=0;i//IplImage*cur_gray = cvCreateImage(cvGetSize(cur_img),cur_img->depth,1);  cvResize(cur_img,standard,CV_INTER_AREA);  //cvCvtColor(standard,cur_gray,CV_RGB2GRAY);  //   cvNamedWindow("cur_img",CV_WINDOW_AUTOSIZE);  //   cvNamedWindow("standard",CV_WINDOW_AUTOSIZE);  //   cvShowImage("cur_img",cur_img);  //   cvShowImage("standard",standard);  //   cvWaitKey();  cvSaveImage(file_vec[i],cur_img); }}void CutImg(IplImage* src, CvRect rect,IplImage* res){ CvSize imgsize; imgsize.height = rect.height; imgsize.width = rect.width; cvSetImageROI(src,rect); cvCopy(src,res); cvResetImageROI(res);}int read_img(const string& dir, vector &images){ CStatDir statdir; if (!statdir.SetInitDir(dir.c_str())) {  cout<<"Direct "<"  not exist!"<<endl;  return 0; } int cls_id = dir[dir.length()-1]-'0'vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*"); int i,s = file_vec.size(); for (i=0;i0);  //graymat.reshape(1,1);//flatten to one row  images.push_back(graymat); } return s;}vectorchar*,Mat>>  read_img(const string& dir){ CStatDir statdir; pair<char*,Mat> pfi; vectorchar*,Mat>> Vp; if (!statdir.SetInitDir(dir.c_str())) {  cout<<"Direct "<"  not exist!"<<endl;  return Vp; } int cls_id = dir[dir.length()-1]-'0'vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*"); int i,s = file_vec.size(); for (i=0;ireturn Vp;}vector detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip, bool draw ){ int i = 0double t = 0vector faces, faces2; const static Scalar colors[] =  { CV_RGB(0,0,255),  CV_RGB(0,128,255),  CV_RGB(0,255,255),  CV_RGB(0,255,0),  CV_RGB(255,128,0),  CV_RGB(255,255,0),  CV_RGB(255,0,0),  CV_RGB(255,0,255)} ; Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); cvtColor( img, gray, CV_BGR2GRAY ); resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); equalizeHist( smallImg, smallImg ); t = (double)cvGetTickCount(); cascade.detectMultiScale( smallImg, faces,  1.1, 2, 0  |CV_HAAR_FIND_BIGGEST_OBJECT  //|CV_HAAR_DO_ROUGH_SEARCH  //|CV_HAAR_SCALE_IMAGE  ,  Size(30, 30) ); if( tryflip ) {  flip(smallImg, smallImg, 1);  cascade.detectMultiScale( smallImg, faces2,   1.1, 2, 0   |CV_HAAR_FIND_BIGGEST_OBJECT   //|CV_HAAR_DO_ROUGH_SEARCH   //|CV_HAAR_SCALE_IMAGE   ,   Size(30, 30) );  for( vector::const_iterator r = faces2.begin(); r != faces2.end(); r++ )  {   faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));  } } t = (double)cvGetTickCount() - t; printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) ); if(draw) {  for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )  {   Mat smallImgROI;   vector nestedObjects;   Point center;   Scalar color = colors[i%8];   int radius;   double aspect_ratio = (double)r->width/r->height;   rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)),    cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)),    color, 3, 8, 0);   if( nestedCascade.empty() )    continue;   smallImgROI = smallImg(*r);   nestedCascade.detectMultiScale( smallImgROI, nestedObjects,    1.1, 2, 0    |CV_HAAR_FIND_BIGGEST_OBJECT    //|CV_HAAR_DO_ROUGH_SEARCH    //|CV_HAAR_DO_CANNY_PRUNING    //|CV_HAAR_SCALE_IMAGE    ,    Size(30, 30) );   //draw eyes   //         for( vector::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )   //         {   //             center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);   //             center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);   //             radius = cvRound((nr->width + nr->height)*0.25*scale);   //             circle( img, center, radius, color, 3, 8, 0 );   //         }  }  cv::imshow( "result", img ); } return faces;}IplImage* DetectandExtract(Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip)vector Rvec = detectAndDraw(img,cascade,nestedCascade,scale,tryflip,0); int i,maxxsize=0,id=-1,area; for (i=0;iif(maxxsizeif(id!=-1) {  CvSize imgsize;  imgsize.height = Rvec[id].height;  imgsize.width = Rvec[id].width;  IplImage* res = cvCreateImage(imgsize,transimg->depth,transimg->nChannels);  CutImg(transimg,Rvec[id],res);  return res; } return NULL;}


3. 主函数

//Detect.cpp//Preprocessing - Detect, Cut and Save//@Author : Rachel-Zhang#include "opencv2/objdetect/objdetect.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include #include #include #include #include "BrowseDir.h"#include "StatDir.h"#include "Prehelper.h"using namespace std;using namespace cv;#define CAM 2#define PHO 1#define K 5string cascadeName = "E:/software/opencv2.4.6.0/data/haarcascades/haarcascade_frontalface_alt.xml";string nestedCascadeName = "E:/software/opencv2.4.6.0/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";int main( ){ CvCapture* capture = 0; Mat frame, frameCopy, image; string inputName; bool tryflip = falseint mode; CascadeClassifier cascade, nestedCascade;  double scale = 1.0if( !cascade.load( cascadeName ) ||!nestedCascade.load( nestedCascadeName)) {  cerr << "ERROR: Could not load classifier cascade or nestedCascade" << endl;//若出现该问题请去检查cascadeName,可能是opencv版本路径问题  return -1; }//  printf("select the mode of detection: \n1: from picture\t 2: from camera\n");//  scanf("%d",&mode); char** pics = (char**) malloc(sizeof*pics); /************************************************************************/ /*                                  detect face and save                                    */ /************************************************************************/ int i,j; cout<<"detect and save..."<<endlconst char dir[256] = "D:\\Face_recognition\\pic\\";   string cur_dir;  char id[5]; for(i=1; i<=K; i++) {  cur_dir = dir;  _itoa(i,id,10);  cur_dir.append("color\\");  cur_dir.append(id);  vectorchar*,Mat>> imgs=read_img(cur_dir);  for(j=0;jif(res)    cvSaveImage(imgs[j].first,res);  } } return 0;}


正确的输出就是一系列人脸检测时间,且原文件夹内的图片变成了检测出的人脸(如上面结果图所示)。

opencv 人脸识别 一 训练样本的处理_第3张图片



文章所用代码打包链接:http://download.csdn.net/detail/abcjennifer/7047853


关于Computer Vision更多的学习资料将继续更新,敬请关注本博客和新浪微博Rachel Zhang




           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

opencv 人脸识别 一 训练样本的处理_第4张图片

你可能感兴趣的:(opencv 人脸识别 一 训练样本的处理)