4.1 OpenCV主要函数介绍
1) cvLoadImage 从文件中读取图像
IplImage*
cvLoadImage(const char* filename,int flags=CV_LOAD_IMAGE_COLOR );
函数cvLoadImage从指定文件读入图像,返回读入图像的指针。 其中filename是要被读入的文件的文件名;flags指定读入图像的颜色和深度。 2)cvSaveImage 保存图像到文件
int cvSaveImage( const char* filename, const CvArr* image );
函数cvSaveImage保存图像到指定文件。其中filename保存文件名。image
要保存的图像。 图像格式的的选择依赖于filename的扩展名,只有8位单通道或者3通道(通道顺序为'BGR' )可以使用这个函数保存。
3)cvQueryFrame从摄像头或者文件中抓取并返回一帧 IplImage* cvQueryFrame( CvCapture* capture );
函数cvQueryFrame从摄像头或者文件中抓取一帧,然后解压并返回这一帧。这个函数仅仅是函数cvGrabFrame和函数cvRetrieveFrame在一起调用的组合。返回的图像不可以被用户释放或者修改。其中capture视频获取结构。。
4)cvCaptureFromCAM 初始化摄像头
CvCapture* cvCaptureFromCAM( int index );
函数cvCaptureFromCAM给从摄像头的视频流分配和初始化CvCapture结构。
其中index要使用的摄像头索引。如果只有一个摄像头或者用哪个摄像头也无所谓,那使用参数-1应该便可以。
5)cvHaarDetectObjects 用来检测图像中的人脸区域 CVAPI(CvSeq*) cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade* cascade, CvMemStorage* storage,
double scale_factor CV_DEFAULT(1.1), int min_neighbors CV_DEFAULT(3), int flags CV_DEFAULT(0),
CvSize min_size CV_DEFAULT(cvSize(0,0)), CvSize max_size CV_DEFAULT(cvSize(0,0)));
用于快速检测人脸区域 ,便于提取得到人脸数据。其中image 为被检图像,cascade为 haar分类器级联的内部标识形式,storage 为用来存储检测到的一
序列候选目标矩形框的内存区域,scale_factor 在前后两次相继的扫描中,搜索窗口的比例系数,例如1.1指将搜索窗口依次扩大10%,min_neighbors 为构成检测目标的相邻矩形的最小个数(缺省-1),flags 为操作方式,min_size 为检测窗口的最小尺寸。缺省的情况下被设为分类器训练时采用的样本尺寸(人脸检测中缺省大小是~20×20)。 6)cvRectangle 绘制矩形
CVAPI(void) cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2,
CvScalar color, int thickness CV_DEFAULT(1), int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0));
绘制出检测到人脸区域并显示,便于使用者观看是否检测出人脸,。其中img 为图像,pt1 -- 矩形的一个顶点,pt2 -- 矩形对角线上的另一个顶点,color -- 线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image),thickness -- 组成矩形的线条的粗细程度,取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形,line_type -- 线条的类型。见cvLine的描述,shift -- 坐标点的小数点位数。 7)cvResize 重置图像大小
CVAPI(void) cvResize( const CvArr* src, CvArr* dst,
int interpolation CV_DEFAULT( CV_INTER_LINEAR )); 重置图像大小,使图像归一到同样大小。interpolation 插值方式:选择用线性插值(CV_INTER_LINEAR)和区域插值(CV_INTER_AREA)。
8)cvOpenFileStorage 打开存在或创建新的文件
CVAPI(CvFileStorage*) cvOpenFileStorage( const char* filename, CvMemStorage* memstorage, int flags,
const char* encoding CV_DEFAULT(NULL) ); 把训练数据保存至xml文件,通过此函数打开文件便于进行读写。flag有10种,这里用到其中读和写二种:CV_STORAGE_READ (打开文件读数据)和 CV_STORAGE_WRITE(打开文件写数据)。文件打开后 有写操作和读操作函数:cvWrite();cvWriteInt();cvReadByName();cvReadIntByName()。
9)cvCalcEigenObjects 计算引入矩阵的eigen vector(特征向量)、eigen value(特征根)、image average(影像平均值) 。 CVAPI(void) cvCalcEigenObjects( int nObjects, void* input, void* output,int ioFlags, int ioBufSize, void* userData,
CvTermCriteria* calcLimit, IplImage* avg,float* eigVals );
OpenCV 已经实现PCA关键算法之一,计算出传入图像阵列的特征值、特征向量和平均值。其中nObjects为样本个数,input 为输入的影响矩阵,output 为特征矩阵,calcLimit为回调结束条件,avg 为平均值,eigVals 特征根。 10)cvEigenDecomposite 透过eigen vector和原始影像集来解析每张图片降维后对应的系数coefficients。
CVAPI(void) cvEigenDecomposite( IplImage* obj, int nEigObjs, void* eigInput, int ioFlags, void* userData, IplImage* avg, float* coeffs );
OpenCV 已经实现PCA关键算法之一,对输入图像投影到子空间,计算投影各维度系数,以此表示图像。其中obj为输入目标图像,nEigObjs为选取的特征维数,eigInput为向量组成的变换矩阵,数据结构属于IplImage队列,或者根据ioFlag参数值变化的回调函数,avg为平均值,coeffs 为输入图像对应的投影。
11)cvConvertScale 使用线性变换转换数组,得到可以保存显示的图像 CVAPI(void) cvConvertScale( const CvArr* src,CvArr* dst, double scale CV_DEFAULT(1), double shift CV_DEFAULT(0) );
OpenCV要保存显示图像,图像数据必须是uchar格式,因此对于非uchar数据需要转换。其中src 为输入数组,dst 为输出数组 ,scale 为比例因子,shift 为该加数被加到输入数组元素按比例缩放后得到的元素上,采用公式dst(I)=src(I)*scale + (shift,shift,...) 进行转换。
4.2 关键功能部分函数设计实现
4.2.1摄像头操作:
要实现系统功能,首要先从摄像头中读取数据,为此,需要保证摄像头开启,为保证获取画面统一便于管理,通过cvSetCaptureProperty()函数设置摄像头分辨率为常用值(320*240),读取摄像头数据,返回 IplImage图像数据,该部分需要实现的是打开摄像头、设置摄像头分辨率属性、读取摄像头图像,还有使用完后释放摄像头资源操作。
软件启动后若选择不从文件中读取信息,自动启动摄像头获取图片。 按“ESC”键退出系统时自动回收资源,关闭摄像头,释放摄像头资源。
4.1.2人脸检测功能:
要实现人脸识别,首要先检测出人脸。实现该功能,接收摄像头中获取的图像数据,进行灰度化等操作,利用Haar特征,使用强级联分类器,搜索检测人脸区域,提取出可能的最大脸,为防止误检,进一步在提取出的区域再次对人眼进行检测,过滤掉检测不到人眼的区域,从而有效地降低了人脸区域误检率,获取真正需要的人脸区域。人脸区域获取后,进一步提取出人脸图像,为了训练需要,还须对提取的图像进行大小归一化,使得得到的图像大小统一,为了进一步提高后续识别效率,对图像进行直方图均衡化,最后得到所需图像用于训练和识别。
4.1.3图像特征训练提取:
利用主成分分析法(PCA)算法对收集到的用户图像进行降维训练,提取人脸特征值。主成分分析法实现主要分为几步完成: 1、去均值 2、计算协方差矩阵及其特征值和特征向量 3、计算协方差矩阵的特征值大于阈值的个数 4、降序排列特征值 5、去掉较小的特征值 6、去掉较大的特征值(可有可无) 7、合并选择的特征值 8、选择相应的特征值和特征向量 9、计算白化矩阵 10、提取主分量。读取人脸训练集,利用PCA算法得到特征人脸和平均人脸,在此基础上把每张训练人脸投影到特征脸空间中得到投影数据作为每幅人脸的特征脸。
满足系统要求,可能需要能够识别多人身份,因此需要能够添加用户。 系统启动后,识别过程中,设置按下’n’键,进入添加用户模式,输入用户名开始自动采集用户脸部图像,开始训练提取特征数据。
4.1.4训练图像保存:
PCA算法过程中会计算出人脸的平均脸信息,和特征脸信息,但得到的这些信息是无法直接显示到屏幕上的,想要看到这些图像,就需要把其加以转换,得到可以直接显示的格式。在这一阶段,计算出其最大值和最小值,对于超出数值范围和非数值的值进行过滤修改,然后利用cvConvertScale函数将float类型的值转化为需要的uchar类型,然后调用cvshowImage进行保存。 训练数据保存与加载:
对于利用PCA得到的训练数据要在识别时使用,所以首先需要保存起来,在识别时读取并当前数据匹配。这个阶段主要涉及到文件的操作,包括文件的打开、关闭,写数据和读数据。
4.1.5身份识别验证功能:
整个系统中最关键重要的就是身份识别功能,之前实现人脸检测提取出当前用户的脸部信息,PCA数据训练得到平均人脸和人脸子空间等数据提供了基础,在此基础上,将当前用户脸部图像投影到人脸子空间中,然后找出与投影脸欧式距离最近的训练人脸,计算距离与可信相似度,并与设置的阀值比较,当大于阀值时可以认为确认身份成功。当阀值设置过大时会使识别很困难,效率降低;而若阀值设置过小,容易把人脸识别错误,使得系统实用性降低,因此,选择一个合适的阀值非常重要,而阀值的选取有没有一个科学的准确依据,因此使得确定合适阀值比较困难。