首页AI技术供需平台OpenCV中人脸识别代码实现站长QQ:926563750

浏览

0

回复

OpenCV中人脸识别代码实现

作者:admin | 分类:AI技术供需平台 | 标签:人脸识别 OpenCV 

声明:本文代码来源于http://www.cognotics.com/opencv/servo_2007_series/,实现平台为Linux+OpenCV,共分为两部分:人脸检测与人脸识别。本文为后半部分的代码,关于第一部分请参见http://blog.csdn.net/liudekuan/article/details/8560251。不多言,以下给出代码及相关注解

  1. #include <stdio.h>  

  2. #include <string.h>  

  3. #include "cv.h"  

  4. #include "cvaux.h"  

  5. #include "highgui.h"  

  6.   

  7. using namespace cv;  

  8.   

  9. //globle variables  

  10. int nTrainFaces         = 0;    // number of trainning images  

  11. int nEigens             = 0;    // number of eigenvalues  

  12. IplImage** faceImgArr       = 0;    // array of face images  

  13. CvMat* personNumTruthMat    = 0;    // array of person numbers  

  14. IplImage* pAvgTrainImg      = 0;    // the average image  

  15. IplImage** eigenVectArr     = 0;    // eigenvectors  

  16. CvMat* eigenValMat      = 0;    // eigenvalues  

  17. CvMat* projectedTrainFaceMat    = 0;    // projected training faces  

  18.   

  19. //// Function prototypes  

  20. void learn();  

  21. void recognize();  

  22. void doPCA();  

  23. void storeTrainingData();  

  24. int loadTrainingData(CvMat** pTrainPersonNumMat);  

  25. int findNearestNeighbor(float* projectedTestFace);  

  26. int loadFaceImgArray(char* filename);  

  27. void printUsage();  

  28.   

  29. int main( int argc, char** argv )  

  30. {  

  31.     if((argc != 2) && (argc != 3)){  

  32.     printUsage();  

  33.     return -1;  

  34.     }  

  35.   

  36.     if( !strcmp(argv[1], "train" )){  

  37.     learn();  

  38.     } else if( !strcmp(argv[1], "test") ){  

  39.     recognize();  

  40.     } else {  

  41.     printf("Unknown command: %s\n", argv[1]);  

  42.     }  

  43.     return 0;  

  44. }  

  45.   

  46. void printUsage(){  

  47.     printf("Usage: eigenface <command>\n",  

  48.     "  Valid commands are\n"  

  49.     "    train\n"  

  50.     "    test\n"  

  51.     );  

  52. }  

  53.   

  54. void learn(){  

  55.     int i;  

  56.   

  57.     // load training data  

  58.     nTrainFaces = loadFaceImgArray("train.txt");  

  59.     if( nTrainFaces < 2){  

  60.     fprintf(  

  61.         stderr,  

  62.         "Need 2 or more training faces\n"  

  63.         "Input file contains only %d\n",  

  64.         nTrainFaces     

  65.     );  

  66.     return;  

  67.     }  

  68.   

  69.     // do PCA on the training faces  

  70.     doPCA();  

  71.   

  72.     // project the training images onto the PCA subspace  

  73.     projectedTrainFaceMat = cvCreateMat(nTrainFaces, nEigens, CV_32FC1);  

  74.     for(i = 0; i < nTrainFaces; i ++){  

  75.     cvEigenDecomposite(  

  76.         faceImgArr[i],  

  77.         nEigens,  

  78.         eigenVectArr,  

  79.         0, 0,  

  80.         pAvgTrainImg,  

  81.         projectedTrainFaceMat->data.fl + i*nEigens  

  82.     );  

  83.     }  

  84.   

  85.     // store the recognition data as an xml file  

  86.     storeTrainingData();  

  87. }  

  88.   

  89. int loadFaceImgArray(char* filename){  

  90.     FILE* imgListFile = 0;  

  91.     char imgFilename[512];  

  92.     int iFace, nFaces = 0;  

  93.   

  94.     // open the input file  

  95.     imgListFile = fopen(filename, "r");  

  96.       

  97.     // count the number of faces  

  98.     while( fgets(imgFilename, 512, imgListFile) ) ++ nFaces;  

  99.     rewind(imgListFile);  

  100.   

  101.     // allocate the face-image array and person number matrix  

  102.     faceImgArr = (IplImage **)cvAlloc( nFaces*sizeof(IplImage *) );  

  103.     personNumTruthMat = cvCreateMat( 1, nFaces, CV_32SC1 );  

  104.   

  105.     // store the face images in an array  

  106.     for(iFace=0; iFace<nFaces; iFace++){  

  107.     //read person number and name of image file  

  108.     fscanf(imgListFile, "%d %s", personNumTruthMat->data.i+iFace, imgFilename);  

  109.   

  110.     // load the face image  

  111.     faceImgArr[iFace] = cvLoadImage(imgFilename, CV_LOAD_IMAGE_GRAYSCALE);  

  112.     }  

  113.   

  114.     fclose(imgListFile);  

  115.   

  116.     return nFaces;  

  117. }  

  118.   

  119. void doPCA(){  

  120.     int i;  

  121.     CvTermCriteria calcLimit;  

  122.     CvSize faceImgSize;  

  123.   

  124.     // set the number of eigenvalues to use  

  125.     nEigens = nTrainFaces - 1;  

  126.   

  127.     // allocate the eigenvector images  

  128.     faceImgSize.width = faceImgArr[0]->width;  

  129.     faceImgSize.height = faceImgArr[0]->height;  

  130.     eigenVectArr = (IplImage**)cvAlloc(sizeof(IplImage*) * nEigens);  

  131.     for(i=0; i<nEigens; i++){  

  132.     eigenVectArr[i] = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);  

  133.     }  

  134.   

  135.     // allocate the eigenvalue array  

  136.     eigenValMat = cvCreateMat( 1, nEigens, CV_32FC1 );  

  137.   

  138.     // allocate the averaged image  

  139.     pAvgTrainImg = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);  

  140.   

  141.     // set the PCA termination criterion  

  142.     calcLimit = cvTermCriteria( CV_TERMCRIT_ITER, nEigens, 1);  

  143.   

  144.     // compute average image, eigenvalues, and eigenvectors  

  145.     cvCalcEigenObjects(  

  146.     nTrainFaces,  

  147.     (void*)faceImgArr,  

  148.     (void*)eigenVectArr,  

  149.     CV_EIGOBJ_NO_CALLBACK,  

  150.     0,  

  151.     0,  

  152.     &calcLimit,  

  153.     pAvgTrainImg,  

  154.     eigenValMat->data.fl  

  155.     );  

  156. }  

  157.   

  158. void storeTrainingData(){  

  159.     CvFileStorage* fileStorage;  

  160.     int i;  

  161.      

  162.     // create a file-storage interface  

  163.     fileStorage = cvOpenFileStorage( "facedata.xml", 0, CV_STORAGE_WRITE);  

  164.   

  165.     // store all the data  

  166.     cvWriteInt( fileStorage, "nEigens", nEigens);  

  167.     cvWriteInt( fileStorage, "nTrainFaces", nTrainFaces );  

  168.     cvWrite(fileStorage, "trainPersonNumMat", personNumTruthMat, cvAttrList(0, 0));  

  169.     cvWrite(fileStorage, "eigenValMat", eigenValMat, cvAttrList(0,0));  

  170.     cvWrite(fileStorage, "projectedTrainFaceMat", projectedTrainFaceMat, cvAttrList(0,0));  

  171.     cvWrite(fileStorage, "avgTrainImg", pAvgTrainImg, cvAttrList(0,0));  

  172.   

  173.     for(i=0; i<nEigens; i++){  

  174.     char varname[200];  

  175.     sprintf( varname, "eigenVect_%d", i);  

  176.     cvWrite(fileStorage, varname, eigenVectArr[i], cvAttrList(0,0));  

  177.     }  

  178.   

  179.     //release the file-storage interface  

  180.     cvReleaseFileStorage( &fileStorage );  

  181. }  

  182.   

  183. void recognize(){  

  184.     int i, nTestFaces = 0;      // the number of test images  

  185.     CvMat* trainPersonNumMat = 0;   // the person numbers during training      

  186.     float* projectedTestFace = 0;     

  187.   

  188.     // load test images and ground truth for person number  

  189.     nTestFaces = loadFaceImgArray("test.txt");      

  190.     printf("%d test faces loaded\n", nTestFaces);  

  191.       

  192.     // load the saved training data  

  193.     if( !loadTrainingData( &trainPersonNumMat ) ) return;  

  194.   

  195.     // project the test images onto the PCA subspace  

  196.     projectedTestFace = (float*)cvAlloc( nEigens*sizeof(float) );  

  197.     for(i=0; i<nTestFaces; i++){  

  198.     int iNearest, nearest, truth;  

  199.   

  200.     // project the test image onto PCA subspace  

  201.     cvEigenDecomposite(  

  202.         faceImgArr[i],  

  203.         nEigens,  

  204.         eigenVectArr,  

  205.             0, 0,  

  206.         pAvgTrainImg,  

  207.         projectedTestFace  

  208.     );  

  209.   

  210.     iNearest = findNearestNeighbor(projectedTestFace);  

  211.     truth = personNumTruthMat->data.i[i];  

  212.     nearest = trainPersonNumMat->data.i[iNearest];  

  213.   

  214.     printf("nearest = %d, Truth = %d\n", nearest, truth);  

  215.     }  

  216. }  

  217.   

  218. int loadTrainingData(CvMat** pTrainPersonNumMat){  

  219.     CvFileStorage* fileStorage;  

  220.     int i;  

  221.    

  222.     // create a file-storage interface  

  223.     fileStorage = cvOpenFileStorage( "facedata.xml", 0, CV_STORAGE_READ );  

  224.     if( !fileStorage ){  

  225.     fprintf(stderr, "Can't open facedata.xml\n");  

  226.     return 0;  

  227.     }  

  228.   

  229.     nEigens = cvReadIntByName(fileStorage, 0, "nEigens", 0);  

  230.     nTrainFaces = cvReadIntByName(fileStorage, 0, "nTrainFaces", 0);  

  231.     *pTrainPersonNumMat = (CvMat*)cvReadByName(fileStorage, 0, "trainPersonNumMat", 0);  

  232.     eigenValMat = (CvMat*)cvReadByName(fileStorage, 0, "eigenValMat", 0);  

  233.     projectedTrainFaceMat = (CvMat*)cvReadByName(fileStorage, 0, "projectedTrainFaceMat", 0);  

  234.     pAvgTrainImg = (IplImage*)cvReadByName(fileStorage, 0, "avgTrainImg", 0);  

  235.     eigenVectArr = (IplImage**)cvAlloc(nTrainFaces*sizeof(IplImage*));  

  236.     for(i=0; i<nEigens; i++){  

  237.     char varname[200];  

  238.     sprintf( varname, "eigenVect_%d", i );  

  239.     eigenVectArr[i] = (IplImage*)cvReadByName(fileStorage, 0, varname, 0);  

  240.     }  

  241.   

  242.     // release the file-storage interface  

  243.     cvReleaseFileStorage( &fileStorage );  

  244.   

  245.     return 1;  

  246. }  

  247.   

  248. int findNearestNeighbor(float* projectedTestFace){  

  249.     double leastDistSq = DBL_MAX;  

  250.     int i, iTrain, iNearest = 0;  

  251.   

  252.     for(iTrain=0; iTrain<nTrainFaces; iTrain++){  

  253.     double distSq = 0;  

  254.   

  255.     for(i=0; i<nEigens; i++){  

  256.         float d_i = projectedTestFace[i] -  

  257.         projectedTrainFaceMat->data.fl[iTrain*nEigens + i];  

  258.         distSq += d_i*d_i;  

  259.     }  

  260.   

  261.     if(distSq < leastDistSq){  

  262.         leastDistSq = distSq;  

  263.         iNearest = iTrain;  

  264.     }  

  265.     }  

  266.   

  267.     return iNearest;  

  268. }  

