基于OpenCV的人脸识别算法之二---代码实现

  1. Opencv代码实现人脸识别

    程序功能:能够利用摄像头自主检测人脸,检测到人脸后才进入人脸识别子函数,与识别模板进行比对,通过PCA算法进行人脸识别,若识别为模板人脸,则在视频上显示姓名。

    程序流程:

    1. 打开摄像头
    2. 拍摄自己的头像,作为人脸检测模型,写入磁盘
    3. 加载人脸检测器,加载人脸模型
    4. 人脸检测
    5. 把检测到的人脸与人脸模型里面的对比,找出这是谁的脸
    6. 如果人脸是自己的,显示自己的名字。

    人脸检测的数据集的获取方法参考博客OpenCV实践之路——人脸识别之一数据收集和预处理

    代码[3]

    #include<opencv2/opencv.hpp>
    #include<iostream>
    #include<stdio.h>
    #include<fstream>
    #include<sstream>
    #include<math.h>
     
    using namespace cv;
    using namespace std;
    using namespace face;
     
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    const char ESC = 27;
     
    String face_cascade_name = "G://openCV/opencv3.2.0/opencv/sources/data/haarcascades_cuda/haarcascade_frontalface_default.xml";
    String eyes_cascade_name = "G://openCV/opencv3.2.0/opencv/sources/data/haarcascades_cuda/haarcascade_eye_tree_eyeglasses.xml";
    CascadeClassifier face_cascade;//定义人脸分类器    
    /////////////////////////////////////////////////////////////////////////////////////////////////////
     
     
    //使用CSV文件去读图像和标签,主要使用stringstream和getline方法
    static void read_csv(const string& filename, vector<Mat> &images, vector<int>& labels, char separator = ';')
    {
        std::ifstream file(filename.c_str(), ifstream::in);
        if (!file)
        {
            string error_message = "No valid input file was given, please check the given filename.";
            CV_Error(CV_StsBadArg, error_message);
        }
        string line, path, classlabel;
        while (getline(file, line))
        {
            stringstream liness(line);
            getline(liness, path, separator);
            getline(liness, classlabel);
            if (!path.empty() && !classlabel.empty())
            {
                images.push_back(imread(path, 0));
                labels.push_back(atoi(classlabel.c_str()));
            }
        }
    }
     
     
    int predictVedio(Ptr<FaceRecognizer>& model, vector<int>& labels)
    {
        VideoCapture cap(0);
     
        std::vector<Rect> faces;
        Mat frame_gray;
     
     
        Mat frame;
        char key = waitKey(100);//等待100ms,返回键盘上的字符
        cap >> frame;
     
        //检测人脸,检测到人脸才允许拍照
        if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading face cascade\n"); return 0; };//读取分类器
        cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
        equalizeHist(frame_gray, frame_gray);
        face_cascade.detectMultiScale(frame_gray, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, Size(70, 70), Size(100, 100));
     
        Mat faceROI;
        for (size_t j = 0; j < faces.size(); j++)
        {
            Point center(faces[j].x + faces[j].width / 2, faces[j].y + faces[j].height / 2);
            rectangle(frame, faces[j], Scalar(255, 0, 0), 2, 8, 0);
     
            faceROI = frame_gray(faces[j]);
     
        }
        ///////////////////////////////////////////////////////
     
        Point text_lb;
     
        for (size_t i = 0; i < faces.size(); i++)
        {
            if (faces[i].height > 0 && faces[i].width > 0)
            {
                text_lb = Point(faces[i].x, faces[i].y);
            }
        }
     
     
        if (faces.size() != 0)
        {
        
            resize(faceROI, faceROI, Size(92, 112));
            int predictedLabel = model->predict(faceROI);
     
            if (predictedLabel == 40)
            {
                string name = "Hao";
                putText(frame, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
            }
        }imshow("frame", frame);
     
        if (key == ESC) { return 0; }
     
        return 1;
    }
     
     
    int main()
    {
        //读取CSV文件路径
        string fn_csv = "at.txt";
     
        // 2个容器来存放图像数据和对应的标签
        vector<Mat> images;
        vector<int> labels;
        //读取数据,如果文件不合法就会出错
        //输入的文件名已经有了
        try
        {
            read_csv(fn_csv, images, labels);
        }
        catch (cv::Exception& e)
        {
            cerr << "Error opening file \"" << fn_csv << "\".Reason:" << e.msg << endl;
            exit(1);
        }
        //如果没有读取到足够的图片,也退出
        if (images.size() <= 1)
        {
            string error_message = "This demo needs at least 2 images to work. Please add more images to you data set!";
            CV_Error(CV_StsError, error_message);
        }
     
    //下面几行创建了一个特征脸模型用于人脸识别,
        //通过CSV文件读取的图像和标签训练它
        //T这里是一个完整的PCA变换
        //如果你只想保留10个主成份,使用如下代码
        // cv::createEigenFaceRecognizer(10);
        //
        //如果你还希望使用置信度阈值来初始化,使用以下语句:
        // cv::createEigenFaceRecognizer(10,123.0);
        //如果你使用所有特征并且使用一个阈值,使用以下语句:`
        // cv::createEigenFaceRecognizer(0,123.0);
     
        Ptr<FaceRecognizer> model = createEigenFaceRecognizer();//基于PCA变换的人脸识别算法
        model->train(images, labels);
        model->load("MyFacePCAModel.xml");
     
        while (1)
        {
         if (!predictVedio(model,labels))
         {
         break;
         }
        }/**/
     
     
        waitKey(0);
        return 0;
    }

    参考文献

    [1]主成分分析(PCA)原理详解

    [2] PCA人脸识别

    [3] OpenCV实践之路——人脸识别之三识别自己的脸

猜你喜欢

转载自blog.csdn.net/LIT_Elric/article/details/79908101