人脸识别C程序代码.docx
《人脸识别C程序代码.docx》由会员分享,可在线阅读,更多相关《人脸识别C程序代码.docx(25页珍藏版)》请在冰豆网上搜索。
人脸识别C程序代码
〃AppDesigiiDlg.cpp:
implementationfile
#includeHstdafx.hn
#includeHAppDesign.hH
#includeHAppDesigiiDlg.hH
#include
#include
#includeHSelect.hH
#include"Cwlmag已h"#defineNIAX.POINT200#ifdef_DEBUG
^definenewDEBUG^NEW#imckfTHIS_FILE
staticcharTHIS_FILE[]=_FILE_;#endif
//CAboutDlgdialogusedforAppAboutusingnamespacestd;
CxCaptuie*m_Video;//opencv库的指针,从视频获取图像
mtnFnnNum=0;//定义第iiFniiNum帧,初始化为0,自动增值,iiFnnNum是帧控件的关联变量,帧控件的ID为LDC_FRAMNUM
////定义几个重要的全局变量
intnTrauiFaces=0;//训练图像的数日,即人脸库中有n张人脸
mtiiEigens=0;//自己取的主要特征值数日(在提取特征脸的时候用到的参数)
Ipllinage**facelingAir=0;//指向训练人脸和测试人脸的指针(在学习和识别阶段指向不
同)
CvMat*persoiiNumTi-utliNIat=0;//人脸图像的ID号
Ipllinage*pAvgTrauiImg=0;〃训练人脸数据的平均值
Ipllinage**eigenVectAir=0;//投影矩阵,也即主特征向量
CvMat*eigenValNIat=0;//特征值
CvMat*projectedTiaiiiFaceMat=0;//训练图像的投影
CvMat*tiainPersoiiNuniMat=0:
严以卜•是自定义函数的声明,具体定义会在卜方,CV开头的是OPENCV自带的库函数*/
voidleani();
mtloadFaceImgAn(char*filename);
voidiecognize2(lpllniage
voiddoPCAQ;
voidstoreTiainingData();
mtloadTiainmgData(CvMat**pTrauiPersoiiNumMat);
mtfiiidNearestNeighbor(float*projectedtestFace);
〃用字符串时一定要把usingnamespacestd;写在前面,否则不能用,下面是用于显示的字符串
CvHaarClassifierCascade*cascade=NULL;
//OPENcv的分类器文件进行人脸检测,此函数是一个匹配函数,根据不同的分类器(tree,stump)进行不同的匹配,返回整形值,具体参考
littp”/baike・so・c(nn/doc/6988QOS.html或http:
//www・docin・coni/p・:
L926s69na・htnil,是人脸检测中用到的_个很重要的函数
严以下是MFC框架代码,在我们用鼠标进行搭建框架的时候自动生成*/
classCAboutDlg:
publicCdialogpublic:
CAboutDlgQ;
//DialogData
//{{AFX.DATA(CAboutDlg)
enum{IDD=EDD_ABOUTBOX};
〃}}AFX_DATA
//ClassWizaidgeneratedvirtualfiinctionoverrides
//{{AFX_\TRTUAL(CAboutDlg)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport
//}}AFX_\TRTUAL
//Implementation
protected:
//{{AFX.MSG(CAboutDlg)
〃}}AFX_MSG
DECLARE_MESSAGE_MAP0
};
CAboutDlg:
:
CAboutDlgO:
CDialog(CAboutDlg:
:
IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)〃}}AFX_DATA_INIT
}
voidCAboutDlg:
:
DoDataExchange(CDataExchaiige*pDX){
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
EEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
//{{AFX_MSG_MAP(CAboiitDlg)
//Nomessagehandlers
〃}}AFX_MSG_MAP
END_MESSAGEJv!
AP0
〃CAppDesigiiDlgdialog
CAppDesigiiDlg:
:
CAppDesignDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CAppDesignDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CAppD亡signDlg)
//NOTE:
theClassWizaidwilladdmemberinitializationhere
//}}AFX_DATA_INIT
//NotethatLoadicondoesnotrequiieasubsequentDestioylconinWin32mjilcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
pCapture=NULL;
m.totalfim=0;
m^cuiirm=0;
m_stop=false;
loadxiiil=false;
m_src=NULL;
m.times=0;
}
voidCAppDesigiiDlg:
:
DoDataExchaiige(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX__DATA_MAP(CAppDesigiiDlg)
//DDX_Contiol(pDX,IDC_PROGRESS1.m_progiess);//}}AFX_DATA_MAP
DDX_Control(pDX,IDC_PROGRESS1,m_progress);
EEGIN_MESSAGE_MAP(CAppD亡signDlg.CDialog)
//{{AFX_MSG_MAP(CAppDesignDlg)
ON_WM_SYSCOMMAND0
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_EN_CLICKED(IDC_EUTTONI,OnOpeiiFile)
ON_WM_TIMER()
ON_EN_CLICKED(IDC_EUTTON5,OnStop)
ON_WM_CTLCOLOR0
〃}}AFX_MSG_MAP
ON_EN_CLICKED(IDC_EUTTON2,&CAppDesigiiDlg:
:
OnBnClickedButtoii2)
ON_BN_CLICKED(IDC_BUTTON3,&CAppDesigiiDlg:
:
OnBnClickedButton3)END_MESSAGE_MAP0
/〃////〃//〃/〃/////〃/〃/////〃/〃/////〃/〃/〃///////////////〃/〃/〃/////
HCAppDesigiiDlgmessagehandlers
BOOLCAppDesigiiDlg:
:
OiiInitDialog()
CDialog:
:
OnInitDialog();
//AddMAbout...nmenuitemtosystemmenu.
//LDM_ABOUTBOXmustbeinthesystemconunaiidrange.
ASSERT((IDM_ABOUTBOX&OxFFFO)==LDM_ABOUTBOX);ASSERT(IDM_ABOUTBOXCMenu*pSysMenu=GetSysteniMenu(FALSE);
if(pSysMenu!
=NULL)
CStringstrAboutMenu;strAboutMenu.LoadStrmg(IDS_ABOUTBOX);if(!
strAboutMenu.IsEmptyO)
pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING5IDM_ABOUTBOX,stiAboutMenu);
//Settheiconfortliisdialog.Theframeworkdoesthisautomatically//whentheapplication^mamwindowisnotadialogSetlcon(mjilcon,TRUE);//Setbigicon
Setlcon(mjilcon,FALSE);//Setsmallicon
//TODO:
Addextrainitializationhere
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol}voidCAppDesigiiDlg:
:
OnSysConmiand(UINTnLD.LPARAMIParam){
if((nID&OxFFFO)==IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModalQ;
}
else
{
CDialog:
:
OnSysConmiand(iiID5lPaiain);
}
}
HIfyouaddaininunizebuttontoyouidialog,youwillneedthecodebelow
//todrawtlieicon・ForMFCapplicationsusingthedocument/viewmodel,
//thisisautomaticallydoneforyoubytheframework・
voidCAppDesigiiDlg:
:
OiiPamt()//OnPaint是WM_PAINT消息的消息处理函数,是CWnd的类成员,负贵响应WM.PAINT消息
{
if(IsIconicQ)
{
CPamtDCdc(this);//devicecontextforpainting
SendMessage(\WIJCONERASEBKGND,(WPARAM)dc.GetSafeHdcQ.0);
//Centericoninclientrectangle
mtcxlcon=GetSysteniNIetrics(SM_CXICON);
mtcylcon=GetSysteniNIetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
mtx=(rect.Width()-cxlcon+1)/2;
iiitv=(rect.HeightQ-cylcon+1)/2;
//Drawtheicon
dc.DrawIcon(x,y;mjilcon);
}
else
{
CDialog:
:
OiiPaint();
}
}
//Thesystemcallsthistoobtainthecursortodisplaywhiletheuserdrags〃theminimizedwindow.
HCURSORCAppDesigiiDlg:
:
OnQueiyDragIcon()
{
return(HCURSOR)mjilcon;
}
严这个程序的思路是,每33亳秒,就调用opencv获取摄像头的图像资料,并更新到界面上,让用户看起来是录像,实时的感觉,其实就是每33亳秒更新一次图片,然后载入头像资料进行识别*/
/*“打开摄像头”控件的相关代码OnOpeiiFileO*/
voidCAppDesigiiDlg:
:
OnOpeiiFile()
//OnOpenFile()是“打开摄像头”这个控件的控制事件,也就是其函数,m.Video是控件的变量
/*调用opencv打开视频*/
//
m_Video=cvCaptureFromCAM(-l);
cvCaptureFromCAM(-1)是opencv的库函数,用来从视频中获
取图像,直接调用,这里也是界面与摄像头的接口
if(!
m_Video)
{
AfkMessageEox(”无法打开摄像头J;//AfxMessageBox这个函数是MFC中弹出消息框的函数,直接调用
retuni;
//cascade是级联
cascade)
stringcascade_name=Hhaarcascade_fiontalface_alt.xiiilH;
cascade=(CvHaaiClassifierCascade*)cvLoad(cascade_name.c_str(),0,0、0);
/*启动计时器*/
SetTmier(l,33.NULL);
/*****************上面的内容基本都是MFC的框架代码,下面函数开始是自定义的函数
Y****************************/
//intnID在这
〃在控件中显示图片,第一个参数是要显示的图片,第二个参数是控件的ID
voidCAppDesignDlg:
:
show_pic(IplImage*t,intnID)
里是形参,而
不是具体的
ID
CDC*pDC=GetDlgItem(nID)->GetDC();
HDChDC=pDC->GetSafeHdc();
CRectrect;
GetDlgItem(nID)->GetClientRect(&rect);
Cvvlmageimg;
img.CopyOf(t,3);
img.DravvToHDC(hDC,&rect);
ReleaseDC(pDC);
严获得图像兴趣区域,并且保存为tmp.jpg,plmg是待处理图像,CvRectroi是确定一个矩形区域roi*/
voidGetSubIiiiage(Ipinnage*plmg.CvRectroi)
〃基于给定的矩形设置图像的ROL即获取感兴趣的图像cvSetIinageROI(pImg,roi);
〃保存图像到指定文件tnip.jpg
cvSaveIinage(ntmp.jpg'\pIing);
//释放图像pimg中被设定的感兴趣区域ROI,与cvSetlmageROI相对应。
cvResetImageROI(pIing);
}
〃这个函数主要是识别开始检测到的人脸,是人脸识别的入11函数
voidRecgmzeRoi(IplIniage*img,char*a)
{
inti?
nTestFaces=O;//测试的人脸数
float*projectedTestFace=0;〃训练的人脸数?
?
?
piojectedTestFace=(float*)cvAlloc(iiEigens*sizeof(float));//cvAlloc是opencv中用于内存管理的函数
//for(i=O;i〃{
intiNearest,neaiest,tnitli;//定义iNearest为最相似的图片
///cvEigenDecompositeO®数作用是将人脸图像通过Eigenface变换矩阵,投射到子空间中,只有将待识别图像投影到PCA空间,然后才能识别。
函数的具体作用以及函数中的7个参数参见
cvEigeiiDecomposite(imgaiEigens,eigenVectAir,0.0,pA\rgTrauiImg.
projectedTestFace);
〃得到最相似的图片
iNearest=fiiidNeaiestNeighbor(projectedTestFace);neaiest=trauiPeisonNuinMat->data.i[iNeaiest];
〃}
//char*itoa(intvalue,char*string,intradix);作用是把一整数转换为字符;I;。
value:
待转化的整数;radix:
是基数的意思,即先将value转化为radix进制的数,范围介于2-36,比如10表示10进制,16表示16进制;*string:
保存转换后得到的字符串,和函数返回值相同,也就是说,最后的图片存储称a
itoa(nearest,a,10);
}
〃检测和识别的入头像识别核心代码
voidCAppDesigiiDlg:
:
Detect_Diaw(IplIniage*plmg)
{
boolbFirstFace=TRUE;
stiiiigstrFirstFace=
这个数组定义了-吃颜色值用这些颜色依次圈出不同的人脸,在
最后画圆来圈出人脸的那句代码*11cvCucle(ling,centei,radius,colois[i%8],3、&0);中的color的数值。
staticCvScalarcolois[]=
{
{{0,0,255}},〃蓝色
{{0,128,255}},
{{0,255,255}},{{0,255,0}},
{{255,128,0}},
{{255,255,0}},{{255,0,0}},
{{255,0,255}}
};
〃先把识别到的学号初始化为空
namelisz"";源代码不知道有没有
〃调用opencv创建存储空间(为NA5ELIST)
CvMemStorage*storage=cvCreateMemStoiage(O);
doublescale=1.8;
〃函数Ipllmage*cvCreateImage(CvSizesize,intdepth,intchannels);创建头并分配数据,参数意义:
size图像宽、高;depth图像元索的位深度;channels每个元索(像素)通道数•可以是1,2,3或4•通道是交叉存取的
Iplliuage*gray=cvCreateIinage(cvSize(pIing->widtli,pIing->height),8.1);
〃仍然是这个函数,对目标图进行设置和分配空间(gray是原图)
Iplliuage*smalLiing=cvCreateIniage(cvSize(cvRound(pling->widtlvscale),
//intcvRound(doublevalue)对一个double型的数进行四舍五入,并返回一个整型数!
cvRound(pling->height/scale)),
8,1);
inti;
〃灰度化,cvCvtColor是Opencv里的颜色空间转换函数,可以实现RGB颜色向HSWHSI等颜色空间的转换,也可以转换为灰度图像。
具体参见httD:
〃baike.so・com/doc/695061l.html。
cvCvtColor(plmg,gray,CV_BGR2GRAY);
〃归一化尺度,函数cvResize重新调整图像src(或它的ROI),使它精确匹配目标dst(或其ROI),src源图像;dst目标图;inte中olation修改、插补的方法,取值如下:
CV_INTER_LINEAR是其默认方法,为双线性插值。
cvResize(gray,smalLimg,CV_INTER_LINEAR);
〃直方图均衡,函数原型为voidcvEqualizeHist(constCvArr*src,CvArr*dst);用来使灰度图象|工方图均衡化。
具体见httD:
//baike・so・com/doc/1.548261・html。
cvEqualizeHist(smalLimg.smalLimg);
〃删除存储空间,与上面创建空间对应。
cxrClearMemStoiage(storage);
〃如果识别成功,就标识出来。
if(cascade)又是级联
〃人脸检测函数,cvHaarDetectObjects函数用来检测图像中的目标,具体见http:
//baik亡・so・com/doc/6835188.htnii。
严级联分类器训练中采用的检测目标的尺寸舟/);〃检测人脸返回矩形人脸广使用针对某目标物体训练的级联分类器在图像中找到包含目标物体的矩形区域,并且将这些区域作为一序列的矩形框返回。
CvSeq*faces=cvHaarDetectObjects(small_img.cascade,storage,
1.1,2,0严CV_HAAR_DO_CANNY_PRUNING*/,cvSize(40,40));
for(i=0;i<(faces?
faces->total:
0);i++)
{
CvRect*r,通过方形左上角坐标和方形的高和宽来确定一个矩形区域,ntx;/*方形的左上角的x•坐标*/;inty;/*方形的左上角的y•坐标*/;intwidth;/*宽*/;intheight;/*高*/
CvRect*r=(CvRect*)cvGetSeqElem(faces,i);〃访问人脸库中的第1个元索
CvPomtptl,pt2;//OpenCV的基本数据类型之一,表示坐标为整数的••维
八八
r->x=r->x*scale;
r->y=r->y*scale;
r->width=r->width*scale;
r->height=r->height*scale;
ptl.x=r->x;
ptl.y=r->y;
pt