OpenCV EigenFaceRecognizer 人脸识别

目录

一、人脸检测vs人脸识别

二、数据库

三、准备需要识别的人脸

四、人脸识别(OpenCV)


一、人脸检测vs人脸识别

人脸检测只是需要检测图像中是否有人脸,而人脸识别是一个程序能够识别出给定图像或者视频中的人脸

二、数据库

人脸数据库,这个博客有网盘链接。

三、准备需要识别的人脸

准备一个人的10张左右数量的人脸,放到刚刚下载ORL的数据库中:

 

捕获人脸代码:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>

using namespace std;
using namespace cv;

void detectFace(Mat frame, string path)
{
    // 级联分类器加载文件
    CascadeClassifier facefier;
    facefier.load("/home/jason/file/opencv/haarcascade_frontalface_alt.xml");

    VideoCapture capture(0);
    vector<Rect> faces;
    Mat gray_frame;

    int number=0;
    while (1)
    {
        capture >> frame;
        imshow("detect face", frame);
        cvtColor(frame,gray_frame,COLOR_BGR2GRAY);
        equalizeHist(gray_frame,gray_frame);

        // 检测人脸
        facefier.detectMultiScale(gray_frame, faces);

        // 保存人脸
        for (size_t i=0; i < faces.size(); i++)
        {

            // 画框标出人脸
            Mat temp = frame.clone();
            rectangle(temp,faces[i], Scalar(255, 0,0), 1, 8);
            imshow("detect face", temp);

            // 扣出人脸
            Mat faceROI = frame(faces[i]);

            // 过滤
            if (faceROI.cols * faceROI.rows > 100 * 100)
            {
                resize(faceROI, faceROI, Size(92, 112));
                string newpath = path + "/" + to_string(number) + ".png";
                imwrite(newpath,faceROI);
                cout << "file  save :" << newpath << endl;
                imshow("ROI", faceROI);
                number++;
            }

        }

        if(waitKey() == 27)
            break;

    }
    cout << "you save " << number << " face images" << endl;


}

void generator(string path)
{

    // 输入文件夹名字
    string name;
    cout << "Please key the name:\n";
    getline(cin, name);


    // 新建文件夹
    string newpath = path + "/" + name;
    cout << "image will save the path:" << newpath.c_str() << endl;

    if (!newpath.empty())
    {
        if(NULL != opendir(newpath.c_str()))
        {
            cout << "fin a dir same to your input! delete it now!" << endl;
            rmdir(newpath.c_str());
        }

        if (NULL == opendir(newpath.c_str()))
        {
            mkdir(newpath.c_str(),0777);
        }

    }

    // 检测人脸并扣出来保存到指定位置
    Mat frame;
    detectFace(frame, newpath);

}




int main()
{
    string path = "/home/jason/file";
    generator(path);
    cout << "Hello World!" << endl;
    return 0;
}

四、人脸识别(OpenCV)

 

实现代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <dirent.h>
#include <sys/stat.h>

#include <opencv2/opencv.hpp>
#include <opencv2/face/facerec.hpp>
using namespace cv;
using namespace std;

int label=0;
std::string nam;

vector<Mat> images;
vector<int> labels;
vector<string> names;
void Load_data(const std::string& path)
{

    DIR* dir = opendir(path.c_str());
    if (dir == nullptr)
    {
        std::cerr << "Cannot open directory: " << path << std::endl;
        return;
    }

    struct dirent* entry;
    while ((entry = readdir(dir)) != nullptr)
    {
        std::string name = entry->d_name;
        if (name == "." || name == "..")
        {
            continue;
        }

        std::string fullPath = path + "/" + name;
        struct stat stat_buf;
        if (stat(fullPath.c_str(), &stat_buf) != 0)
        {
            std::cerr << "Cannot stat file: " << fullPath << std::endl;
            return;
        }
        // Determine whether it is a folder
        if (S_ISDIR(stat_buf.st_mode))
        {
            std::cout << "Directory: " << fullPath  <<std::endl;
            Load_data(fullPath);


            // label name
            label+=1;
            nam=name;
        }
        else if (S_ISREG(stat_buf.st_mode))
        {
            std::cout << "File: " << fullPath
                      << "  name:" << nam
                      << "  label: "<<label<<std::endl;

            // 添加到容器中
            Mat img = imread(fullPath);

            images.push_back(img);
            labels.push_back(label);
            names.push_back(nam);
        }
    }
    closedir(dir);

}

void FaceRec(const string &path, string person_name="jack")
{
    // 准备数据
    Load_data(path);

    // 训练
//    Ptr<cv::face::FaceRecognizer> model = cv::face::FisherFaceRecognizer::create();
    Ptr<cv::face::EigenFaceRecognizer> model = cv::face::EigenFaceRecognizer::create();
//    Ptr<cv::face::LBPHFaceRecognizer> model = cv::face::LBPHFaceRecognizer(1, 8,8,8,);
    model->train(images, labels);

    // 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
    CascadeClassifier casc;
    casc.load("/home/jason/file/opencv/haarcascade_frontalface_alt.xml");

    int jack_label;

    for (size_t i=0; i<names.size(); i++)
    {
        if (names[i] == person_name)
            jack_label=labels[i];
    }

    VideoCapture capture(0);
    Mat frame, gray;
    vector<Rect> faces;

    while (1)
    {
        // 获取图像
        capture >> frame;

        imshow("recognizer", frame);

        // 预处理
        cvtColor(frame,gray,COLOR_RGB2GRAY);
        equalizeHist(gray, gray);

        // 检测人脸
        casc.detectMultiScale(gray, faces);

        // 扣出人脸判断是否为目标人物
        for(size_t i=0; i<faces.size(); i++)
        {
            Mat temp = frame.clone();
            rectangle(temp, faces[i], Scalar(255, 0, 0), 1, 8);

            Mat roi_gray = gray(faces[i]);
            resize(roi_gray, roi_gray, Size(92, 112));
            imshow("person",roi_gray);

            int result;
            double confidence=0.8;

            // 预测
            model->predict(roi_gray, result, confidence);
            cout<< "result: " << result
                <<"confidence: " << confidence<< endl;
            if (result==jack_label)
            {
                putText(temp, person_name ,Point(faces[i].x, faces[i].y),FONT_ITALIC,
                        0.5, Scalar(255, 0, 0),1,8);
            }
            else
            {
                cout << "not  find " << person_name << endl;

            }
            imshow("recognizer", temp);
        }

        if (waitKey(10)==27) break;

    }
}



int main()
{
    std::string path = "/home/jason/file/Face/ORL_Faces";
    FaceRec(path,"jack");
    return 1;
}

参考资料:

C++创建文件夹和写文件_林多的博客-CSDN博客

C++11标准中遍历文件夹方法_c++11 遍历目录_HotPot_Dumplings的博客-CSDN博客

OpenCV: cv::face::FaceRecognizer Class Reference

https://www.cnblogs.com/zyly/p/9498857.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值