欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

人脸识别之三识别视频流(摄像头)中的人脸

程序员文章站 2022-07-12 20:51:09
...

前面两篇讲了人脸库的建立及模型训练,为本篇识别人脸做好准备。

本篇将在前两篇所做的工作的基础上展开。


首先,将上篇得到的三个训练模型文件(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...


人脸识别之三识别视频流(摄像头)中的人脸

注:蓝色框为缩放后的人脸位置,绿色框为还原后的人脸位置。