在工作目录下建立/pic文件夹放入测试图片,建立/positive文件夹,放入自己的训练数据(我使用的是自己的相片中截获好的头像)建立list.txt,在里面写入pic/文件名以回车隔开,即可。
#define CV_NO_BACKWARD_COMPATIBILITY #include "cv.h" #include "highgui.h" #include <iostream> #include <cstdio> #include <string.h> #ifdef _EiC #define WIN32 #endif using namespace std; using namespace cv; void detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale,int picid); int compressPCA(const Mat& pcaset, int maxComponents, const Mat& testset, Mat& compressed); String cascadeName ="haarcascade_frontalface_alt.xml"; String nestedCascadeName ="haarcascade_eye_tree_eyeglasses.xml"; int WINDOWID=1; int main( int argc, const char** argv ) { Mat frame, frameCopy, image; const String scaleOpt = "--scale="; size_t scaleOptLen = scaleOpt.length(); const String cascadeOpt = "--cascade="; size_t cascadeOptLen = cascadeOpt.length(); const String nestedCascadeOpt = "--nested-cascade"; size_t nestedCascadeOptLen = nestedCascadeOpt.length(); String inputName; CascadeClassifier cascade, nestedCascade; double scale = 1; for( int i = 1; i < argc; i++ ) { if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 ) cascadeName.assign( argv[i] + cascadeOptLen ); else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 ) { if( argv[i][nestedCascadeOpt.length()] == '=' ) nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 ); if( !nestedCascade.load( nestedCascadeName ) ) cerr << "WARNING: Could not load classifier cascade for nested objects" << endl; } else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 ) { if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 ) scale = 1; } else if( argv[i][0] == '-' ) { cerr << "WARNING: Unknown option %s" << argv[i] << endl; } else inputName.assign( argv[i] ); } if( !cascade.load( cascadeName ) ) { cerr << "ERROR: Could not load classifier cascade" << endl; cerr << "Usage: facedetect [--cascade=\"<cascade_path>\"]\n" " [--nested-cascade[=\"nested_cascade_path\"]]\n" " [--scale[=<image scale>\n" " [filename|camera_index]\n" ; return -1; } image = imread( inputName, 1 ); if( !image.empty() ) { detectAndDraw( image, cascade, nestedCascade, scale,0 ); waitKey(0); } else if( !inputName.empty() ) { FILE* f = fopen( inputName.c_str(), "rt" ); if( f ) { char buf[1000+1]; int picid=1; printf("################################################################\n"); printf("\n"); while( fgets( buf, 1000, f ) ) { int len = (int)strlen(buf), c; while( len > 0 && isspace(buf[len-1]) ) len--; buf[len] = '\0'; cout << "file " << buf << endl; image = imread( buf, 1 ); if( !image.empty() ) { detectAndDraw( image, cascade, nestedCascade, scale,picid ); picid++; printf("\n"); printf("################################################################\n"); printf("\n"); printf("图片编号: %d \n",picid); } } fclose(f); waitKey(0); } } return 0; } void detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, int picid) { int i = 0; double t = 0; vector<Rect> faces; const static Scalar colors[] = { CV_RGB(0,0,255), CV_RGB(0,128,255), CV_RGB(0,255,255), CV_RGB(0,255,0), CV_RGB(255,128,0), CV_RGB(255,255,0), CV_RGB(255,0,0), CV_RGB(255,0,255)} ; Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); cvtColor( img, gray, CV_BGR2GRAY ); resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); equalizeHist( smallImg, smallImg ); t = (double)cvGetTickCount(); cascade.detectMultiScale( smallImg, faces, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE , Size(30, 30) ); t = (double)cvGetTickCount() - t; printf( "检测用时为: %g ms\n", t/((double)cvGetTickFrequency()*1000.) ); int index=1; char facenum[100]; char filenum[100]; char filename[255]; //pca算法处理图像开始 Mat p1,p2,p3,p4,compressed,UnknowFaceMat; p1=cv::imread("positive/1.jpg",0); p2=cv::imread("positive/2.jpg",0); p3=cv::imread("positive/3.jpg",0); p4=cv::imread("positive/4.jpg",0); float dataArr[40000]; int start=0; for(int i=0;i<p1.rows;i++) { for(int j=0;j<p1.cols;j++) { dataArr[start]=(float) p1.at<uchar>(i,j); start++; } } for(int i=0;i<p2.rows;i++) { for(int j=0;j<p2.cols;j++) { dataArr[start]=(float)p2.at<uchar>(i,j); start++; } } for(int i=0;i<p3.rows;i++) { for(int j=0;j<p3.cols;j++) { dataArr[start]=(float)p3.at<uchar>(i,j); start++; } } for(int i=0;i<p4.rows;i++) { for(int j=0;j<p4.cols;j++) { dataArr[start]=(float)p4.at<uchar>(i,j); start++; } } Mat positiveMat(4,10000,CV_32FC1,dataArr); //pca算法结束 for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) { Mat smallImgROI,tempMat; vector<Rect> nestedObjects; Point center; Scalar color = colors[i%8]; int radius; center.x = cvRound((r->x + r->width*0.5)*scale); center.y = cvRound((r->y + r->height*0.5)*scale); radius = cvRound((r->width + r->height)*0.25*scale); // circle( img, center, radius, color, 3, 8, 0 ); smallImgROI = smallImg(*r); tempMat = smallImg(*r); itoa(picid,filenum,10); itoa(index,facenum,10); strcpy(filename,"faces/"); strcat(filename,filenum); strcat(filename,"_"); strcat(filename,facenum); strcat(filename,".jpg"); cv::Mat graysmallface(Size(100,100),CV_8UC1); cv::resize(tempMat,graysmallface,graysmallface.size(),0,0); cv::imwrite(filename,graysmallface); printf("检测到人脸,写入如下文件: %s\n", filename); index++; UnknowFaceMat=graysmallface; float UnknowDataArr[10000]; start=0; for(int i=0;i<UnknowFaceMat.rows;i++) { for(int j=0;j<UnknowFaceMat.cols;j++) { UnknowDataArr[start]=(float) UnknowFaceMat.at<uchar>(i,j); start++; } } Mat negativeMat(1,10000,CV_32FC1,UnknowDataArr); int result=compressPCA(positiveMat,3,negativeMat,compressed); if(result==-1) { continue; } //--use pca end--- if(result==1) { printf("检测到指定的人!\n点任意键继续\n"); center.x = cvRound((r->x + r->width*0.5)*scale); center.y = cvRound((r->y + r->height*0.5)*scale); radius = cvRound((r->width + r->height)*0.25*scale); circle( img, center, radius, color, 2, 8, 0 ); char windowname[255]; char wnum[10]; itoa(WINDOWID,wnum,10); strcpy(windowname,"Match_"); strcat(windowname,wnum); cv::Mat tempimg(Size(800,600),CV_8UC3); cv::resize(img,tempimg,tempimg.size(),0,0); cv::imshow(windowname,img); WINDOWID++; waitKey(0); } } } int compressPCA(const Mat& pcaset, int maxComponents, const Mat& testset, Mat& compressed) { PCA pca(pcaset, // pass the data Mat(), // we do not have a pre-computed mean vector, // so let the PCA engine to compute it CV_PCA_DATA_AS_ROW, // indicate that the vectors // are stored as matrix rows // (use CV_PCA_DATA_AS_COL if the vectors are // the matrix columns) maxComponents // specify, how many principal components to retain ); // if there is no test data, just return the computed basis, ready-to-use //if( !testset.data ) //return pca; CV_Assert( testset.cols == pcaset.cols ); compressed.create(testset.rows, maxComponents, testset.type()); Mat reconstructed; for( int i = 0; i < testset.rows; i++ ) { Mat vec = testset.row(i), coeffs = compressed.row(i); // compress the vector, the result will be stored // in the i-th row of the output matrix pca.project(vec, coeffs); // and then reconstruct it pca.backProject(coeffs, reconstructed); // and measure the error printf("%d. 偏移量为: %g\n", i+1, norm(vec, reconstructed, NORM_L2)); if(norm(vec, reconstructed, NORM_L2)>2000) { return -1; } } return 1; }