zoukankan      html  css  js  c++  java
  • opencv 人脸识别 (一)训练样本的处理

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

    • 进行人脸检测,将检测出的人脸存入数据库2
    • 对数据库2进行人脸建模
    • 在测试集上进行recognition
     
    本篇实现第一步:
    • 进行人脸检测,将检测出的人脸存入数据库2

    环境:vs2010+opencv 2.4.6.0

    特征:eigenface

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

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

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

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

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

    最终结果:

    核心:face detection(detectAndDraw)

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

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

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

    1.1 BrowseDir.h

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #pragma once  
    2. #include "direct.h"  
    3. #include "string.h"  
    4. #include "io.h"  
    5. #include "stdio.h"   
    6. #include <vector>  
    7. #include <iostream>  
    8. using namespace std;  
    9. class CBrowseDir  
    10. {  
    11. protected:  
    12.     char m_szInitDir[_MAX_PATH];  
    13.   
    14. public:  
    15.     CBrowseDir();  
    16.     bool SetInitDir(const char *dir);  
    17.     bool BeginBrowse(const char *filespec);  
    18.     vector<char*> BeginBrowseFilenames(const char *filespec);  
    19.   
    20. protected:  
    21.     bool BrowseDir(const char *dir,const char *filespec);  
    22.     vector<char*> GetDirFilenames(const char *dir,const char *filespec);  
    23.     virtual bool ProcessFile(const char *filename);  
    24.     virtual void ProcessDir(const char *currentdir,const char *parentdir);  
    25. };  



    1.2 BrowseDir.cpp

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #include "BrowseDir.h"  
    2. #include "direct.h"  
    3. #include "string.h"  
    4. #include "io.h"  
    5. #include "stdio.h"   
    6. #include <vector>  
    7. #include <iostream>  
    8. using namespace std;  
    9.   
    10. CBrowseDir::CBrowseDir()  
    11. {  
    12.     getcwd(m_szInitDir,_MAX_PATH);  
    13.     int len=strlen(m_szInitDir);  
    14.     if (m_szInitDir[len-1] != '\')  
    15.         strcat(m_szInitDir,"\");  
    16. }  
    17.   
    18. bool CBrowseDir::SetInitDir(const char *dir)  
    19. {  
    20.     if (_fullpath(m_szInitDir,dir,_MAX_PATH) == NULL)  
    21.         return false;  
    22.   
    23.     if (_chdir(m_szInitDir) != 0)  
    24.         return false;  
    25.     int len=strlen(m_szInitDir);  
    26.     if (m_szInitDir[len-1] != '\')  
    27.         strcat(m_szInitDir,"\");  
    28.   
    29.     return true;  
    30. }  
    31.   
    32. vector<char*>CBrowseDir:: BeginBrowseFilenames(const char *filespec)  
    33. {  
    34.     ProcessDir(m_szInitDir,NULL);  
    35.     return GetDirFilenames(m_szInitDir,filespec);  
    36. }  
    37.   
    38. bool CBrowseDir::BeginBrowse(const char *filespec)  
    39. {  
    40.     ProcessDir(m_szInitDir,NULL);  
    41.     return BrowseDir(m_szInitDir,filespec);  
    42. }  
    43.   
    44. bool CBrowseDir::BrowseDir(const char *dir,const char *filespec)  
    45. {  
    46.     _chdir(dir);  
    47.     long hFile;  
    48.     _finddata_t fileinfo;  
    49.     if ((hFile=_findfirst(filespec,&fileinfo)) != -1)  
    50.     {  
    51.         do  
    52.         {  
    53.             if (!(fileinfo.attrib & _A_SUBDIR))  
    54.             {  
    55.                 char filename[_MAX_PATH];  
    56.                 strcpy(filename,dir);  
    57.                 strcat(filename,fileinfo.name);  
    58.                 cout << filename << endl;  
    59.                 if (!ProcessFile(filename))  
    60.                     return false;  
    61.             }  
    62.         } while (_findnext(hFile,&fileinfo) == 0);  
    63.         _findclose(hFile);  
    64.     }  
    65.     _chdir(dir);  
    66.     if ((hFile=_findfirst("*.*",&fileinfo)) != -1)  
    67.     {  
    68.         do  
    69.         {  
    70.             if ((fileinfo.attrib & _A_SUBDIR))  
    71.             {  
    72.                 if (strcmp(fileinfo.name,".") != 0 && strcmp  
    73.                     (fileinfo.name,"..") != 0)  
    74.                 {  
    75.                     char subdir[_MAX_PATH];  
    76.                     strcpy(subdir,dir);  
    77.                     strcat(subdir,fileinfo.name);  
    78.                     strcat(subdir,"\");  
    79.                     ProcessDir(subdir,dir);  
    80.                     if (!BrowseDir(subdir,filespec))  
    81.                         return false;  
    82.                 }  
    83.             }  
    84.         } while (_findnext(hFile,&fileinfo) == 0);  
    85.         _findclose(hFile);  
    86.     }  
    87.     return true;  
    88. }  
    89.   
    90. vector<char*> CBrowseDir::GetDirFilenames(const char *dir,const char *filespec)  
    91. {  
    92.     _chdir(dir);  
    93.     vector<char*>filename_vec;  
    94.     filename_vec.clear();  
    95.   
    96.     long hFile;  
    97.     _finddata_t fileinfo;  
    98.     if ((hFile=_findfirst(filespec,&fileinfo)) != -1)  
    99.     {  
    100.         do  
    101.         {  
    102.             if (!(fileinfo.attrib & _A_SUBDIR))  
    103.             {  
    104.                 char *filename = new char[_MAX_PATH];  
    105.                 strcpy(filename,dir);  
    106.                 //int st = 0;   while (dir[st++]!='');  
    107.                 strcat(filename,fileinfo.name); //filename[st]='';  
    108.                 filename_vec.push_back(filename);  
    109.             }  
    110.         } while (_findnext(hFile,&fileinfo) == 0);  
    111.         _findclose(hFile);  
    112.     }  
    113.     _chdir(dir);  
    114.     if ((hFile=_findfirst("*.*",&fileinfo)) != -1)  
    115.     {  
    116.         do  
    117.         {  
    118.             if ((fileinfo.attrib & _A_SUBDIR))  
    119.             {  
    120.                 if (strcmp(fileinfo.name,".") != 0 && strcmp  
    121.                     (fileinfo.name,"..") != 0)  
    122.                 {  
    123.                     char subdir[_MAX_PATH];  
    124.                     strcpy(subdir,dir);  
    125.                     strcat(subdir,fileinfo.name);  
    126.                     strcat(subdir,"\");  
    127.                     ProcessDir(subdir,dir);  
    128.                     return GetDirFilenames(subdir,filespec);  
    129.                 }  
    130.             }  
    131.         } while (_findnext(hFile,&fileinfo) == 0);  
    132.         _findclose(hFile);  
    133.     }  
    134.     return filename_vec;  
    135. }  
    136.   
    137. bool CBrowseDir::ProcessFile(const char *filename)  
    138. {  
    139.     return true;  
    140. }  
    141.   
    142. void CBrowseDir::ProcessDir(const char   
    143.     *currentdir,const char *parentdir)  
    144. {  
    145. }  



    1.3 StatDir.h

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #pragma once  
    2. #include "browsedir.h"  
    3. class CStatDir:public CBrowseDir  
    4. {  
    5. protected:  
    6.     int m_nFileCount;   //保存文件个数  
    7.     int m_nSubdirCount; //保存子目录个数  
    8.   
    9. public:  
    10.     CStatDir()  
    11.     {  
    12.         m_nFileCount=m_nSubdirCount=0;  
    13.     }  
    14.   
    15.     int GetFileCount()  
    16.     {  
    17.         return m_nFileCount;  
    18.     }  
    19.   
    20.     int GetSubdirCount()  
    21.     {  
    22.         return m_nSubdirCount-1;  
    23.     }  
    24.   
    25. protected:  
    26.     virtual bool ProcessFile(const char *filename)  
    27.     {  
    28.         m_nFileCount++;  
    29.         return CBrowseDir::ProcessFile(filename);  
    30.     }  
    31.   
    32.     virtual void ProcessDir  
    33.         (const char *currentdir,const char *parentdir)  
    34.     {  
    35.         m_nSubdirCount++;  
    36.         CBrowseDir::ProcessDir(currentdir,parentdir);  
    37.     }  
    38. };  


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

    2.1 Prehelper.h

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //preprocessing helper  
    2. //@ Author : Rachel-Zhang  
    3.   
    4. #include "opencv2/core/core.hpp"  
    5. #include "opencv2/highgui/highgui.hpp"  
    6. #include "opencv2/contrib/contrib.hpp"  
    7. #include <cv.h>  
    8. #include <vector>  
    9. #include <utility>  
    10. using namespace cv;  
    11. using namespace std;  
    12.   
    13. void normalizeone(const char* dir,IplImage* standard);  
    14.   
    15. void CutImg(IplImage* src, CvRect rect,IplImage* res);  
    16.   
    17. vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,  
    18.     CascadeClassifier& nestedCascade,  
    19.     double scale, bool tryflip,bool draw );  
    20.   
    21. IplImage* DetectandExtract(Mat& img, CascadeClassifier& cascade,  
    22.     CascadeClassifier& nestedCascade,  
    23.     double scale, bool tryflip);  
    24.   
    25. int read_img(const string& dir, vector<Mat> &images);  
    26.   
    27. vector<pair<char*,Mat>>  read_img(const string& dir);  



    2.2 Prehelper.cpp

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #include "Prehelper.h"  
    2. #include "BrowseDir.h"  
    3. #include "StatDir.h"  
    4.   
    5. #include <opencv2/core/core.hpp>  
    6. #include <opencv2/highgui/highgui.hpp>  
    7. #include <cv.h>  
    8. using namespace cv;  
    9.   
    10. void normalizeone(const char* dir,IplImage* standard)  
    11. {  
    12.     CStatDir statdir;  
    13.     if (!statdir.SetInitDir(dir))  
    14.     {  
    15.         puts("Dir not exist");  
    16.         return;  
    17.     }  
    18.     vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*");  
    19.     int i;  
    20.     for (i=0;i<file_vec.size();i++)  
    21.     {  
    22.         IplImage* cur_img = cvLoadImage(file_vec[i],CV_LOAD_IMAGE_GRAYSCALE);  
    23.         //IplImage*cur_gray = cvCreateImage(cvGetSize(cur_img),cur_img->depth,1);  
    24.         cvResize(cur_img,standard,CV_INTER_AREA);  
    25.         //cvCvtColor(standard,cur_gray,CV_RGB2GRAY);  
    26.         //      cvNamedWindow("cur_img",CV_WINDOW_AUTOSIZE);  
    27.         //      cvNamedWindow("standard",CV_WINDOW_AUTOSIZE);  
    28.         //      cvShowImage("cur_img",cur_img);  
    29.         //      cvShowImage("standard",standard);  
    30.         //      cvWaitKey();  
    31.         cvSaveImage(file_vec[i],cur_img);  
    32.     }  
    33. }  
    34.   
    35. void CutImg(IplImage* src, CvRect rect,IplImage* res)  
    36. {  
    37.     CvSize imgsize;  
    38.     imgsize.height = rect.height;  
    39.     imgsize.width = rect.width;  
    40.     cvSetImageROI(src,rect);  
    41.     cvCopy(src,res);  
    42.     cvResetImageROI(res);  
    43. }  
    44.   
    45. int read_img(const string& dir, vector<Mat> &images)  
    46. {  
    47.     CStatDir statdir;  
    48.     if (!statdir.SetInitDir(dir.c_str()))  
    49.     {  
    50.         cout<<"Direct "<<dir<<"  not exist!"<<endl;  
    51.         return 0;  
    52.     }  
    53.     int cls_id = dir[dir.length()-1]-'0';  
    54.     vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*");  
    55.     int i,s = file_vec.size();  
    56.     for (i=0;i<s;i++)  
    57.     {  
    58.         Mat graymat = imread(file_vec[i],0);  
    59.         //graymat.reshape(1,1);//flatten to one row  
    60.         images.push_back(graymat);  
    61.     }  
    62.     return s;  
    63. }  
    64.   
    65. vector<pair<char*,Mat>>  read_img(const string& dir)  
    66. {  
    67.     CStatDir statdir;  
    68.     pair<char*,Mat> pfi;  
    69.     vector<pair<char*,Mat>> Vp;  
    70.     if (!statdir.SetInitDir(dir.c_str()))  
    71.     {  
    72.         cout<<"Direct "<<dir<<"  not exist!"<<endl;  
    73.         return Vp;  
    74.     }  
    75.     int cls_id = dir[dir.length()-1]-'0';  
    76.     vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*");  
    77.     int i,s = file_vec.size();  
    78.     for (i=0;i<s;i++)  
    79.     {  
    80.         pfi.first = file_vec[i];  
    81.         pfi.second = imread(file_vec[i]);  
    82.         Vp.push_back(pfi);  
    83.     }  
    84.     return Vp;  
    85. }  
    86.   
    87. vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,  
    88.     CascadeClassifier& nestedCascade,  
    89.     double scale, bool tryflip, bool draw )  
    90. {  
    91.     int i = 0;  
    92.     double t = 0;  
    93.     vector<Rect> faces, faces2;  
    94.     const static Scalar colors[] =  { CV_RGB(0,0,255),  
    95.         CV_RGB(0,128,255),  
    96.         CV_RGB(0,255,255),  
    97.         CV_RGB(0,255,0),  
    98.         CV_RGB(255,128,0),  
    99.         CV_RGB(255,255,0),  
    100.         CV_RGB(255,0,0),  
    101.         CV_RGB(255,0,255)} ;  
    102.     Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );  
    103.   
    104.     cvtColor( img, gray, CV_BGR2GRAY );  
    105.     resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );  
    106.     equalizeHist( smallImg, smallImg );  
    107.   
    108.     t = (double)cvGetTickCount();  
    109.     cascade.detectMultiScale( smallImg, faces,  
    110.         1.1, 2, 0  
    111.         |CV_HAAR_FIND_BIGGEST_OBJECT  
    112.         //|CV_HAAR_DO_ROUGH_SEARCH  
    113.         //|CV_HAAR_SCALE_IMAGE  
    114.         ,  
    115.         Size(30, 30) );  
    116.     if( tryflip )  
    117.     {  
    118.         flip(smallImg, smallImg, 1);  
    119.         cascade.detectMultiScale( smallImg, faces2,  
    120.             1.1, 2, 0  
    121.             |CV_HAAR_FIND_BIGGEST_OBJECT  
    122.             //|CV_HAAR_DO_ROUGH_SEARCH  
    123.             //|CV_HAAR_SCALE_IMAGE  
    124.             ,  
    125.             Size(30, 30) );  
    126.         for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++ )  
    127.         {  
    128.             faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));  
    129.         }  
    130.     }  
    131.     t = (double)cvGetTickCount() - t;  
    132.     printf( "detection time = %g ms ", t/((double)cvGetTickFrequency()*1000.) );  
    133.     if(draw)  
    134.     {  
    135.         for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )  
    136.         {  
    137.             Mat smallImgROI;  
    138.             vector<Rect> nestedObjects;  
    139.             Point center;  
    140.             Scalar color = colors[i%8];  
    141.             int radius;  
    142.   
    143.             double aspect_ratio = (double)r->width/r->height;  
    144.             rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)),  
    145.                 cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)),  
    146.                 color, 3, 8, 0);  
    147.             if( nestedCascade.empty() )  
    148.                 continue;  
    149.             smallImgROI = smallImg(*r);  
    150.             nestedCascade.detectMultiScale( smallImgROI, nestedObjects,  
    151.                 1.1, 2, 0  
    152.                 |CV_HAAR_FIND_BIGGEST_OBJECT  
    153.                 //|CV_HAAR_DO_ROUGH_SEARCH  
    154.                 //|CV_HAAR_DO_CANNY_PRUNING  
    155.                 //|CV_HAAR_SCALE_IMAGE  
    156.                 ,  
    157.                 Size(30, 30) );  
    158.             //draw eyes  
    159.             //         for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )  
    160.             //         {  
    161.             //             center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);  
    162.             //             center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);  
    163.             //             radius = cvRound((nr->width + nr->height)*0.25*scale);  
    164.             //             circle( img, center, radius, color, 3, 8, 0 );  
    165.             //         }  
    166.         }  
    167.         cv::imshow( "result", img );  
    168.     }  
    169.     return faces;  
    170. }  
    171.   
    172. IplImage* DetectandExtract(Mat& img, CascadeClassifier& cascade,  
    173.     CascadeClassifier& nestedCascade,  
    174.     double scale, bool tryflip)  
    175. {  
    176.     vector<Rect> Rvec = detectAndDraw(img,cascade,nestedCascade,scale,tryflip,0);  
    177.     int i,maxxsize=0,id=-1,area;  
    178.     for (i=0;i<Rvec.size();i++)  
    179.     {  
    180.         area = Rvec[i].width*Rvec[i].height;  
    181.         if(maxxsize<area)  
    182.         {  
    183.             maxxsize = area;  
    184.             id = i;  
    185.         }  
    186.     }  
    187.     IplImage* transimg = cvCloneImage(&(IplImage)img);  
    188.     if(id!=-1)  
    189.     {  
    190.         CvSize imgsize;  
    191.         imgsize.height = Rvec[id].height;  
    192.         imgsize.width = Rvec[id].width;  
    193.         IplImage* res = cvCreateImage(imgsize,transimg->depth,transimg->nChannels);  
    194.         CutImg(transimg,Rvec[id],res);  
    195.   
    196.         return res;  
    197.     }  
    198.     return NULL;  
    199. }  



    3. 主函数

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //Detect.cpp  
    2. //Preprocessing - Detect, Cut and Save  
    3. //@Author : Rachel-Zhang  
    4.   
    5. #include "opencv2/objdetect/objdetect.hpp"  
    6. #include "opencv2/highgui/highgui.hpp"  
    7. #include "opencv2/imgproc/imgproc.hpp"  
    8.   
    9. #include <cctype>  
    10. #include <iostream>  
    11. #include <iterator>  
    12. #include <stdio.h>  
    13. #include "BrowseDir.h"  
    14. #include "StatDir.h"  
    15. #include "Prehelper.h"  
    16.   
    17. using namespace std;  
    18. using namespace cv;  
    19. #define CAM 2  
    20. #define PHO 1  
    21. #define K 5  
    22.   
    23. string cascadeName = "E:/software/opencv2.4.6.0/data/haarcascades/haarcascade_frontalface_alt.xml";  
    24. string nestedCascadeName = "E:/software/opencv2.4.6.0/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";  
    25.   
    26. int main( )  
    27. {  
    28.     CvCapture* capture = 0;  
    29.     Mat frame, frameCopy, image;  
    30.     string inputName;  
    31.     bool tryflip = false;  
    32.     int mode;  
    33.     CascadeClassifier cascade, nestedCascade;   
    34.     double scale = 1.0;  
    35.     if( !cascade.load( cascadeName ) ||!nestedCascade.load( nestedCascadeName))  
    36.     {  
    37.         cerr << "ERROR: Could not load classifier cascade or nestedCascade" << endl;//若出现该问题请去检查cascadeName,可能是opencv版本路径问题  
    38.         return -1;  
    39.     }  
    40.   
    41. //  printf("select the mode of detection:  1: from picture  2: from camera ");  
    42. //  scanf("%d",&mode);  
    43.     char** pics = (char**) malloc(sizeof*pics);  
    44.   
    45.     /************************************************************************/  
    46.     /*                                  detect face and save                                    */  
    47.     /************************************************************************/  
    48.     int i,j;  
    49.     cout<<"detect and save..."<<endl;  
    50.     const char dir[256] = "D:\Face_recognition\pic\";   
    51.         string cur_dir;  
    52.         char id[5];  
    53.     for(i=1; i<=K; i++)  
    54.     {  
    55.         cur_dir = dir;  
    56.         _itoa(i,id,10);  
    57.         cur_dir.append("color\");  
    58.         cur_dir.append(id);  
    59.         vector<pair<char*,Mat>> imgs=read_img(cur_dir);  
    60.         for(j=0;j<imgs.size();j++)  
    61.         {  
    62.             IplImage* res = DetectandExtract(imgs[j].second,cascade,nestedCascade,scale,tryflip);  
    63.             if(res)  
    64.                 cvSaveImage(imgs[j].first,res);  
    65.         }  
    66.     }  
    67.     return 0;  
    68. }  



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

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

    from: http://blog.csdn.net/abcjennifer/article/details/20396869

  • 相关阅读:
    Netty 零拷贝(一)Linux 零拷贝
    启动服务(上)服务端:NioServerSocketChannel 是什么时候激活的
    Reactor 模型(一)基本并发编程模型
    并发编程(三)Promise, Future 和 Callback
    并发编程(二)concurrent 工具类
    并发编程(一)同步类容器和并发类容器
    Executor(二)ThreadPoolExecutor、ScheduledThreadPoolExecutor 及 Executors 工厂类
    Executor(一)ExecutorService 线程池
    Java NIO系列教程(一四) Files
    Java NIO系列教程(一三) Path
  • 原文地址:https://www.cnblogs.com/GarfieldEr007/p/5354728.html
Copyright © 2011-2022 走看看