人脸识别C++程序代码 - 副本_第1页
人脸识别C++程序代码 - 副本_第2页
人脸识别C++程序代码 - 副本_第3页
人脸识别C++程序代码 - 副本_第4页
人脸识别C++程序代码 - 副本_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、/ AppDesignDlg.cpp : implementation file/#include stdafx.h#include AppDesign.h#include AppDesignDlg.h#include #include #include Select.h#include CvvImage.h#define MAX_POINT 200#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CAboutDlg dialog used for App About

2、using namespace std;CvCapture * m_Video; / opencv库的指针,从视频获取图像int nFrmNum=0; /定义第nFrmNum帧,初始化为0,自动增值,nFrmNum是帧控件的关联变量,帧控件的ID为IDC_FRAMNUM/定义几个重要的全局变量int nTrainFaces =0; /训练图像的数目,即人脸库中有n张人脸int nEigens =0; /自己取的主要特征值数目(在提取特征脸的时候用到的参数)IplImage* faceImgArr =0; /指向训练人脸和测试人脸的指针(在学习和识别阶段指向不同)CvMat* personNum

3、TruthMat=0; /人脸图像的ID号IplImage* pAvgTrainImg =0; /训练人脸数据的平均值IplImage* eigenVectArr =0; /投影矩阵,也即主特征向量CvMat* eigenValMat =0; /特征值CvMat* projectedTrainFaceMat=0; /训练图像的投影CvMat* trainPersonNumMat=0;/*以下是自定义函数的声明,具体定义会在下方,cv开头的是OPENCV自带的库函数*/void learn(); int loadFaceImgArr(char *filename);void recognize2

4、(IplImage *img);void doPCA();void storeTrainingData();int loadTrainingData(CvMat* pTrainPersonNumMat);int findNearestNeighbor(float* projectedtestFace);/用字符串时一定要把using namespace std;写在前面,否则不能用,下面是用于显示的字符串CvHaarClassifierCascade* cascade=NULL; /OPENcv的分类器文件进行人脸检测,此函数是一个匹配函数,根据不同的分类器(tree、stump)进行不同的匹

5、配,返回整形值,具体参考/*以下是MFC框架代码,在我们用鼠标进行搭建框架的时候自动生成*/class CAboutDlg : public Cdialogpublic:CAboutDlg();/ Dialog Data/AFX_DATA(CAboutDlg)enum IDD = IDD_ABOUTBOX ;/AFX_DATA/ ClassWizard generated virtual function overrides/AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); / DD

6、X/DDV support/AFX_VIRTUAL/ Implementationprotected:/AFX_MSG(CAboutDlg)/AFX_MSGDECLARE_MESSAGE_MAP();CAboutDlg:CAboutDlg() : CDialog(CAboutDlg:IDD)/AFX_DATA_INIT(CAboutDlg)/AFX_DATA_INITvoid CAboutDlg:DoDataExchange(CDataExchange* pDX)CDialog:DoDataExchange(pDX);/AFX_DATA_MAP(CAboutDlg)/AFX_DATA_MAPB

7、EGIN_MESSAGE_MAP(CAboutDlg, CDialog)/AFX_MSG_MAP(CAboutDlg)/ No message handlers/AFX_MSG_MAPEND_MESSAGE_MAP()/ CAppDesignDlg dialogCAppDesignDlg:CAppDesignDlg(CWnd* pParent /*=NULL*/): CDialog(CAppDesignDlg:IDD, pParent)/AFX_DATA_INIT(CAppDesignDlg)/ NOTE: the ClassWizard will add member initializat

8、ion here/AFX_DATA_INIT/ Note that LoadIcon does not require a subsequent DestroyIcon in Win32m_hIcon = AfxGetApp()-LoadIcon(IDR_MAINFRAME);pCapture = NULL;m_totalfrm = 0;m_curfrm = 0;m_stop = false;loadxml=false;m_src = NULL;m_times =0;void CAppDesignDlg:DoDataExchange(CDataExchange* pDX)CDialog:DoD

9、ataExchange(pDX);/AFX_DATA_MAP(CAppDesignDlg)/DDX_Control(pDX, IDC_PROGRESS1, m_progress);/AFX_DATA_MAPDDX_Control(pDX, IDC_PROGRESS1, m_progress);BEGIN_MESSAGE_MAP(CAppDesignDlg, CDialog)/AFX_MSG_MAP(CAppDesignDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, OnOpen

10、File)ON_WM_TIMER()ON_BN_CLICKED(IDC_BUTTON5, OnStop)ON_WM_CTLCOLOR()/AFX_MSG_MAPON_BN_CLICKED(IDC_BUTTON2, &CAppDesignDlg:OnBnClickedButton2)ON_BN_CLICKED(IDC_BUTTON3, &CAppDesignDlg:OnBnClickedButton3)END_MESSAGE_MAP()/ CAppDesignDlg message handlersBOOL CAppDesignDlg:OnInitDialog()CDialog:OnInitDi

