资料简介
一、写作背景
基于人脸识别的考勤系统主要用于对公司员工的出勤统计,员工签到时需要通过摄像头采集到员工面部照片,再通过人脸识别算法从采集到的照片中取得特征值并与数据库中预先存入的员工人脸照片的特征值进行分析比较,识别成功后报出员工的姓名,则考勤成功。本文主要介绍的是考勤机后台管理程序中的人脸信息录入部分的设计,也就是通过摄像头进行员工面部信息的采集,每个员工采集若干张照片,需要保存到数据库中,同时需要通过一定的算法保存其对应的特征值。本文就对一张照片的采集与显示的关键步骤展开阐述,并给出在VisualC++6.0实现的必要代码。
二、软件支持
VFW(VideoforWindows)是Microsoft1992年推出的关于数字视频的一个软件包,它提供了一系列应用程序编程接口,它使应用程序对视频的采集和播放变得非常容易实现。VFW给程序员提供VBX和AVICap窗口类的编程工具,使程序员能通过发送消息来采集、播放和编辑视频剪辑。现在的计算机用户不必专门安装VFW,当用户在安装Win2dows时,安装程序会自动地安装配置视频所需的组件,如设备驱动程序、视频压缩程序等。
VisualC++6.0在支持VFW方面提供有vfw32.lib、msacm32.lib、winmm.lib等类似的库,特别是它提供了功能强大、简单易行、类似于MCIWnd的窗口类AVICap。AVICap为应用程序提供了一个简单的、基于消息的接口,使之能访问视频和波形音频硬件,并能在捕获视频流到硬盘上的过中进行控制。AVICap支持实时的视频流捕获和单帧捕获并提供对视频源的控制。它能直接访问视频缓冲区,不需要生成中间文件,实时性很强,效率很高。同时,它也可捕获数字视频并保存到文件。在捕获视频之前需要创建一个捕获窗口,所有的捕获操作及其设置都以它为基础。用AVICap窗口类创建的窗口被称为“捕获窗口”。捕获窗口功能强大可以进行视频录像(将一视频流和音频流捕获到一个AVI文件中)或是画面截取。在人脸识别考勤系统中主要用到画面截取功能。下面是截取画面时需要用到的几个设置操作:
①动态地同视频采集设备连接或断开;
②以Overlay或Preview模式对输入的视频流进行实时显示;
a.预览(Preview)模式:该模式把从捕获硬件传来的数据送入系统内存并且在捕获窗口中使用GDI函数来显示这些数据帧。此种模式要占用一定的系统资源,一般的视频采集设备都是通过这种显示方式工作的。
b.叠加(Overlay)模式:该模式的视频显示不经过VGA卡,而是将其输出信号与VGA的输出信号合并,形成组合信号显示在计算机的监视器上。在该模式下所捕捉的视频数据的显示不需要占用系统资源。
③设置捕获速率;
④显示控制视频源、视频格式、视频压缩的对话框;
⑤将捕获的一个单帧图像保存为DIB格式的文件。
三、实现原理
采集照片时捕获一帧图像,在临时文件夹中保存为DIB格式的位图文件,然后通过文件类的读操作将该位图文件转化为二进制的数据同时获取数据的长度,再调用数据库接口函数把转化得到的二进制数据和数据的长度存入数据库,zui后删除临时文件夹里的位图文件;显示照片时调用数据库访问接口函数从数据库取出照片的二进制数据和数据的长度,再通过文件类的写操作在临时文件夹中生成位图文件用来显示,显示完后删除该文件。至于把图片显示到界面上,只需把临时文件夹里的位图文件通过绘图函数显示可以了。特征值的算法不在本文讨论之列。
四、实现流程
五、关键程序代码
(一)采集照片
1.在头文件中定义摄像头相关的控制成员变量
HWNDm-hWndCap;PP定义视频捕捉窗口
CAPDRIVERCAPSm-CapDriverCaps;PP捕获驱动器的性能
CAPSTATUSm-CapStatus;PP捕获窗口的当前状态
2.启动摄像头
//创建视频捕捉窗口
m-hWndCap=capCreateCaptureWindow(-T(”人脸录入”),WS-CHILD|WS-VISIBLE,CAMERA-LEFT,CAMERA-TOP,CAMERA-WIDTH,CAMERAHEIGHT,m-hWnd,0);
/**个参数捕捉窗口的名称,第二个参数捕捉窗口的样式,第三、四个参数捕捉窗口的左上角的位置坐标,第五、六个参数捕捉窗口的宽度和高度,第七、八个参数分别是捕捉窗口的父窗口的句柄和编号。*/
/*将捕捉窗与默认摄像头连接,如果连接成功则获得捕获驱动的性能,放在结构变量m-Cap2DriverCaps中*/
if(capDriverConnect(m-hWndCap,0))
capDriverGetCaps(m-hWndCap,&m-CapDriver2Caps,sizeof(CAPDRIVERCAPS));
//如果摄像头支持叠加显示模式则启用叠加显示模式
if(m-CapDriverCaps.fHasOverlay)
capOverlay(m-hWndCap,TRUE);
else
{
capPreviewRate(m-hWndCap,66);//设置预览模式的显示速率
capPreview(m-hWndCap,TRUE);//启用预览模式
}
至此,如果摄像头正常安装了驱动,就能正常工作了。
3.采集并预览照片
界面上左边是捕捉窗口,右边留有和捕捉窗口同样大小的区域用于预览或显示捕捉到的照片。
capGrabFrameNoStop(m-hWndCap);//捕捉照片且捕捉窗口画面不停止
capFileSaveDIB(m-hWndCap,”\employee.bmp”);//保存捕捉到的照片
//获得照片句柄用于在界面显示捕捉到的照片
m-hPhotoBmp=(HBITMAP)LoadImage(AfxGetIn2stanceHandle(),”\employee.bmp”,IMAGE-BITMAP,0,0,LR-CREATEDIBSECTION|LR-LOADFROMFILE);
/**个参数取应用程序实例句柄,第二个参数照片的路径及名称,第三个参数照片的类型,第四、五个参数照片的宽和高,为零则使用图像默认大小,第六个参数LR-CREATEDIB2SECTION:当图像类型为IMAGE-BITMAP时,使函数返回一个DIB位图,而不是一个兼容的位图。LRLOADFROMFILE:根据照片的路径和名称装载图像。*/
Invalidate(FALSE);PP重绘窗口显示照片
为了在界面显示照片还需添加绘图函数On2Paint():
//在界面添加picture控件,命名为IDC-STATICPICTURE,并图片控件
CPaintDCdcPicture(GetDlgItem(IDC-STATIC-PIC2TURE));
CRectrectPic;//定义矩形区域
GetDlgItem(IDC-STATIC-PICTURE)->GetClien2tRect(&rectPic);//在图片控件上
CDCmemDC;//建立与显示设备兼容的内存设备场境
memDC.CreateCompatibleDC(&dcPicture);
memDC.SelectObject(m-hPhotoBmp);//将位图选入内存场境
//调用缺省的窗口过程来为没有处理的窗口消息提供缺省的处理
CWnd::DefWindowProc(WM-PAINT,(WPARAM)memDC.m-hDC,0);
dcPicture.BitBlt(rectPic.left,rectPic.top,rectPic.Width(),rectPic.Height(),&memDC,0,0,SRCCOPY);
/*显示位图。前四个参数分别显示图片的左上角顶点的位置坐标,和图片的宽高,第五个参数表示源设备场景的地址,第六七两个参数表示显示图片的左上角顶点在源设备环境的矩形区域中的坐标,zui后一个参数表示将源矩形图象直接复制到目标矩形上。*/
4.保存照片到数据库
先把捕捉到的位图文件转化成二进制数据,然后通过接口函数保存到数据库中。对数据库的操作请参考DAO或ADO编程。
CFilebmpFile;//定义文件类变量
if(bmpFile.Open(”\employee.bmp”,CFile::mo2deRead))//读模式打开照片文件
{LONGnLength=bmpFile.GetLength();//获得照片的文件长度
unsignedchar3pData=newunsignedchar[nLength];//申请内存空间
//如果申请到空间就读数据到缓冲区,即得到二进制数据
bmpFile.Read(pData,nLength);//读照片文件到缓冲区
bmpFile.Close();//关闭文件
}
Employee.SavePicture(EmployeeID,&pData,nLength);//对数据库访问接口
bmpFile.Remove(”\employee.bmp”);//删除临时文件夹里生成的位图文件
delete[]pData;//释放内存中申请的缓冲区
5.断开摄像头
capDriverDisconnect(m-hWndCap);//断开摄像头(二)显示数据库中的照片前面已经实现照片的预览功能,现在只要从数据库取出照片数据,生成位图文件,取得位图的句柄显示问题就解决了。
//通过数据库接口得到照片的文件长度(nLength)和二进制照片数据的地址pData。
unsignedchar3pData=NULL;//定义字符型指针变量
employee.GetPicture(&pData,&nLength);//取照片数据
//如果取到照片数据则生成位图文件
CFileoutFile(”\employee.bmp”,CFile::mode2Create|CFile::modeWrite);
outFile.WriteHuge((LPSTR)pData,nLength);
outFile.Close();
//取得生成图片的句柄
六、总结
VisualC++提供的AVICap窗口类为VC的数字视频采集提供了很大的方便,极大增强了VC多媒体程序开发的能力。本文所描述的照片采集的过程便是基于此技术,并且已经在人脸识别考勤系统中作为人脸录入模块使用,该模块负责在系统zui初运行时对人脸信息采集或是对已有人脸信息进行更新时使用。经过多次测试该模块运行稳定,可以满足需求。
参考文献:
[1]刘玮.VisualC++视频P音频开发实用工程案例精选[M].北京:人民邮电出版社,2005.
[2]王洪涛.深入剖析VisualC++编程技术及应用实例[M].北京:人民邮电出版社,2003.
[3]张力.VisualC++编程Effectiveprogramming[M].北京:人民邮电出版社,2002.
[4](美)DAVIDJ.KRUGLINSKI.VisualC++技术内幕[M].北京:清华大学出版社,2004.
[5]陈瑶,刘洋.Windows环境下实时视频捕捉、压缩的实现[J].沈阳化工学院学报,2004(1)