随笔 - 632  文章 - 17  评论 - 54  阅读 - 93万

OpenCV之使用EigenFaceRecognizer来实现人脸识别

一、概述

  案例:使用EigenFaceRecognizer来实现人脸识别算法

  实现步骤:

    1.准备人脸数据(人脸和人脸对应的标签),ps:预留一个或几个样本用来测试

    2.将样本数据和样本对应的标签数据从文件中读取出来并分别存入集合

    3.实例化EigenFaceRecognizer

    4.将准备好的人脸集合和标签集合放入EigenFaceRecognizer.train函数中进行训练

    5.训练好数据后执行predict方法进行预测

    6.假如预留样本的标签值与执行predict预测后的标签值是一致的就说明我们预测成功了。

  ps:使用这个算法来实现人脸识别时样本图像和实际的图像大小必须要要一致,否则算法会出现不工作的情况。

二、代码示例

复制代码
Face_Eigen_Face_Recognizer::Face_Eigen_Face_Recognizer(QWidget *parent)
    : MyGraphicsView{parent}
{
    this->setWindowTitle("特征脸识别器");
    QPushButton * btn = new QPushButton(this);
    btn->setText("读取数据");
    connect(btn,&QPushButton::clicked,[=](){
        QString srcDirPath = QFileDialog::getExistingDirectory(
                    this, "choose src Directory",
                    "/Users/yangwei/Documents/tony/opencv/orl_faces");
        if (srcDirPath.isEmpty())
        {
            return;
        }
        else
        {
            string filename = string("/Users/yangwei/Documents/tony/opencv/orl_faces/targetData.txt");
            out.open(filename,ios::out);
            qDebug() << "srcDirPath=" << srcDirPath;
            srcDirPath += "/";
            prepareImageData(srcDirPath.toStdString().c_str(),"");
            out.close();
        }

    });




    QPushButton *btnShow = new QPushButton(this);
    btnShow->move(0,btn->y()+btn->height()+5);
    btnShow->setText("开始检测特征脸");
    connect(btnShow,&QPushButton::clicked,[=](){
        showEgenFaceRecoginzer("");
    });

}

void Face_Eigen_Face_Recognizer::dropEvent(QDropEvent *event){
    path = event->mimeData()->urls().at(0).toLocalFile();
    showEgenFaceRecoginzer(path.toStdString().c_str());
}

void Face_Eigen_Face_Recognizer::showEgenFaceRecoginzer(const char * filePath){
    string filename = string("/Users/yangwei/Documents/tony/opencv/orl_faces/targetData.txt");
    ifstream file(filename,ifstream::in);
    string line,path,classLabel;//行、路径、标签
    vector<Mat> images;
    vector<int> labels;
    while(getline(file,line)){

        stringstream liness(line);
        getline(liness,path,' ');
        getline(liness,classLabel);
        //        if (!path.empty() && !labels.empty()) {
        cout << "path :"<< classLabel.c_str()<<endl;;
        images.push_back(imread(path, 0));
        labels.push_back(atoi(classLabel.c_str()));
        //        }
    }
    file.close();
    if (images.size() < 1 || labels.size() < 1) {
        qDebug()<<"invalid image path...\n";
        return;
    }

    int width = images[0].cols;
    int height = images[0].rows;
    cout << "width:"<<width<<"|"<<"height:"<<height<<endl;
    //准备测试数据和测试label
    Mat testMatSample = images[images.size()-1];
    int testLabel = labels[labels.size()-1];
    imshow("testMatSample",testMatSample);
    images.pop_back();
    labels.pop_back();

    //接下来就是最重要的步骤
    //1.训练
    Ptr<BasicFaceRecognizer> model = EigenFaceRecognizer::create();
    model->train(images,labels);
    //2.预测
    int predictedLabel = model->predict(testMatSample);

    //此处如果样本和预测结果是一致的就说明此次识别是算法是成功的
    cout << "testLabel:"<<testLabel<<endl;
    cout <<"predictedLabel:"<<predictedLabel<<endl;

    //从训练结果中获取均值、特征向量、特征值矩阵
    Mat eigenvalues = model->getEigenValues();
    Mat eigenvectors = model->getEigenVectors();
    Mat mean = model->getMean();
    //得到均值脸
    Mat meanFace = mean.reshape(1,height);
    Mat dst;
    //归一化0~255并输出
    if(meanFace.channels()==1){//单通道图像
        normalize(meanFace,dst,0,255,NORM_MINMAX,CV_8UC1);
    }else{//多通道图像
        normalize(meanFace,dst,0,255,NORM_MINMAX,CV_8UC3);
    }
    imshow("dist",dst);

//    //输出特征脸
//    for (int i = 0; i < min(16, eigenvectors.cols); i++) {
//        Mat ev = eigenvectors.col(i).clone();
//        Mat grayscale;
//        Mat eigenFace = ev.reshape(1, height);
//        if (eigenFace.channels() == 1) {
//            normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC1);
//        }
//        else if (eigenFace.channels() == 3) {
//            normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC3);
//        }
//        Mat colorface;
//        applyColorMap(grayscale, colorface, COLORMAP_BONE);
//        char* winTitle = new char[128];
//        sprintf(winTitle, "eigenface_%d", i);
//        imshow(winTitle, colorface);
//    }

//    for (int num = 0; num < min(eigenvectors.cols, 16); num++) {
//            Mat evs = eigenvectors.col(num);
//            Mat projection = LDA::subspaceProject(evs, mean, images[0].reshape(1, 1));
//            Mat reconstruction = LDA::subspaceReconstruct(evs, mean, projection);

//            Mat result = reconstruction.reshape(1, height);
//            if (result.channels() == 1) {
//                normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC1);
//            }
//            else if (result.channels() == 3) {
//                normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC3);
//            }
//            char* winTitle = new char[128];
//            sprintf(winTitle, "recon_face_%d", num);
//            imshow(winTitle, reconstruction);
//        }




}
复制代码

 

三、演示图像

  预测结果:

  

 

posted on   飘杨......  阅读(791)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示