zoukankan      html  css  js  c++  java
  • Opencv与dlib联合进行人脸关键点检测与识别

    前言

    依赖库:opencv 2.4.9 /dlib 19.0/libfacedetection
    本篇不记录如何配置,重点在实现上。使用libfacedetection实现人脸区域检测,联合dlib标记人脸特征点,最后使用opencv的FaceRecognizer实现人脸识别。

    准备工作

    1、配置好Opencv2.4.9。(Opencv3.1需要另外下载一个包才有FaceRecognizer)
    2、配置好dlib 19.0(版本其实没有多大关系)
    3、配置好ShiQi.Yu的人脸检测库

    思想

    训练模块:人脸检测——>获取人脸区域的点坐标——>人脸关键点标记——>人脸对正——>归一化处理——>保存图片——>手动筛选图片——>训练样本——>得到train.xml
    识别模块:读取train.xml——>循环(人脸检测——>获取人脸区域的点坐标——>人脸关键点标记——>人脸对正——>归一化处理——>送入model->predict——>预测出结果——>putText在方框上写出名字)

    结果

    识别速度:0.15~0.25秒,Release平台。
    识别精度:还可以
    使用了一段中国好声音的视频做识别。
    这里写图片描述
    这里写图片描述
    这里写图片描述
    当然,这里用的是Fisherface算法,主要还是样本不多,已经可以搞定了。

    代码

    ReadCSV.h

    #include <opencv.hpp>
    #include <iostream>
    #include <fstream>
    using namespace cv;
    using namespace std;
    static void read_csv(const string& filename, cv::vector<Mat>& images, cv::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()));
            }
        }
    }

    FaceRotate.h

    #include <dlib/image_processing/frontal_face_detector.h>
    #include <dlib/image_processing/render_face_detections.h>
    #include <dlib/image_processing.h>
    #include <dlib/gui_widgets.h>
    #include <dlib/image_io.h>
    #include<dlib/opencv/cv_image.h>
    #include <dlib/opencv.h>
    
    using namespace dlib;
    
    frontal_face_detector detector = get_frontal_face_detector();
    shape_predictor sp;//Already get

    FaceRecognition.cpp

    #include <FaceDetect.h>
    #include <ReadCSV.h>
    const int namenumber = 4;//测试的人脸数量
    const string textname[namenumber] = { "Hariem", "Miss.Na", "Mr.Wang", "Jay.Chou" };//做一个储存人脸名字的数组
    
    
    Ptr<FaceRecognizer>  GetTrainModel(string fn_csv)//输入CSV文件的路径名
    {
        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 your data set!";
            CV_Error(CV_StsError, error_message);
        }
        Ptr<FaceRecognizer> model = createEigenFaceRecognizer(80);//创建人脸识别类 可修改 LBPHFace、EigenFace、FisherFace
        model->train(images, labels);
        return model;
    }
    
    int main()
    {
        Dlib_Predefine();//加载dlib的文件
        Ptr<FaceRecognizer> model = GetTrainModel("face.csv");//获得模型
        VideoCapture cap("好声音.mp4");
        Mat frame,gray;
        while (true)
        {
            cap >> frame;
            if (!frame.empty())
            {
                gray = FaceDetect(frame);
                if (!gray.empty())
                putText(frame, textname[model->predict(gray)], Point(50, 50), FONT_HERSHEY_DUPLEX, 3, Scalar(230, 255, 0), 2);//model->predict(frame) = predictLabel 名字写在 1 1
                imshow("Face Recogniton", frame);
                waitKey(1);
            }
            else{ cout << "The Video's end." <<endl; break; }
        }
    
    }

    FaceDetect.cpp

    用了掩码。

    #include <FaceDetect.h>
    #include <FaceRotate.h>
    void Dlib_Predefine()
    {
        deserialize("shape_predictor_68_face_landmarks.dat") >> sp;//读入标记点文件
    }
    
    cv::Mat FaceToOne(cv::Mat source)//归一化处理函数
    {
    
        cv::equalizeHist(source, source);//直方图均衡
        cv::resize(source, source, cv::Size(92, 112));//裁剪
        cv::Mat Mask = cv::imread("mask.jpg", 0);
        cv::Mat changedMask;
        source.copyTo(changedMask, Mask);
        return changedMask;
    }
    
    Mat FaceDetect(Mat frame)//脸是否存在
    {
        Mat gray, error;
        cvtColor(frame, gray, CV_BGR2GRAY);
        int * pResults = NULL;
        pResults = facedetect_frontal_tmp((unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, gray.step, 1.2f, 5, 24);
        int peopleNUM = (pResults ? *pResults : 0);
    
        for (int i = 0; i < peopleNUM; i++)//代表有几张人脸(pResults ? *pResults : 0)
        {
            short * p = ((short*)(pResults + 1)) + 6 * i;
            Rect opencvRect(p[0], p[1], p[2], p[3]);
            //gray = gray(opencvRect);
            cv::rectangle(frame, opencvRect, Scalar(230, 255, 0));
            dlib::rectangle dlibRect((long)opencvRect.tl().x, (long)opencvRect.tl().y, (long)opencvRect.br().x - 1, (long)opencvRect.br().y - 1);
            //人脸对齐技术提高了准确率
            dlib::full_object_detection shape = sp(dlib::cv_image<uchar>(gray), dlibRect);//标记点
            std::vector<full_object_detection> shapes;
            shapes.push_back(shape);//把点保存在了shape中
            dlib::array<array2d<rgb_pixel>>  face_chips;
            extract_image_chips(dlib::cv_image<uchar>(gray), get_face_chip_details(shapes), face_chips);
            Mat pic = toMat(face_chips[0]);
            cvtColor(pic, pic, CV_BGR2GRAY);
            return FaceToOne(pic);
        }
        return error;
    }
    
    
    

    FaceDetect.h

    #include <opencv.hpp>
    #include "facedetect-dll.h"
    
    using namespace cv;
    using namespace std;
    
    Mat FaceDetect(Mat frame);
    void Dlib_Predefine();//dlib 预定义的函数
    

    FaceRotate.h

    #include <dlib/image_processing/frontal_face_detector.h>
    #include <dlib/image_processing/render_face_detections.h>
    #include <dlib/image_processing.h>
    #include <dlib/gui_widgets.h>
    #include <dlib/image_io.h>
    #include<dlib/opencv/cv_image.h>
    #include <dlib/opencv.h>
    
    using namespace dlib;
    
    frontal_face_detector detector = get_frontal_face_detector();
    shape_predictor sp;//Already get

    Mask图片:
    这里写图片描述

  • 相关阅读:
    更改eclipse(myeclipse) author的默认名字(注释的作者)
    Myecplise Tomcat 启动很慢
    Java Enum 比较用 == 还是 eques
    Spring JDBC查询返回对象代码跟踪
    Apache启动失败(Windows 无法在本地计算机启动Apache2.2)
    SQLServer2008 统计表占用空间
    SET IDENTITY_INSERT ON/OFF 权限
    字母出现频率
    统计单词数
    查找最大元素
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9412040.html
Copyright © 2011-2022 走看看