门禁系统小结(三)-终结篇
2011-05-30 16:14 sensensen 阅读(480) 评论(0) 编辑 收藏 举报1.time.h time函数可以用在以下一些地方:
time函数也常用于随机数的生成,用日历时间作为种子:srand((unsigned) time(NULL));
用time()函数结合其他函数(如:localtime、gmtime、asctime、ctime)可以获得当前系统时间或是标准时间。
2.srand函数是随机数发生器的初始化函数:
原型:void srand(unsigned seed);
用法:它需要提供一个种子,如: srand(1); 直接使用1来初始化种子。不过常常使用系统时间来初始化,即使用 time函数来获得系统时间,它的返回值为从 00:00:00 GMT, January 1, 1970 到现在所持续的秒数,然后将time_t型数据转化为(unsigned)型再传给srand函数,即: srand((unsigned) time(&t)); 还有一个经常用法,不需要定义time_t型t变量,即: srand((unsigned) time(NULL)); 直接传入一个空指针,因为你的程序中往往并不需要经过参数获得的t数据。srand((int)getpid()); 使用程序的ID(getpid())来作为初始化种子,在同一个程序中这个种子是固定的。
注意:1.NULL必须大写
2.我们知道rand()函数可以用来产生随机数,但是这不是真正意义上的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态分布,从而相当于产生了随机数,但这不是真正的随机数,当计算机正常开机后,这个种子的值是定了的,除非你破坏了系统。
rand()的内部实现是用线性同余法做的,它不是真的随机数,因其周期特别长,故在一定的范围里可看成是随机的。rand()返回一随机数值的范围在0至RAND_MAX 间。RAND_MAX的范围最少是在32767之间(int)。用unsigned int 双字节是65535,四字节是4294967295的整数范围。0~RAND_MAX每个数字被选中的机率是相同的。用户未设定随机数种子时,系统默认的随机数种子为1。 rand()产生的是伪随机数字,每次执行时是相同的(这一点我试过了,比柏拉图的爱情问题,10次中每次产生的值确实不同,比如41,467,334,500.。。看似是不同,但是第二次运行还是按这个先后顺序出来这些数字);若要不同,用函数srand()初始化它。
PS:rand()产生的随机数在每次运行的时候都是与上一次相同的。若要不同,用函数srand()初始化它。可以利用srand((unsigned int)(time(NULL))的方法,产生不同的随机数种子,因为每一次运行程序的时间是不同的。
参考文献http://blogold.chinaunix.net/u3/94667/showart_2436518.html
3. OPENCV相关人脸识别内容
OPENCV的配置,不是很大的问题,环境变量里改了没有?VS的include里面都装了没有,还有link->input那几句话写了没有,头文件里面cv.h等等加了没有。
cvMat 多通道矩形
cfiledialog.domodal():Call this function to display the Windows common file dialog box and allow the user to browse files and directories and enter a filename.
if(IDOK==cfiledialog.domodal()) 说明点了ok键。
********************************************************************************
首先说一下.xml,因为程序中用到了xml让我很费解,后来百度之后终于知道了,这是OPENCV提供的给我们做人脸识别的分类器文件。
首先,xml是一种可扩展标记语言,它常常用来传送和携带数据,常以<?xml version="1.0"?>开头(序言),由于它简单易用,所以各类程序读写数据都把它作为数据交换的公共语言,它部依附于特定的浏览器。
关于如何产生自己的xml分类器,可以参见如下两个网站:
http://blog.csdn.net/kingstar568/archive/2010/02/06/5291937.aspx
http://blog.csdn.net/yanfanqie/archive/2010/04/12/5478767.aspx
写的很好,总的来说就是需要很多很多的正负样本,然后就是运行程序。
而我们做的人脸识别系统只需要用它就可以了,那来看看调用它的过程:
先说说控制摄像头,用的是cvCaptureFromCAM,使用的是vfw消息机制。
然后是装载,cascade=(CvHaarClassifierCascade *)cvLoad(strXml,0,0,0);//strxml是这个.xml文件的路径
之后CvMemStorage * storage=cvCreateMemStorage(0);//创建内存块
最后用这个分类器去检测物体:
CvSeq *faces=cvHaarDetectObjects(img,cascade,storage,1.1,2,CV_HAAR_DO_CANNY_PRUNING,cvSize(40,40));
N=faces?faces->total:0;//得到total number
for(int i=0;i<N;i++)
{
CvRect* r = (CvRect*)cvGetSeqElem(faces,i);//返回索引所指的元素指针
pt1.x = r->x*scale;//cvrect矩阵框的偏移和大小
pt2.x = (r->x+r->width)*scale;
pt1.y = r->y*scale;
pt2.y = (r->y+r->height)*scale;
cvRectangle(img,pt1,pt2,CV_RGB(255,0,0),2,8,0);//绘制矩形框
......
}
最后,对于这个程序里面用到的PCA,LDA我还不是特别清楚,有待下文。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最终的最终,我终于弄明白了,lda.c,pca.c都没有用到(测试用的),真正的工程是:先用haarclassifiercascade...xml的分类器(像上面说的加载然后检测)进行人脸的检测,检测出人脸后,对数据库中的人脸进行PCA分析,再对检测到的图像进行PCA投影,计算它到人脸图像中距离最小的一个(一般就用最近距离啦),最后保证这个最小距离小于某个值(这里是15e14吧),就可以完成对人脸的识别啦~~~~