基于QT+Opencv+C++基础的人脸识别项目

前提条件:
1.安装vmware16.0虚拟机
2.虚拟机里安装ubuntu16.04
3.虚拟机安装tools(方便与主机进行交互)
4.虚拟机里安装QT(Ubuntu版本)
5.在虚拟机的QT中添加opencv环境(这个比较复杂,可以查找资料或者评论拿资料)
6.界面设计直接用QT里面的设计就可以。如图(例子)

在这里插入图片描述
说明:
【1】拍照+录入信息:把当前拍摄的照片加入到指定的问价夹中,后台会存储10张这样的照片(存储10张目的是为了识别的时候数据更加可靠)。
【2】学习:目的是把你之前拍摄的照片进行“训练”。需要用到opencv的库。
【3】识别:只有把你拍摄的照片进行训练后,才能识别,识别后拍摄区会出现对应的名字(这个名字需要你后台去指定,这也是我这个项目不足之处,其实应该在你拍照后就可以直接输入名字的,这个功能就交给大家实现把,哈哈。
主要代码:

#include "widget.h"
#include "ui_widget.h"
#include<stdio.h>
#include<iostream>
#include<QTimer>
#include<QDebug>
#include<vector>
#include<cstdio>
#include<stdio.h>
#include <algorithm>
#include<list>
#include <sys/stat.h>//判断文件是否存在
using namespace face;
bool openxuexi=false;
bool openshibie =false;
bool openluruxinxi=false;
bool isFileExists_stat(string& name);
int imagecount=0;
bool keyisgibie=false;
list<QString> mylist;


string doubleToStr(string b);
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{

    ui->setupUi(this); 


    list<QString>::iterator it;
//    int i=1;
//    for ( it=mylist.begin() ; it != mylist.end(); it++ )
//    {
//        if(i==2){
//            QString temp = *it; //依次取list里面的值到temp中
//            qDebug()<<temp;
//        }

//    i=i+1;

//    }
//    qDebug()<<"list循环结束";

// ui->Widget->setStyleSheet("border-image:url(/home/lyx/桌面/bj.jpg)");
    QImage _image;
      _image.load("/home/lyx/桌面/bj.jpg");
      setAutoFillBackground(true);   // 这个属性一定要设置
       QPalette pal(palette());
        pal.setBrush(QPalette::Window, QBrush(_image.scaled(size(), Qt::IgnoreAspectRatio,
                          Qt::SmoothTransformation)));
        // this->setStyleSheet("background-color:rgb(255,34,198)");
       setPalette(pal);
ui->label->setStyleSheet("QLabel{background-color:rgb(173, 127, 168,%0);}");
ui->label_2->setStyleSheet("QLabel{background-color:rgb(173, 127, 168,%0);}");
ui->pushButton->setStyleSheet("QPushButton{background-color:rgb(52, 101, 164);}");
ui->pushButton_3->setStyleSheet("QPushButton{background-color:rgb(52, 101, 164);}");
ui->pushButton_4->setStyleSheet("QPushButton{background-color:rgb(52, 101, 164);}");
ui->pushButton_5->setStyleSheet("QPushButton{background-color:rgb(52, 101, 164);}");
ui->lineEdit_3->setStyleSheet("QLineEdit{background-color:rgb(114, 159, 207);}");
ui->lineEdit->setStyleSheet("QLineEdit{background-color:rgb(114, 159, 207);}");
      //首先获取文件夹数量
    for(int i=1;i<100;i++){
        string path=format("/home/lyx/桌面/studeyphoto/image_%d",i);
            bool cunzai=isFileExists_stat(path);
            if(!cunzai)
            {
                imagecount=i-1;
                qDebug()<<imagecount;
                break;

            }

    }
    tim.setInterval(33);//1s计数完成
    //开启摄像机信号
connect(ui->pushButton,\
         SIGNAL(clicked()),\
         this,\
     SLOT(on_pushButtons_clicked())
     );


    //定时器信号
    connect(&tim,\
            SIGNAL(timeout()),\
            this,\
            SLOT(timerout_solt()));




    connect(ui->pushButton_4,\
             SIGNAL(clicked()),\
             this,\
         SLOT(on_pushButton_4_clicked())
         );



    connect(ui->pushButton_5,\
             SIGNAL(clicked()),\
             this,\
         SLOT(on_pushButton_5_clicked())
         );
    //加载脸部识别分类器
   facedector.load("/home/lyx/OpenCv_Src/opencv-3.4.5/install/share/OpenCV/haarcascades/haarcascade_frontalface_alt2.xml");
   //

}

Widget::~Widget()
{
    delete ui;
}
int KeyValue;
//点击打开摄像头
void Widget::on_pushButton_clicked()
{
    Mat cvimg;
    cap.open(-1);
   if(cap.isOpened()==false)//打开失败
   {
       cout<<"摄像头打开失败,结束进程";
       exit(0);//结束进程
   }
    if(cap.isOpened()==true){
       cout<<"摄像头打开ok";
   }

   //摄像头分辨率调整
   cap.set(CAP_PROP_FRAME_WIDTH,411.0);
   cap.set(CAP_PROP_FRAME_HEIGHT,361.0);
   tim.start();//开始定时器计时
}
void Widget::timerout_solt()
{
Mat cvimg,tmpimg;
//定义一个rect类型的容器
vector<Rect> faces;
vector<Rect> eyes;
cap.read(cvimg);//读取一桢图片
 flip(cvimg,cvimg,1);//反转
 cvtColor(cvimg,tmpimg,CV_RGB2GRAY);//灰度处理
 equalizeHist(tmpimg,tmpimg);  //直方图均衡化,,用于提高图像的质量
 //detectMultiScale 分类器对象调用
 //第一个参数:要输入的图像 //第二个表示检测到的人脸序列(objects--被检测物体的矩形框向量组;代表四个坐标)
 //第三个参数:每次图像扩大的比例1.1默认//第四个参数:最小认可度,认可度越小越容易识别,识别率越高,精度越低。
 //第五个默认0,//第六个和第七个:目标最小尺寸和最大尺寸
 // //会将识别到的人脸坐标和大小全部放入 faces 容器中
 facedector.detectMultiScale(tmpimg,faces,1.1,3,0,Size(10,10),Size(640,480));
 //最起码有一个人像
 if(faces.size()>0)
 {
        for(int i=0;i<faces.size();i++)
        {

         if(openshibie==true){
             cout<<"qq";
             list<QString>::iterator it;
              QString temp="没有赋值";
              string temp2="默认值";
             // 识别当前的脸是否为你之前训练的人脸
         //   qDebug()<<"现在开始识别";
               Mat tmpface ;
               int predictLabel = -1;
               double predictConfidence = 0.0;
               cv::resize(tmpimg(faces[i]),tmpface,Size(100,100));
              // predict 这个函数是将一张人脸图片
             // 和我们现在之前学习的模型进行对比!
               //第一个参数:这个函数是将一张人脸图片,和我们现在之前学习的模型进行对比!识别你是谁!
              // 第二个参数  会对不同的人脸做一个标记!一般是一个数字!
              // !相似度。越低越好
               model->predict(tmpface,predictLabel,predictConfidence);

               cout<<"开始赋值"<<endl;

             //
               for(int i=1;i<imagecount;i++){
                 //  cout<<"赋值进行中"<<endl;
                   waitKey(20);
                    if(predictLabel==i && predictConfidence<100)
                    {
                        int j=1;
                        //下面这个for循环就是取出来集合中对应的名字,把名字赋值给对应的人物
                        for ( it=mylist.begin() ; it != mylist.end(); it++ )
                        {
                            if(j==i)
                            {
                                QString temp = *it; //依次取list里面的值到temp中
                                 temp2=temp.toStdString();
                                 cout<<"你看";
                                qDebug()<<temp;
                            }

                        j=j*2;

                        }

                        //第二个参数转换重点!temp2是string类型
                        //为了与C兼容,在C中没有string类型,故必须通过string类对象的成员函数c_str()把string对象转换成C中的字符串样式。
                        ft2->putText(cvimg,format("%s",temp2.c_str()),faces[i].tl(),40,Scalar(0,0,255),-1,8,true);
                        double x=predictConfidence;

                        QString str_x = QString::number(x,'g',10);

                        //ui->lineEdit->setText("姓名:"+format("%s",temp2) +"相似度:"+str_x);

                        cout<<"姓名:";
                        cout<<temp2;
                        cout<<"相似度:";
                        cout<<predictConfidence;
                        cout<<endl;
                    }
               }
//               else
               {
                   ft2->putText(cvimg,"",faces[i].tl(),40,Scalar(0,0,255),-1,8,true);
               }
               /

         }

            rectangle(cvimg,faces[i],Scalar(0,0,255),2,16); //cvimg加载的图,faces[i]矩形向量框,Scalaar线条颜色,2线条宽度,16是线型
        }
}


 QImage qimage=Mat2QImage(cvimg);
ui->label->setPixmap(QPixmap::fromImage(qimage));
}
//Mat->QImage
QImage Widget::Mat2QImage(cv::Mat cvImg)
{
    QImage qImg;
    cv::cvtColor(cvImg,cvImg,CV_BGR2RGB);
    //cv::cvtColor(cvImg,cvImg,cv::COLOR_BGR2RGB);
    qImg=QImage((const unsigned char*)(cvImg.data),
                             cvImg.cols,cvImg.rows,          //宽,高
                             cvImg.step,                     //步长
                             QImage::Format_RGB888);         //24位图,RGB=[0,1,2]
    //return qImg.rgbSwapped();
    return qImg;
}

void Widget::on_pushButton_4_clicked()
{

     if(keyisgibie){
         qDebug()<<"点击了开始识别";
       openshibie=true;

     }
 else{
         qDebug()<<"点击了开始识别,但是还没有学习,请先学习后识别";
     }

}


//判断文件是否存在的函数
bool isFileExists_stat(string& name) {
  struct stat buffer;
  return (stat(name.c_str(), &buffer) == 0);
}

void Widget::on_pushButton_5_clicked()
{

                   qDebug()<<"开始学习";
                   cout<<endl;
                    model=LBPHFaceRecognizer::create();//创建学习模型
                    //从第一个文件夹开始遍历,直到全部学习完成!
                           cout<<imagecount;
                           cout<<"份人脸数据";
                           cout<<endl;
                            int n=1;
                    for(int i=1;i<=imagecount;i++)
                    {

                        //每个文件夹10个图片
                        for(int i=1;i<=10;i++)
                        {

                            //遍历学习
                            Mat scrimg =imread(format("/home/lyx/桌面/studeyphoto2/image_%d/myface_%d.jpg",n,i));

                            cvtColor(scrimg,scrimg,CV_BGR2GRAY);//转换为灰度图片
                            study_faces.push_back(scrimg);//压栈--往里面填充数据!
                            study_index.push_back(n);//imagecount就相当我这张人脸的索引号
                        }

                        //如果获取内容非空

                        if(!(ui->lineEdit_4->text()==""))
                        {
                            name =ui->lineEdit_4->text();
                            //将获取的值加入list集合
                                qDebug()<<name;
                                 qDebug()<<"获取值list qdebug";
                            mylist.push_back(name);

                        }
                        n=n+1;
                    }

                       study_faces.pop_back();
                       study_index.pop_back();
                       //

                       list<QString>::iterator it;

                       for ( it=mylist.begin() ; it != mylist.end(); it++ )
                       {
                         QString temp = *it; //依次取list里面的值到temp中
                             qDebug()<<"遍历";
                               qDebug()<<temp;


                       }
                       qDebug()<<"list循环结束";
                       //
                       //识别不同人脸的特性进行学习和保存 //我们通过容器进行训练
                       model->train(study_faces,study_index);

                      ft2 = freetype::createFreeType2();//初始化中文容器
                      ft2->loadFontData("/usr/share/fonts/truetype/arphic/uming.ttc",0);
                       qDebug()<<"完成学习";
                       keyisgibie=true;


}


void Widget::on_pushButton_3_clicked()
{
    qDebug()<<"按键按下!×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××\r\n\r\n\r\n";
    //打开ok
    if(cap.isOpened()==true)
    {
        Mat cvimg2,tmpimg2;
        cap.read(cvimg2);//读取一桢图片
        flip(cvimg2,cvimg2,1);//反转
        cvtColor(cvimg2,tmpimg2,CV_RGB2GRAY);//灰度处理
        equalizeHist(tmpimg2,tmpimg2);  //直方图均衡化,,用于提高图像的质量
        //将读取的图片写入此路径
        //
        //如果点击了录入信息,开始写入10张图片数据
        vector<Rect> faces2;
        facedector.load("/home/lyx/OpenCv_Src/opencv-3.4.5/install/share/OpenCV/haarcascades/haarcascade_frontalface_alt2.xml");
        facedector.detectMultiScale(tmpimg2,faces2,1.1,3,0,Size(10,10),Size(640,480));
        openluruxinxi=true;

        ///

           //opencv图像转换为qt类型的图像
        QImage qimage=Mat2QImage(cvimg2);
        imwrite("/home/lyx/桌面/image.jpg",cvimg2);
          qDebug()<<"拍照成功";
           //展示ui中的label中
    ui->label_2->setPixmap(QPixmap::fromImage(qimage));

    /
    if(openluruxinxi==true )
    {
        qDebug()<<"开始";
        //最大限度假如是10个图像文件夹
        for(int i=1;i<=10;i++)
        {
            string path=format("/home/lyx/桌面/studeyphoto2/image_%d",i);
                bool cunzai=isFileExists_stat(path);
                if(cunzai)
                {
                    qDebug()<<"存在";

                }
                else
                {
                    qDebug()<<"不存在,创建文件夹";
                    string folderPath =format("/home/lyx/桌面/studeyphoto2/image_%d",i);

                        string command;
                        command = "mkdir -p " + folderPath;
                        system(command.c_str());
                        qDebug()<<"asdsadsadsadsadsadsa";
                        qDebug()<<"文件创建完成,写入图片数据";
                        Mat dst;//存储人脸的mat数据类型

                          for(int count=1;count<=10;count++)
                          {
                                qDebug()<<"aa";
//                            if(cvimg2.empty())
//                            {
//                                qDebug()<<"Photo ERRRR!!!!";
//                            }
                            if(faces2.size()<=0)
                            {
                                qDebug()<<"meiyou face";
                                break;
                            }
                            qDebug()<<i<<"::";
                            cv::resize(cvimg2(faces2[i-1]),dst,Size(100,100));
                            qDebug()<<"bb";
                           //得到了dst图片--仅仅存储着人脸
                           //人脸数据就是 100*100
                           imwrite(format("/home/lyx/桌面/studeyphoto2/image_%d/myface_%d.jpg",i,count),dst);

                           }
                          imagecount=i;
                            qDebug()<<"信息已经录入完成";
                          //这个break代表录入一个人的信息后(拍摄10张照片)就停下了,
                          break;
                }
        }
      qDebug()<<"循环已经跳出";
       qDebug()<<"文件夹数量";
      qDebug()<<imagecount;
    }
    }
}
string doubleToStr(double d){
    char buffer[30];
    sprintf(buffer,"%f",d);
    string str=buffer;
    return str;
}

  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java学习使我快乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值