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
- #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() { // 摄 ...
随机推荐
- C#新语法特性前瞻
今天逛微软的UserVoice site发现了几个有很有用,也很可能被添加到新版C#中的语法,当然也可能被推迟到下一版,拿出来给大家分享一下. 另外还没投票的可以去为自己最想要的新特性投票,有兴趣的可 ...
- 自动回复消息-微信公众平台开发4(asp.net)
接着上一节的processRequest 处理函数,代码如下: /// <summary> /// 处理微信发来的请求 /// </summary> /// ...
- .NET Framework 4.5、4.5.1 和 4.5.2 中的新增功能
.NET Framework 4.5.4.5.1 和 4.5.2 中的新增功能 https://msdn.microsoft.com/zh-cn/library/ms171868.aspx
- transitionend 事件的兼容
google :webkitTransitionEnd firefox :transitionend ie : MSTransitionEnd
- 如何用javascript正则表达式验证身份证号码是否合法
在用户注册页面有些需求要求的比较严格,需要对身份证js验证是否合法,通过此功能严格此系统软件,从而过滤到很多水客.下面就此实现方法给大家讲解下. 很多时候我们都是通过一组正则表达式来判断用户输入的身份 ...
- 剑指offer-17题
题目要求:输入一个表示整数的字符串,把该字符串转换成整数并输出.例如输入字符串"345",则输出整数345. 分析:这道题能够很好地反应出程序员的思维和编程习惯. 的确,自己编写的 ...
- 快速幂取模 分类: ACM TYPE 2014-08-29 22:01 95人阅读 评论(0) 收藏
#include<stdio.h> #include<stdlib.h> //快速幂算法,数论二分 long long powermod(int a,int b, int c) ...
- Scrum敏捷软件开发之技术实践——测试驱动开发TDD
重复无聊的定义 测试驱动开发,英文全称Test-Driven Development,简称TDD,是一种不同于传统软件开发流程的新型的开发方法.它要求在编写某个功能的代码之前先编写测试代码,然后只编写 ...
- __dict__和__slots__
__dict__: __slots__:
- 游戏引擎网络开发者的 64 做与不做 | Part 1 | 客户端方面
摘要:纵观过去 10 年的游戏领域,单机向网络发展已成为一个非常大的趋势.然而,为游戏添加网络支持的过程中往往存在着大量挑战,这里将为大家揭示游戏引擎网络开发者的 64 个做与不做. [编者按]时下, ...