OpenCV 的人脸detect及PCA匹配

来源:互联网 发布:android 6.0 java版本 编辑:程序博客网 时间:2024/05/16 20:30

OpenCV 的人脸detect及PCA匹配

分类: 杂七杂八 代码 469人阅读 评论(2) 收藏 举报


好久没写东西了,一来考试周,二来一直在看deep learning的东西,整理好了一个presentation的ppt,但不是很适合发博客上

人脸识别在OpenCV里面比较简单(我没想到这么简单……)直接调用cvHaarDetectObjects()即可,虽然也不是很好,比如偏头呀,用手遮之后detect的效果就很差强人意了,但我也没法用更好的方法做,一句话,装备跟不上~~~~

做吧做吧,人脸识别还是挺简单的,调用视频,几个简单的函数就搞定了

detect_and_draw检测脸      
save_face把脸搞出来单独放一个窗口

[cpp] view plaincopy
  1. // opencv.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. #include <opencv2\opencv.hpp>  
  7. #include <iostream>  
  8. #include <string>  
  9. #include "opencv\highgui.h"  
  10. using namespace cv;  
  11. using namespace std;  
  12.   
  13. static CvHaarClassifierCascade* cascade = 0;  
  14. const char* cascade_name =   
  15. "haarcascade_frontalface_alt.xml";   
  16. static CvMemStorage* storage = 0;   
  17. double scale=2;   
  18.     static CvScalar colors[] = {   
  19.         {{0,0,255}},{{0,128,255}},{{0,255,255}},{{0,255,0}},   
  20.         {{255,128,0}},{{255,255,0}},{{255,0,0}},{{255,0,255}}   
  21.     };//Just some pretty colors to draw with  
  22.   
  23.   
  24. void save_face(IplImage* img, CvRect *face, double scale)  
  25. {  
  26.     assert(img!=NULL);  
  27.     assert(face!=NULL);  
  28.     IplImage* pimg=cvCloneImage(img);  
  29.     cvSetImageROI(  
  30.             pimg,  
  31.             cvRect(  
  32.                 face->x *scale,            /* x = start from leftmost */  
  33.                 face->y *scale,  
  34.                 face->width *scale,  
  35.                 face->height *scale  
  36.             )  
  37.         );  
  38.         //save as 704 * 576 image  
  39.         IplImage *dst = 0;   //目标图像指针  
  40.         CvSize dst_cvsize;   //目标图像尺寸  
  41.         dst_cvsize.width = 240;    
  42.         dst_cvsize.height = 240;   
  43.         dst = cvCreateImage( dst_cvsize, pimg->depth, pimg->nChannels); //构造目标图象  
  44.         cvResize(pimg, dst, CV_INTER_LINEAR); //缩放源图像到目标图像  
  45.         cvShowImage( "face", dst );  
  46. }  
  47.   
  48.   
  49.   
  50. void detect_and_draw(IplImage* img )   
  51. {   
  52.      
  53.     //Image Preparation   
  54.     //   
  55.     IplImage* gray = cvCreateImage(cvSize(img->width,img->height),8,1);   
  56.     IplImage* small_img=cvCreateImage(  
  57.         cvSize(cvRound(img->width/scale),cvRound(img->height/scale))  
  58.         ,8  
  59.         ,1);   
  60.   
  61.     cvCvtColor(img,gray, CV_BGR2GRAY);   
  62.     cvResize(gray, small_img, CV_INTER_LINEAR);  
  63.   
  64.     cvEqualizeHist(small_img,small_img); //直方图均衡  
  65.   
  66.     //Detect objects if any   
  67.     //   
  68.     cvClearMemStorage(storage);   
  69.     double t = (double)cvGetTickCount();   
  70.     CvSeq* objects = cvHaarDetectObjects(small_img,   
  71.                                                          cascade,   
  72.                                                          storage,   
  73.                                                          1.1,   
  74.                                                          2,   
  75.                                                          0/*CV_HAAR_DO_CANNY_PRUNING*/,   
  76.                                                          cvSize(30,30));  
  77.   
  78.     t = (double)cvGetTickCount() - t;   
  79.     //Loop through found objects and draw boxes around them   
  80.     for(int i=0;i<(objects? objects->total:0);++i)   
  81.     {   
  82.         CvRect* r=(CvRect*)cvGetSeqElem(objects,i);   
  83.         save_face(img,r,scale);  
  84.         cvRectangle(img, cvPoint(r->x*scale,r->y*scale), cvPoint((r->x+r->width)*scale,(r->y+r->height)*scale), colors[i%8]);   
  85.           
  86.     }   
  87.     forint i = 0; i < (objects? objects->total : 0); i++ )   
  88.     {   
  89.         CvRect* r = (CvRect*)cvGetSeqElem( objects, i );   
  90.         CvPoint center;   
  91.         int radius;   
  92.         center.x = cvRound((r->x + r->width*0.5)*scale);   
  93.         center.y = cvRound((r->y + r->height*0.5)*scale);   
  94.         radius = cvRound((r->width + r->height)*0.25*scale);   
  95.         cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );   
  96.     }  
  97. }  
  98.   
  99. int main( int argc, char** argv ) {   
  100.   
  101.     cvNamedWindow( "Face_detect", CV_WINDOW_AUTOSIZE );  
  102.     cvNamedWindow( "face", CV_WINDOW_AUTOSIZE );  
  103.   
  104.     CvCapture* capture;  
  105.     cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );   
  106.     storage = cvCreateMemStorage(0);   
  107.   
  108.     if (argc==1) {  
  109.         capture = cvCreateCameraCapture( 0 );  
  110.     } else {  
  111.         capture = cvCreateFileCapture( argv[1] );  
  112.     }  
  113.     assert( capture != NULL );  
  114.   
  115.     IplImage* frame;  
  116.     while(1) {  
  117.         frame = cvQueryFrame( capture );  
  118.         if( !frame ) break;  
  119.         IplImage* img_rgb =frame;  
  120.         detect_and_draw(img_rgb);  
  121.         //IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);  
  122.         //cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);  
  123.         //IplImage* img_cny = doCanny( img_gry, 35, 100, 3 );  
  124.         //IplImage* img_inv = inverse(img_cny);  
  125.         cvShowImage( "FaceDetect", img_rgb );  
  126.         char c = cvWaitKey(10);  
  127.         if( c == 27 ) break;  
  128.     }  
  129.     cvReleaseCapture( &capture );  
  130.     cvDestroyWindow( "FaceDetect" );  
  131.     cvDestroyWindow( "face" );  
  132.   
  133. }  

