opencv linux 人脸识别,OpenCV 人脸识别

本文介绍了如何使用Eigenface算法实现人脸检测,首先通过CBrowseDir和Prehelper辅助函数处理图像数据,自动检测人脸并将其存入数据库,然后进行人脸建模,为后续的人脸识别做准备。实验数据包含15人,每人20个样本,展示了从人脸数据库到人脸检测与初步识别的完整流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

进行人脸检测,将检测出的人脸存入数据库2

对数据库2进行人脸建模

在测试集上进行recognition

本篇实现第一步:

进行人脸检测,将检测出的人脸存入数据库2

环境:vs2010+opencv 2.4.6.0

特征:eigenface

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

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

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

文章所用代码打包下载:

到Linux公社资源站下载:

------------------------------------------分割线------------------------------------------

具体下载目录在 /2016年资料/6月/18日/OpenCV 人脸识别/

------------------------------------------分割线------------------------------------------

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

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

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

1bcf55478a5a45922b33b97811209fc1.png

最终结果:

a77919bb377d59c67efc0bcc00c94e62.png

核心:face detection(detectAndDraw)

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

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

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

{

protected:

char m_szInitDir[_MAX_PATH];

public:

CBrowseDir();

bool SetInitDir(const char *dir);

bool BeginBrowse(const char *filespec);

vector BeginBrowseFilenames(const char *filespec);

protected:

bool BrowseDir(const char *dir,const char *filespec);

vector 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 false;

if (_chdir(m_szInitDir) != 0)

return false;

int len=strlen(m_szInitDir);

if (m_szInitDir[len-1] != '\\')

strcat(m_szInitDir,"\\");

return true;

}

vectorCBrowseDir:: 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 CBrowseDir::GetDirFilenames(const char *dir,const char *filespec)

{

_chdir(dir);

vectorfilename_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

#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);

vector>  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;

}

vectorfile_vec = statdir.BeginBrowseFilenames("*.*");

int i;

for (i=0;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 &images)

{

CStatDir statdir;

if (!statdir.SetInitDir(dir.c_str()))

{

cout<

return 0;

}

int cls_id = dir[dir.length()-1]-'0';

vectorfile_vec = statdir.BeginBrowseFilenames("*.*");

int i,s = file_vec.size();

for (i=0;i

{

Mat graymat = imread(file_vec[i],0);

//graymat.reshape(1,1);//flatten to one row

images.push_back(graymat);

}

return s;

}

vector>  read_img(const string& dir)

{

CStatDir statdir;

pair pfi;

vector> Vp;

if (!statdir.SetInitDir(dir.c_str()))

{

cout<

return Vp;

}

int cls_id = dir[dir.length()-1]-'0';

vectorfile_vec = statdir.BeginBrowseFilenames("*.*");

int i,s = file_vec.size();

for (i=0;i

{

pfi.first = file_vec[i];

pfi.second = imread(file_vec[i]);

Vp.push_back(pfi);

}

return Vp;

}

vector detectAndDraw( Mat& img, CascadeClassifier& cascade,

CascadeClassifier& nestedCascade,

double scale, bool tryflip, bool draw )

{

int i = 0;

double t = 0;

vector 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;i

{

area = Rvec[i].width*Rvec[i].height;

if(maxxsize

{

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

#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 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<

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> imgs=read_img(cur_dir);

  for(j=0;j

{

IplImage* res = DetectandExtract(imgs[j].second,cascade,nestedCascade,scale,tryflip);

if(res)

cvSaveImage(imgs[j].first,res);

}

}

return 0;

}

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

557d3ca7f7cd0857788074b54a4257ee.png

0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值