前面两篇讲了人脸库的建立及模型训练,为本篇识别人脸做好准备。
本篇将在前两篇所做的工作的基础上展开。
首先,将上篇得到的三个训练模型文件(MyFaceFisherModel.xml、MyFaceLBPHModel.xml、MyFacePCAModel.xml)复制至当前目录,因为人脸识别时以这三个文件作为依据。
本篇亦以三种方法进行识别。
大概流程如下:
1、打开摄像头;
2、加载人脸检测器、人脸模型;
3、对图像缩放处理(提高效率),检测人脸并框出;
4、识别人脸(以人脸模型中的作对比)。
代码【opencv-3.2.0版本】:
#include <opencv2/opencv.hpp> #include "opencv2/core.hpp" #include "opencv2/face.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include <iostream> #include <fstream> #include <sstream> using namespace cv; using namespace cv::face; using namespace std; #define ROW_MIN 45 int exitFlag = 0; int DetectAndDraw(Mat& img, CascadeClassifier& cascade, double scale, Mat& facesImg); int main() { int ret = 0; double scale = 4; VideoCapture cap(0); //打开摄像头 if (!cap.isOpened()) { printf("open camera failed.\n"); return -1; } // 加载级联分类器 CascadeClassifier cascade; ret = cascade.load("/root/library/opencv/opencv-3.2.0/data/haarcascades/haarcascade_frontalface_alt.xml"); if( !ret ) { printf("load xml failed[ret=%d].\n", ret); return -1; } cout << "load xml succeed. " << endl; // 加载训练好的人脸模型 Ptr<BasicFaceRecognizer> modelPCA = createEigenFaceRecognizer(); modelPCA->load("MyFacePCAModel.xml"); Ptr<BasicFaceRecognizer> modelFisher = createFisherFaceRecognizer(); modelFisher->load("MyFaceFisherModel.xml"); Ptr<LBPHFaceRecognizer> modelLBPH = createLBPHFaceRecognizer(); modelLBPH->load("MyFaceLBPHModel.xml"); Mat frame; while (!exitFlag) { cap >> frame; if(frame.empty()) { continue; } //建立用于存放人脸的向量容器 Mat faces; ret = DetectAndDraw(frame, cascade, scale, faces); if(ret <= 0) // 没有人脸 { cout << "faces.size <= 0" << endl; continue; } Mat face_resize; int predictPCA = 0; int predictFisher = 0; int predictLBPH = 0; if (faces.rows >= ROW_MIN) // 控制人脸不能太小(远) { resize(faces, face_resize, Size(92, 112)); } else { printf("face.rows[%d] < %d\n", faces.rows, ROW_MIN); continue; } if (!face_resize.empty()) { //测试图像应该是灰度图 predictPCA = modelPCA->predict(face_resize); predictFisher = modelFisher->predict(face_resize); predictLBPH = modelLBPH->predict(face_resize); } cout << "predictPCA : " << predictPCA << endl; cout << "predictFisher: " << predictFisher << endl; cout << "predictLBPH : " << predictLBPH << endl; if (waitKey(1) == 27) // Esc { exitFlag = 1; cout << "Esc..." << endl; break; } } return 0; } /* 参数 : 输入图像、级联分类器、缩放倍数、输出人脸 */ int DetectAndDraw(Mat& img, CascadeClassifier& cascade, double scale, Mat& facesImg) { double t = 0; Mat gray; Mat GrayImg; vector<Rect> faces; double fx = 1 / scale; cvtColor( img, gray, COLOR_BGR2GRAY ); // 将源图像转为灰度图 /* 缩放图像 */ resize( gray, GrayImg, Size(), fx, fx, INTER_LINEAR); equalizeHist( GrayImg, GrayImg ); // 直方图均衡化,提高图像质量 /* 检测目标 */ t = (double)getTickCount(); cascade.detectMultiScale( GrayImg, faces, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH |CASCADE_SCALE_IMAGE, Size(30, 30) ); t = (double)getTickCount() - t; printf( "detection time = %g ms faces.size = %ld\n", t*1000/getTickFrequency(), faces.size()); /* 画矩形框出目标 */ for ( size_t i = 0; i < faces.size(); i++ ) // faces.size():检测到的目标数量 { Rect rectFace = faces[i]; facesImg = GrayImg(faces[i]); rectangle(img, faces[i], Scalar(255, 0, 0), 1, 8, 0); // 缩放后的人脸 rectangle( img, Point(rectFace.x, rectFace.y) * scale, Point(rectFace.x + rectFace.width, rectFace.y + rectFace.height) * scale, Scalar(0, 255, 0), 2, 8); // 还原后的人脸 } imshow( "FaceDetect", img ); // 显示 if(waitKey(1) == 27) // 显示后要添加延时 { exitFlag = 1; } return faces.size(); }
编译、运行结果:
detection time = 23.5059 ms faces.size = 1 predictPCA : 1 predictFisher: 1 predictLBPH : 1 Esc...
注:蓝色框为缩放后的人脸位置,绿色框为还原后的人脸位置。