完了之后,总觉得太简单也不好,于是想着做下人脸识别,我也没法用其它方法搞出一坨feature,于是只能是用PCA做了一下图片匹配

好在demo效果还不错,界面用MFC做的(那叫一个纠结啊,我的VS开始有个包没装好,结果不给添加事件,一通乱搞)

还有多线程的东西,杂七杂八是搞出来了,但是不好退出(关闭程序后进程残留,所以最好用那个按钮退出程序)


“开始检测”点了这个才会开始使用你的摄像头

“采集图像”呢就是你输入下标示信息,如果是分辨是哪个人呢就输入名字,除此之外还有很多玩法嘛,比如输入脸的朝向啦,戴没带眼镜啦,诸如此类

“准备PCA”开始用PCA找eigen,然后保存起来,所以在“解析”之前要准备下PCA(一次准备,多次可用,除非你又采集了新图像)

中间那个checkbox就没什么用,我无聊拿来用脸的朝向控制鼠标移动的。。。。。

“解析” 把采集的图像中和目前detect到的人脸最相似的一张的“标示信息”用MessageBox出来


PCA的部分代码:主要还是三个函数

pca_make_eigen()
prepare()
pca_detect(IplImage *img_test)
[cpp] view plaincopy
  1. void pca_make_eigen()  
  2. {   /* 
  3.       to prepare the need for svd recognize 
  4.     */  
  5.     int index=get_index();  
  6.     Mat SampleSet(index, 100*100, CV_32FC1);    
  7.     CString cs;  
  8.     for (int s=0; s<index; ++s)    
  9.     {   cs.Format(_T("C:\\Users\\Darkscope\\Desktop\\face\\%d.jpg"),s);  
  10.         IplImage *img = cvLoadImage(cs2ca(cs));    
  11.         IplImage *img_g = cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U, 1);    
  12.         cvCvtColor(img, img_g, CV_BGR2GRAY);//Change it to gray level    
  13.         Mat frame(img_g);    
  14.         for (int row=0; row<img->height; ++row)    
  15.         {    
  16.             for (int col=0; col<img->width; ++col)    
  17.             {    
  18.                 float f = (float)(frame.at<uchar>(row, col));    
  19.                 SampleSet.at<float>(s, (row*(img->width) + col) ) = f;    
  20.             }    
  21.         }    
  22.         cvReleaseImage(&img);    
  23.         cvReleaseImage(&img_g);    
  24.     }    
  25.     PCA *pca = new PCA(SampleSet, Mat(), CV_PCA_DATA_AS_ROW);  
  26.       
  27.     int c_index=0;      
  28.     float sum=0, sum0=0, ratio;      
  29.     for (int d=0; d<pca->eigenvalues.rows; ++d)      
  30.     {      
  31.         sum += pca->eigenvalues.at<float>(d,0);      
  32.     }      
  33.     for (int d=0; d<pca->eigenvalues.rows; ++d)      
  34.     {      
  35.         sum0 += pca->eigenvalues.at<float>(d,0);      
  36.         ratio = sum0/sum;      
  37.         if(ratio > 0.9){  //0.9 is the threshold    
  38.             c_index = d;      
  39.             break;      
  40.         }      
  41.     }      
  42.     Mat eigenvetors_d;      
  43.     eigenvetors_d.create((c_index+1), WIDTH*HEIGHT, CV_32FC1);//eigen values of decreased dimension      
  44.     for (int i=0; i<(c_index+1); ++i)      
  45.     {      
  46.         pca->eigenvectors.row(i).copyTo(eigenvetors_d.row(i));      
  47.     }      
  48.     //cout << "eigenvectors" <<endl << eigenvetors_d << endl;      
  49.     FileStorage fs_w("C:\\Users\\Darkscope\\Desktop\\face\\config.xml", FileStorage::WRITE);//write mean and eigenvalues into xml file      
  50.     fs_w << PCA_MEAN << pca->mean;      
  51.     fs_w << PCA_EIGEN_VECTOR << eigenvetors_d;      
  52.     fs_w.release();      
  53.     delete pca;    
  54.      
  55. }  
  56. bool flag=0;  
  57. int index;  
  58. PCA *pca_encoding;  
  59. Mat SampleSet;  
  60. CString cs;  
  61. Mat encoded;  
  62.   
  63. void prepare()  
  64. {  
  65.     index=get_index();  
  66.     pca_encoding = new PCA();  //Read config    
  67.     SampleSet=Mat(index, 100*100, CV_32FC1);    
  68.     for (int s=0; s<index; ++s)    
  69.     {   cs.Format(_T("C:\\Users\\Darkscope\\Desktop\\face\\%d.jpg"),s);  
  70.         IplImage *img = cvLoadImage(cs2ca(cs));    
  71.         IplImage *img_g = cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U, 1);    
  72.         cvCvtColor(img, img_g, CV_BGR2GRAY);//Change it to gray level    
  73.         Mat frame(img_g);    
  74.         for (int row=0; row<img->height; ++row)    
  75.         {    
  76.             for (int col=0; col<img->width; ++col)    
  77.             {    
  78.                 float f = (float)(frame.at<uchar>(row, col));    
  79.                 SampleSet.at<float>(s, (row*(img->width) + col) ) = f;    
  80.             }    
  81.         }    
  82.         cvReleaseImage(&img);    
  83.         cvReleaseImage(&img_g);    
  84.     }    
  85.     FileStorage fs_r("C:\\Users\\Darkscope\\Desktop\\face\\config.xml", FileStorage::READ);      
  86.     fs_r[PCA_MEAN] >> pca_encoding->mean;      
  87.     fs_r[PCA_EIGEN_VECTOR] >> pca_encoding->eigenvectors;      
  88.     fs_r.release();      
  89.     encoded=Mat(index, pca_encoding->eigenvectors.rows, CV_32FC1);    
  90.     for (int s=0; s<index; ++s)    
  91.     {    
  92.         Mat in = SampleSet.row(s);    
  93.         Mat out = encoded.row(s);    
  94.         //pca->project(in, out);    
  95.         pca_encoding->project(in, out);    
  96.           
  97.     }    
  98. }  
  99. int  pca_detect(IplImage *img_test)  
  100. {  
  101.       
  102.     if (!flag)  
  103.     {  
  104.         prepare();  
  105.         flag=1;  
  106.     }  
  107.   
  108.     IplImage *img_test_g = cvCreateImage(cvSize(img_test->width,img_test->height),IPL_DEPTH_8U, 1);    
  109.     cvCvtColor(img_test, img_test_g, CV_BGR2GRAY);  
  110.     Mat mat_img(img_test_g);//input    
  111.     Mat mat_test(1, HEIGHT*WIDTH, CV_32FC1);    
  112.     for (int row=0; row<HEIGHT; ++row)    
  113.     {    
  114.         for (int col=0; col<WIDTH; ++col)    
  115.         {    
  116.             float f = (float)(mat_img.at<uchar>(row, col));    
  117.             mat_test.at<float>(0, (row*(WIDTH) + col) ) = f;    
  118.         }    
  119.     }    
  120.     Mat encoded_test(1, pca_encoding->eigenvectors.rows, CV_32FC1);    
  121.     pca_encoding->project(mat_test, encoded_test);    
  122.    // cvReleaseImage(&img_test);    
  123.     cvReleaseImage(&img_test_g);  
  124.   
  125.     float min_sum = CV_MAX_ALLOC_SIZE;    
  126.     int min_index;    
  127.     for (int s=0; s<index; ++s)    
  128.     {    
  129.         float sum=0;    
  130.         for (int e=0; e<pca_encoding->eigenvectors.rows; ++e)    
  131.         {    
  132.             float fs = encoded.at<float>(s,e);    
  133.             float fi = encoded_test.at<float>(0,e);    
  134.             sum += ((fs-fi)*(fs-fi));    
  135.         }    
  136.         if(sum < min_sum){    
  137.             min_sum = sum;    
  138.             min_index = s;    
  139.         }    
  140.          
  141.     }    
  142.     /* 
  143.      reuturn the index of the most similar face for the given img. 
  144.     */  
  145.    
  146.     return min_index;  
  147. }  

其实就是调用下PCA而已,PCA的原理见我的这篇博客点击打开链接

我把MFC的工程代码放在了 github 有兴趣的可以看下(注意代码里的绝对路径face目录下必须要存在一个access.ini,里面有一个数字0,才能开始采集图像)

发现MFC整个工程居然有200MB+………………我就只上传了代码部分…………

0 0
原创粉丝点击