本文实现基于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

  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. public:
  14. CBrowseDir();
  15. bool SetInitDir(const char *dir);
  16. bool BeginBrowse(const char *filespec);
  17. vector<char*> BeginBrowseFilenames(const char *filespec);
  18. protected:
  19. bool BrowseDir(const char *dir,const char *filespec);
  20. vector<char*> GetDirFilenames(const char *dir,const char *filespec);
  21. virtual bool ProcessFile(const char *filename);
  22. virtual void ProcessDir(const char *currentdir,const char *parentdir);
  23. };

1.2 BrowseDir.cpp

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

1.3 StatDir.h

  1. #pragma once
  2. #include "browsedir.h"
  3. class CStatDir:public CBrowseDir
  4. {
  5. protected:
  6. int m_nFileCount;   //保存文件个数
  7. int m_nSubdirCount; //保存子目录个数
  8. public:
  9. CStatDir()
  10. {
  11. m_nFileCount=m_nSubdirCount=0;
  12. }
  13. int GetFileCount()
  14. {
  15. return m_nFileCount;
  16. }
  17. int GetSubdirCount()
  18. {
  19. return m_nSubdirCount-1;
  20. }
  21. protected:
  22. virtual bool ProcessFile(const char *filename)
  23. {
  24. m_nFileCount++;
  25. return CBrowseDir::ProcessFile(filename);
  26. }
  27. virtual void ProcessDir
  28. (const char *currentdir,const char *parentdir)
  29. {
  30. m_nSubdirCount++;
  31. CBrowseDir::ProcessDir(currentdir,parentdir);
  32. }
  33. };

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

2.1 Prehelper.h

  1. //preprocessing helper
  2. //@ Author : Rachel-Zhang
  3. #include "opencv2/core/core.hpp"
  4. #include "opencv2/highgui/highgui.hpp"
  5. #include "opencv2/contrib/contrib.hpp"
  6. #include <cv.h>
  7. #include <vector>
  8. #include <utility>
  9. using namespace cv;
  10. using namespace std;
  11. void normalizeone(const char* dir,IplImage* standard);
  12. void CutImg(IplImage* src, CvRect rect,IplImage* res);
  13. vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,
  14. CascadeClassifier& nestedCascade,
  15. double scale, bool tryflip,bool draw );
  16. IplImage* DetectandExtract(Mat& img, CascadeClassifier& cascade,
  17. CascadeClassifier& nestedCascade,
  18. double scale, bool tryflip);
  19. int read_img(const string& dir, vector<Mat> &images);
  20. vector<pair<char*,Mat>>  read_img(const string& dir);

2.2 Prehelper.cpp

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

3. 主函数

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

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

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

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

opencv 人脸识别 (一)训练样本的处理的更多相关文章

  1. OpenCV人脸识别的原理 .

    OpenCV人脸识别的原理 . 在之前讲到的人脸测试后,提取出人脸来,并且保存下来,以供训练或识别是用,提取人脸的代码如下: void GetImageRect(IplImage* orgImage, ...

  2. opencv人脸识别代码

    opencv人脸识别C++代码 /* * Copyright (c) 2011,2012. Philipp Wagner <bytefish[at]gmx[dot]de>. * Relea ...

  3. opencv人脸识别提取手机相册内人物充当数据集,身份识别学习(草稿)

    未写完 采用C++,opencv+opencv contrib 4.1.0 对手机相册内人物opencv人脸识别,身份识别学习 最近事情多,介绍就先不介绍了 photocut.c #include & ...

  4. OpenCV人脸识别Eigen算法源码分析

    1 理论基础 学习Eigen人脸识别算法需要了解一下它用到的几个理论基础,现总结如下: 1.1 协方差矩阵 首先需要了解一下公式: 共公式可以看出:均值描述的是样本集合的平均值,而标准差描述的则是样本 ...

  5. OpenCV人脸识别LBPH算法源码分析

    1 背景及理论基础 人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能,该术语需要和人脸检测进行区分,人脸检测是在一张图片中把人脸定位出来,完成的是搜寻 ...

  6. opencv 人脸识别

      背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从 ...

  7. OpenCV 人脸识别 C++实例代码

    #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include & ...

  8. opencv 人脸识别 (二)训练和识别

    上一篇中我们对训练数据做了一些预处理,检测出人脸并保存在\pic\color\x文件夹下(x=1,2,3,...类别号),本文做训练和识别.为了识别,首先将人脸训练数据 转为灰度.对齐.归一化,再放入 ...

  9. OpenCv 人脸识别 基础

    #include <opencv2\opencv.hpp> #include <iostream> using namespace std; int main() { // 摄 ...

随机推荐

  1. xml基础学习笔记01

    注意:刚刚看了网上对于XML中的标签,节点和元素?到底应该怎么表述?起初我也有这个疑惑,现在我的想法是:下面出现node的应称作节点,节点对象.element应称作元素,毕竟这更符合英文的本意.至于标 ...

  2. Careercup - Microsoft面试题 - 5943729928011776

    2014-05-10 21:56 题目链接 原题: Suppose you get number of unique users every second from bing For eg, ,,,, ...

  3. hbuilder的aptana php插件无法提示命名空间之外函数和对象的解决办法

  4. cygwin chmod 失效

    问题背景 为了在 Cygwin 下使用之前最喜爱的 screen 命令, 安装 Cygwin 时就选上了 screen 来运行一把 ganiks.liu@MAMIS-Gaiks-Liu /tmp $ ...

  5. Codeforces Round #265 (Div. 1) C. Substitutes in Number dp

    题目链接: http://codeforces.com/contest/464/problem/C J. Substitutes in Number time limit per test 1 sec ...

  6. Leetcode#68 Text Justification

    原题地址 没有复杂的算法,纯粹的模拟题 先试探,计算出一行能放几个单词 然后计算出单词之间有几个空格,注意,如果空格总长度无法整除空格数,前面的空格长度通通+1 最后放单词.放空格,组成一行,加入结果 ...

  7. ios 缓存相关信息收集

    链接:http://www.cnblogs.com/pengyingh/category/353093.html 使用NSURLCache让本地数据来代替远程UIWebView请求 摘要: 原文作者: ...

  8. shadowmap 及优化

    对于子阴影的走样, 条纹 开zbias resterizeState zbias = 1000...大概这样 另一个方法是画背面 backface是指一个人肚子那面,后背那面 而不是肚子的里面那层 所 ...

  9. .Net 命名(委托,事件==)

    委托及参数命名: public delegate void ClickedEventHandler(object sender, ClickedEventArgs e); ClickedEventHa ...

  10. 《JavaScript DOM编程艺术》

    第2章JS语法关联数组在为新元素给出下标时,不必局限于整数数字.数组下标可以是字符串逻辑与&&只有两个操作数都是true时结果才为true逻辑或||只有两个操作数都是false时结果才 ...