代码解析:

        OpenCV实现了基于PCA的特征脸人脸识别方法,相关理论可参考Paul Viola和Michael Jones于2001年发表的《Rapid Object Detection using a Boosted Cascade of SimpleFeatures》。整个算法又分为样本训练和人脸识别两个过程,在上述代码中,分别通过函数learn()与recognize()来实现。在样本训练阶段,将样本库中的人脸图像转换为特征向量表示,并投影到PCA子空间,最终将这些向量数据保存到中间文件facedata.xml中。而在识别阶段,同样将待识别的人脸图像使用PCA子空间的向量表示,通过计算待识别图像的向量与样本中的向量之间的距离,寻找其中最相近的人脸图像,作为识别结果。

        需要说明的是,在代码中训练样本图像及待识别的图像分别通过文本文件train.txt和test.txt记录,所用图像均为pgm格式,train.txt及test.txt中的内容如下所示:

其中,在这两个文件中,每一行记录一幅人脸图像。每条记录开始的数字表示人的序号,紧跟其后的则是此照片的存储路径。显然,此例在训练样本时只使用了序号为1,2,4三个人的第一幅照片,而识别时则对这三个人的多幅人脸图像进行了识别。其最终的识别结果如下所示:

nearest表示最相似的样本图像的序号,而Truth则表示待识别图像的序号。当二者相同时,表示正确识别,否则识别错误。


本文链接:http://cvchina.net/post/3.html
原创文章如转载请注明:转载自计算机视觉网-AI技术供需平台-计算机视觉论坛谢谢!

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。