11、alog();/ Add About. menu item to system menu./ IDM_ABOUTBOX must be in the system command range.ASSERT(IDM_ABOUTBOX & 0xFFF0) = IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR);pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);/ Set the icon for this dialog. The framework does thi

12、s automatically/ when the applications main window is not a dialogSetIcon(m_hIcon, TRUE);/ Set big iconSetIcon(m_hIcon, FALSE);/ Set small icon/ TODO: Add extra initialization herereturn TRUE; / return TRUE unless you set the focus to a controlvoid CAppDesignDlg:OnSysCommand(UINT nID, LPARAM lParam)

13、if (nID & 0xFFF0) = IDM_ABOUTBOX)CAboutDlg dlgAbout;dlgAbout.DoModal();elseCDialog:OnSysCommand(nID, lParam);/ If you add a minimize button to your dialog, you will need the code below/ to draw the icon. For MFC applications using the document/view model,/ this is automatically done for you by the f

14、ramework.void CAppDesignDlg:OnPaint() / OnPaint是WM_PAINT消息的消息处理函数, 是CWnd的类成员,负责响应WM_PAINT消息if (IsIconic()CPaintDC dc(this); / device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);/ Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon =

15、GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;/ Draw the icondc.DrawIcon(x, y, m_hIcon);elseCDialog:OnPaint();/ The system calls this to obtain the cursor to display while the user drags/ the minimized win

16、dow.HCURSOR CAppDesignDlg:OnQueryDragIcon()return (HCURSOR) m_hIcon;/*这个程序的思路是,每33毫秒,就调用opencv获取摄像头的图像资料,并更新到界面上,让用户看起来是录像,实时的感觉,其实就是每33毫秒更新一次图片,然后载入头像资料进行识别*/*“打开摄像头”控件的相关代码OnOpenFile() */void CAppDesignDlg:OnOpenFile() / OnOpenFile()是“打开摄像头”这个控件的控制事件,也就是其函数,m_Video是控件的变量 /* 调用opencv打开视频*/m_Video =

17、 cvCaptureFromCAM(-1); / cvCaptureFromCAM(-1)是opencv的库函数,用来从视频中获取图像,直接调用,这里也是界面与摄像头的接口if (!m_Video)AfxMessageBox(无法打开摄像头); / AfxMessageBox这个函数是MFC中弹出消息框的函数,直接调用return;/cascade是级联if(!cascade)string cascade_name = haarcascade_frontalface_alt.xml;cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name

18、.c_str(), 0, 0, 0);/*启动计时器*/SetTimer(1,33,NULL);/*上面的内容基本都是MFC的框架代码,下面函数开始是自定义的函数了*/在控件中显示图片,第一个参数是要显示的图片,第二个参数是控件的IDvoid CAppDesignDlg:show_pic(IplImage *t,int nID) / int nID在这里是形参,而不是具体的IDCDC *pDC = GetDlgItem(nID)-GetDC();HDC hDC= pDC-GetSafeHdc();CRect rect;GetDlgItem(nID)-GetClientRect(&rect);C

19、vvImage img;img.CopyOf(t,3);img.DrawToHDC(hDC,&rect); ReleaseDC(pDC);/*获得图像兴趣区域,并且保存为tmp.jpg, pImg是待处理图像, CvRect roi是确定一个矩形区域roi */void GetSubImage(IplImage *pImg, CvRect roi)/基于给定的矩形设置图像的ROI,即获取感兴趣的图像cvSetImageROI(pImg,roi);/保存图像到指定文件tmp.jpgcvSaveImage(tmp.jpg,pImg);/释放图像pImg中被设定的感兴趣区域ROI,与cvSetIma

