本文实现基于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
- #pragma once
- #include "direct.h"
- #include "string.h"
- #include "io.h"
- #include "stdio.h"
- #include <vector>
- #include <iostream>
- using namespace std;
- class CBrowseDir
- {
- protected:
- char m_szInitDir[_MAX_PATH];
- public:
- CBrowseDir();
- bool SetInitDir(const char *dir);
- bool BeginBrowse(const char *filespec);
- vector<char*> BeginBrowseFilenames(const char *filespec);
- protected:
- bool 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 <vector>
- #include <iostream>
- 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 false;
- if (_chdir(m_szInitDir) != 0)
- return false;
- int 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
- {
- protected:
- int m_nFileCount; //保存文件个数
- int m_nSubdirCount; //保存子目录个数
- public:
- CStatDir()
- {
- m_nFileCount=m_nSubdirCount=0;
- }
- int GetFileCount()
- {
- return m_nFileCount;
- }
- int GetSubdirCount()
- {
- return m_nSubdirCount-1;
- }
- protected:
- virtual 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 <cv.h>
- #include <vector>
- #include <utility>
- using namespace cv;
- using namespace std;
- void normalizeone(const char* dir,IplImage* standard);
- void CutImg(IplImage* src, CvRect rect,IplImage* res);
- vector<Rect> 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<Mat> &images);
- vector<pair<char*,Mat>> read_img(const string& dir);
2.2 Prehelper.cpp
- #include "Prehelper.h"
- #include "BrowseDir.h"
- #include "StatDir.h"
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <cv.h>
- 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<file_vec.size();i++)
- {
- IplImage* cur_img = cvLoadImage(file_vec[i],CV_LOAD_IMAGE_GRAYSCALE);
- //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<Mat> &images)
- {
- CStatDir statdir;
- if (!statdir.SetInitDir(dir.c_str()))
- {
- cout<<"Direct "<<dir<<" 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;i<s;i++)
- {
- Mat graymat = imread(file_vec[i],0);
- //graymat.reshape(1,1);//flatten to one row
- images.push_back(graymat);
- }
- return s;
- }
- vector<pair<char*,Mat>> read_img(const string& dir)
- {
- CStatDir statdir;
- pair<char*,Mat> pfi;
- vector<pair<char*,Mat>> Vp;
- if (!statdir.SetInitDir(dir.c_str()))
- {
- cout<<"Direct "<<dir<<" 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;i<s;i++)
- {
- pfi.first = file_vec[i];
- pfi.second = imread(file_vec[i]);
- Vp.push_back(pfi);
- }
- return Vp;
- }
- vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,
- CascadeClassifier& nestedCascade,
- double scale, bool tryflip, bool draw )
- {
- int i = 0;
- double t = 0;
- vector<Rect> 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<Rect>::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<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
- {
- Mat smallImgROI;
- vector<Rect> 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<Rect>::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<Rect> Rvec = detectAndDraw(img,cascade,nestedCascade,scale,tryflip,0);
- int i,maxxsize=0,id=-1,area;
- for (i=0;i<Rvec.size();i++)
- {
- area = Rvec[i].width*Rvec[i].height;
- if(maxxsize<area)
- {
- maxxsize = area;
- id = i;
- }
- }
- IplImage* transimg = cvCloneImage(&(IplImage)img);
- if(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 <cctype>
- #include <iostream>
- #include <iterator>
- #include <stdio.h>
- #include "BrowseDir.h"
- #include "StatDir.h"
- #include "Prehelper.h"
- using namespace std;
- using namespace cv;
- #define CAM 2
- #define PHO 1
- #define K 5
- string 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 = false;
- int mode;
- CascadeClassifier cascade, nestedCascade;
- double scale = 1.0;
- if( !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..."<<endl;
- const 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);
- vector<pair<char*,Mat>> imgs=read_img(cur_dir);
- for(j=0;j<imgs.size();j++)
- {
- IplImage* res = DetectandExtract(imgs[j].second,cascade,nestedCascade,scale,tryflip);
- if(res)
- cvSaveImage(imgs[j].first,res);
- }
- }
- return 0;
- }
正确的输出就是一系列人脸检测时间,且原文件夹内的图片变成了检测出的人脸(如上面结果图所示)。
文章所用代码打包链接:http://download.csdn.net/detail/abcjennifer/7047853
from: http://blog.csdn.net/abcjennifer/article/details/20396869
opencv 人脸识别 (一)训练样本的处理的更多相关文章
-
OpenCV人脸识别的原理 .
OpenCV人脸识别的原理 . 在之前讲到的人脸测试后,提取出人脸来,并且保存下来,以供训练或识别是用,提取人脸的代码如下: void GetImageRect(IplImage* orgImage, ...
-
opencv人脸识别代码
opencv人脸识别C++代码 /* * Copyright (c) 2011,2012. Philipp Wagner <bytefish[at]gmx[dot]de>. * Relea ...
-
opencv人脸识别提取手机相册内人物充当数据集,身份识别学习(草稿)
未写完 采用C++,opencv+opencv contrib 4.1.0 对手机相册内人物opencv人脸识别,身份识别学习 最近事情多,介绍就先不介绍了 photocut.c #include & ...
-
OpenCV人脸识别Eigen算法源码分析
1 理论基础 学习Eigen人脸识别算法需要了解一下它用到的几个理论基础,现总结如下: 1.1 协方差矩阵 首先需要了解一下公式: 共公式可以看出:均值描述的是样本集合的平均值,而标准差描述的则是样本 ...
-
OpenCV人脸识别LBPH算法源码分析
1 背景及理论基础 人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能,该术语需要和人脸检测进行区分,人脸检测是在一张图片中把人脸定位出来,完成的是搜寻 ...
-
opencv 人脸识别
背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从 ...
-
OpenCV 人脸识别 C++实例代码
#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include & ...
-
opencv 人脸识别 (二)训练和识别
上一篇中我们对训练数据做了一些预处理,检测出人脸并保存在\pic\color\x文件夹下(x=1,2,3,...类别号),本文做训练和识别.为了识别,首先将人脸训练数据 转为灰度.对齐.归一化,再放入 ...
-
OpenCv 人脸识别 基础
#include <opencv2\opencv.hpp> #include <iostream> using namespace std; int main() { // 摄 ...
随机推荐
-
一款轻量级移动web开发框架
本帖最后由 yangzhu230 于 2013-9-11 00:39 编辑 如果我说要推荐zepto你肯定说“切,这地球人都知道,又一个标题党” 不卖关子,开门见山我推荐的是[百度]的GMU GMU是 ...
-
【转】DataGridView之为每行前面添加序号
//最简单的方法是在Datagridview的事件RowPostPaint事件下面添加如下代码即可 private void dataGridView1_RowPostPaint(object sen ...
-
ADO.NET中连接SQL Sever
1.在配置文件中定义数据库连接信息. 在配置文件*.config中添加这段代码在<configuration>与</configuration>之间: <connecti ...
-
iOS 字体设置
使用无衬线字体 body { font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif; } iOS 4 ...
-
IOS基础开发二(iphone计算器)
今天做了个iphone的小例子计算器:才用mvc设计模式 项目目录: 代码如下: CalculatorViewController:(MVC的控制器) // CalculatorViewControl ...
-
使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱
1.当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的某一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释来精确配置. 2.示例 ...
-
Elastic 技术栈之 Logstash 基础
title: Elastic 技术栈之 Logstash 基础 date: 2017-12-26 categories: javatool tags: java javatool log elasti ...
-
Ubuntu 安装phpMyAdmin + 配置nginx
0x01 安装phpMyAdmin ``` sudo apt-get install phpmyadmin ``` 0x02 添加链接 ``` sudo ln -s /usr/share/phpMyA ...
-
解决win10“cmd自动弹出一闪而过”问题的方法
1.禁用CMD win+Q gpedit 打开组策略 用户配置--管理模板--系统--阻止访问命令提示符--已启用. 2.启用PowerShell PS:需要使用CMD时可用powershell代替: ...
-
PHP学习笔记1
1.什么是PHP? Hypertext Preprocessor(超文本预处理语言). 是脚本语言. 是最流行的网站开发语言. 2.PHP能做什么? 可以生成动态页面内容. 可以创建.打开.读取.写入 ...