20、geROI相对应。cvResetImageROI(pImg);/这个函数主要是识别开始检测到的人脸,是人脸识别的入口函数void RecgnizeRoi(IplImage *img,char *a)int i, nTestFaces=0; / 测试的人脸数float* projectedTestFace=0; /训练的人脸数?projectedTestFace=(float*)cvAlloc(nEigens*sizeof(float); /cvAlloc是opencv中用于内存管理的函数/for (i=0;idata.iiNearest;/ char *itoa(int value, char

21、 *string, int radix);作用是把一整数转换为字符串。value: 待转化的整数;radix: 是基数的意思,即先将value转化为radix进制的数,范围介于2-36,比如10表示10进制,16表示16进制;* string: 保存转换后得到的字符串,和函数返回值相同,也就是说,最后的图片存储称aitoa(nearest,a,10); /检测和识别的入口,头像识别核心代码void CAppDesignDlg:Detect_Draw(IplImage *pImg)bool bFirstFace = TRUE;string strFirstFace = ;/一个颜色数组,这个数组

22、定义了一些颜色值 用这些颜色依次圈出不同的人脸,在最后画圆来圈出人脸的那句代码中 cvCircle( img, center, radius, colorsi%8, 3, 8, 0 );中的color的数值。static CvScalar colors = 0,0,255, /蓝色0,128,255,0,255,255,0,255,0,255,128,0,255,255,0,255,0,0,255,0,255;/先把识别到的学号初始化为空namelist=; 源代码不知道有没有/调用opencv创建存储空间(为NAMELIST)CvMemStorage* storage = cvCreateM

23、emStorage(0);double scale = 1.8;/函数IplImage* cvCreateImage( CvSize size, int depth, int channels ); 创建头并分配数据,参数意义:size 图像宽、高;depth 图像元素的位深度;channels每个元素(像素)通道数.可以是 1, 2, 3 或 4.通道是交叉存取的IplImage* gray = cvCreateImage( cvSize(pImg-width,pImg-height), 8, 1 );/仍然是这个函数,对目标图进行设置和分配空间(gray是原图)IplImage* smal

24、l_img = cvCreateImage( cvSize( cvRound (pImg-width/scale),/int cvRound (double value)对一个double型的数进行四舍五入,并返回一个整型数!cvRound (pImg-height/scale),8, 1 );int i;/灰度化,cvCvtColor 是Opencv里的颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。具体参见cvCvtColor( pImg, gray, CV_BGR2GRAY );/归一化尺度,函数cvResize 重新调整图像src(或它的RO

25、I),使它精确匹配目标dst(或其ROI),src源图像;dst 目标图;interpolation 修改、插补的方法,取值如下:CV_INTER_LINEAR 是其默认方法,为双线性插值。cvResize( gray, small_img, CV_INTER_LINEAR );/直方图均衡,函数原型为void cvEqualizeHist( const CvArr* src, CvArr* dst ); 用来使灰度图象直方图均衡化。具体见cvEqualizeHist( small_img, small_img );/删除存储空间,与上面创建空间对应。cvClearMemStorage( st

26、orage ); /如果识别成功,就标识出来。if( cascade ) 又是级联/人脸检测函数,cvHaarDetectObjects函数用来检测图像中的目标,具体见/*级联分类器训练中采用的检测目标的尺寸*/);/检测人脸返回矩形人脸 /*使用针对某目标物体训练的级联分类器在图像中找到包含目标物体的矩形区域,并且将这些区域作为一序列的矩形框返回。CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,cvSize(40, 40) );for(

27、i = 0; i total : 0); i+ ) CvRect* r,通过方形左上角坐标和方形的高和宽来确定一个矩形区域,nt x; /* 方形的左上角的x-坐标 */;int y; /* 方形的左上角的y-坐标*/;int width; /* 宽 */;int height; /* 高 */CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); /访问人脸库中的第i个元素CvPoint pt1, pt2; /OpenCV的基本数据类型之一,表示坐标为整数的二维点r-x = r-x * scale;r-y = r-y * scale;r-width =

28、r-width * scale;r-height = r-height * scale;pt1.x = r-x;pt1.y = r-y;pt2.x = r-x + r-width;pt2.y = r-y + r-height;/矩形将人脸框起来。cvRectangle是 OpenCV里面的绘图函数,四个参数分别代表(图像,矩形的两个点,线条颜色,线条粗细,线条类型,小数点位数)cvRectangle( pImg, pt1, pt2, colorsi%8, 3, 8, 0);GetSubImage(gray, *r);/获取图片/读入图像,参数分别为(被读入图像的文件名(包括后缀),指定读入图像

29、的颜色和深度,CV_LOAD_IMAGE_GRAYSCALE是单通道),具体见IplImage *gray1=cvLoadImage(tmp.jpg,CV_LOAD_IMAGE_GRAYSCALE);/创建头并分配数据(图像宽,高,depth 图像元素的位深度,每个元素(像素)通道数)IplImage *dst=cvCreateImage(cvSize(96,96),8,1);/函数cvResize 重新调整图像src(或它的ROI),使它精确匹配目标dst(或其ROI) cvResize(gray1,dst,CV_INTER_NN); / CV_INTER_NN - 最近-邻居插补的修改方法

30、 char a20=; /识别检测到的人脸,调用了之前定义的函数RecgnizeRoi(dst,a);/ 应该是有关输出的对齐方式的CvFont font1;CvPoint wp;wp.x = pt1.x ;wp.y = pt1.y-10 ; cvInitFont(&font1, CV_FONT_ITALIC, 0.75F, 0.75F, 0, 3, 8);/将识别结果显示出来/函数 cvPutText 将具有指定字体的和指定颜色的文本加载到图像中。加载到图像中的文本被感兴趣的矩形框圈定。(输入图像,显示字符串,第一个字符左下角的坐标,字体结构初始化,文本的字体颜色)cvPutText(pIm

31、g, a, wp, &font1, colors2);/在控件上显示出识别了几个人CString str;/Format是CString类的一个成员函数,它通过格式操作使任意类型的数据转换成一个字符串。str.Format(%d,faces-total);/返回窗口中指定参数ID的子元素的句柄,可以通过返回的句柄对窗口内的子元素进行操作。GetDlgItem(IDC_PEOPLENUM)-SetWindowText(str);/系统释放存储空间cvReleaseImage( &gray );cvReleaseImage( &small_img );每33毫秒调用一下这个模块/定时器函数,nID

32、Event是定时器标识符void CAppDesignDlg:OnTimer(UINT nIDEvent) IplImage* image; IplImage* motion = 0; /*调用opencv 提取视频图像数据*/读取摄像头一帧, cvQueryFrame(m_Video)从摄像头或者文件中抓取并返回一帧image=cvQueryFrame(m_Video);/*帧数计算器*/下面四行代码是将帧数显示在控件上/*帧数计算器*/nFrmNum+;CString str; /str就是那个变化的帧值,同str几个人是一样一样的/*把帧数在界面显示出来*/str.Format(%d,n

33、FrmNum); /显示函数/返回窗口中指定参数ID的子元素的句柄,可以通过返回的句柄对窗口内的子元素进行操作。上面共识别几个人的那个控件也用到了这条语句,功能是一样的。GetDlgItem(IDC_FRAMNUM)-SetWindowText(str);/ cvGetTickCount()是测量运行时间的函数,在程序段的开始和结束时两次使用cvGetTickCount(),然后将两次的差除以cvGetTickFrequency()后就可以获得程序段的以微秒us为单位的运行时间,而 *1000表示精确到ms double tt =(double)cvGetTickCount();/如果加载了训

34、练结果,则可以开始检测识别了,调用函数Detect_Draw, Detect_Draw这个函数是头像识别函数if(loadxml)Detect_Draw(image);/得到没帧的时间消耗tt=(double)cvGetTickCount()-tt;str.Format(%lf,tt/(cvGetTickFrequency()*1000.); /把处理耗时显示在界面上GetDlgItem(IDC_TIME)-SetWindowText(str);/ 把识别到的人的学号显示在界面的列表中GetDlgItem(IDC_NAMELIST)-SetWindowText(namelist);/控件上显示

35、图片/*把摄像头的图像显示到图片空间上*/show_pic(image,IDC_SHOWIMG);CDialog:OnTimer(nIDEvent);/ /OnTimer(UINT nIDEvent)是定时器的函数,为什么要在这里写这句?/这个暂停按钮的代码void CAppDesignDlg:OnStop() / TODO: Add your control notification handler code herem_stop=!m_stop;if (m_stop)KillTimer(1); /销毁定时器 else SetTimer(1,33,NULL); /创建定时器,这里是一个33毫

36、秒触发1次的定时器/继续void CAppDesignDlg:OnOK()/ TODO: Add extra validation herecvReleaseCapture( &pCapture );CDialog:OnOK();/控制控件的显示颜色,OnCtlColor有关参见pDC是一个CDC指针,是用来绘图和显示的pWnd是一个cWnd指针,指向控件(不确定)nCtlColor则是用来区别不同的调用的HBRUSH CAppDesignDlg:OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) HBRUSH hbr = CDialog:OnCt

37、lColor(pDC, pWnd, nCtlColor);if (pWnd-GetDlgCtrlID() = IDC_FRAMNUM)pDC-SetTextColor(RGB(255,0, 0); /帧控件的字体颜色 if (pWnd-GetDlgCtrlID() = IDC_TIME)pDC-SetTextColor(RGB(255, 0, 0); /时间控件的字体颜色 / TODO: Return a different brush if the default is not desiredreturn hbr;/训练样本的函数void CAppDesignDlg:Train()int i

38、;/文件解析,得到文件列表或者称,加载训练图像集nTrainFaces为训练图像的数目;导入faceImgArr(指向训练人脸的指针),解析得到train.txtnTrainFaces=loadFaceImgArr(train.txt);if(nTrainFaces2)fprintf(stderr,Need 2 or more training facesn,Input file contains only %dn, nTrainFaces);return;/设置进度条,m_progress是进度条的关联参数, 1和 nTrainFaces分别是起始和结束的位置m_progress.SetRa

39、nge(1, nTrainFaces);/PCA 提取特征,进行主成分分析/*int nTrainFaces =0; /训练图像的数目,即人脸库中有n张人脸int nEigens =0; /自己取的主要特征值数目(在提取特征脸的时候用到的参数)IplImage* faceImgArr =0; /指向训练人脸和测试人脸的指针(在学习和识别阶段指向不同)CvMat* personNumTruthMat=0; /人脸图像的ID号IplImage* pAvgTrainImg =0; /训练人脸数据的平均值IplImage* eigenVectArr =0; /投影矩阵,也即主特征向量CvMat* ei

40、genValMat =0; /特征值CvMat* projectedTrainFaceMat=0; /训练图像的投影CvMat* trainPersonNumMat=0;*/doPCA();/ projectedTrainFaceMat是训练图像的投影;cvCreateMat是创建矩阵函数,参数分别为(矩阵行数,矩阵列数,元素类型),下面的分别是(训练图像数目,特征值数目,32位数据)projectedTrainFaceMat=cvCreateMat(nTrainFaces,nEigens,CV_32FC1);for (i=0;idata.fl+i*nEigens); m_progress.S

41、etPos(i+1); /进度条的位置加1Sleep(100); /程序暂停1毫秒/将训练结果保存到文件storeTrainingData();/解析文件列表,就是读文件 /加载txt文件的列举的图像int loadFaceImgArr(char *filename)FILE* imgListFile=0;char imgFilename512;int iFace, nFaces=0;/open the input fileimgListFile=fopen(filename,r);/统计人脸数while(fgets(imgFilename,512,imgListFile) +nFaces;/

42、fgets: read a line of files strings to store in imgFilename/function fgets stops if meets a line break or read number of parameter 2rewind(imgListFile);/get the pointer to the start position of a file/分配人脸图像存储空间和人脸ID号存储空间faceImgArr=(IplImage*)cvAlloc(nFaces*sizeof(IplImage*);personNumTruthMat=cvCrea

43、teMat(1,nFaces,CV_32SC1);for (iFace=0;iFacedata.i+iFace,imgFilename);/将图片保存在数组中/加载人脸图像faceImgArriFace=cvLoadImage(imgFilename,CV_LOAD_IMAGE_GRAYSCALE);fclose(imgListFile);return nFaces;/PCA提取人脸特征void doPCA()int i;CvTermCriteria calcLimit; / CvTermCriteria criteria:停止迭代的标准,传入;CvSize faceImgSize; /人脸框

44、的大小/set the number of eigenvalues to usenEigens=nTrainFaces-1; /特增值的数目/分配内存空间faceImgSize.width=faceImgArr0-width; / faceImgArr测试人脸的宽faceImgSize.height=faceImgArr0-height; / faceImgArr测试人脸的高eigenVectArr=(IplImage*)cvAlloc(sizeof(IplImage*)*nEigens); /分配个数为住特征值个数/按照设定的特征值,从小到大,依次给主特征向量分配内存空间(测试人脸框的大小,

45、深度,通道数)for (i=0;idata.fl);/保存训练结果函数void storeTrainingData()CvFileStorage* fileStorage;int i;/create a file-storage interface cvOpenFileStorage:为读写数据打开文件存储器fileStorage=cvOpenFileStorage(facedata.xml,0,CV_STORAGE_WRITE);/存储特征值,投影矩阵,平均矩阵等训练结果cvWriteInt(fileStorage,nEigens,nEigens); 特征值数目cvWriteInt(fileStorage,nTrainFaces,nTrainFaces); 训练图像数目cvWrite(fileStorage,trainPersonNumMat,personNumTruthMat,cvAttrList(0,0); 人脸图像ID号cvWrite(fileStorage,eigenValMat,eigenValMat,cvAttrList(0,0); 特征值cvWrite(fileStorage,projectedTrainFaceMat,projectedTrainFaceMat,cvAttrList(0,0); 训练图像的投影cvWrite(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论