基于ubuntu+opencv+qt实现的简单人脸识别

做这个也是被课设所逼迫,弄了个看着还挺高大上的东西,我这个小白还是记录一下吧
其实前期主要是在安装和配置环境这哉了好几天了,后来在b站上看到一个视频顿时开窍了,视频里用的是opencv3.3+opencv-contrib3.3,但是我安装的时候发现还是有点问题,因为缺少的.i文件好像加不进去,所以我就换成了4.3.0的版本,就一点毛病都没有了,注意opencv和contrib的版本要一样。
还有就是不要在共享目录下面安装opencv,不然编译时会出问题。
附上视频链接:

https://www.bilibili.com/video/BV1MK411A7XT

缺少的文件和放的位置视频里都有讲,跟着视频走就完事,我这里就不再赘述了。
其实这里还有个地方就是可能在运行失败的时候会提示没有链接成功,在没用qt进行开发的时候,需在cmakeList.txt里面添加相应的库、库路径和头文件路径
如下(改成你自己相应的目录和库):
set(OpenCV_INCLUDE_DIRS /home/china/opencv/opencv-4.3.0_install/include/opencv4/opencv2) set(OpenCV_LIB_DIR /home/china/opencv/opencv-4.3.0_install/lib) set(OpenCV_LIBS /home/china/opencv/opencv-4.3.0_install/lib/libopencv_face.so /home/china/opencv/opencv-4.3.0_install/lib/libopencv_freetype.so /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 )
还有最下面需要改成:

# Link your application with OpenCV libraries
target_link_libraries(opencv_t PRIVATE ${OpenCV_LIBS} )

这样就不会报链接错误了
其实大部分错误都是库没找到或者相应头文件没找到,只要动动手指改一改就可以了。
如果这个不够详细的话可以看看这位的博客:

https://blog.csdn.net/shanyicheng1111/article/details/77485926

代码在ubuntu上能编译运行后,就想着放到qt上去了,其实这个时候也就和前面大同小异了,各种库各种头文件,我后面还把数据库给加进去了,显得可能比较乱。
附上部分代码:
pro文件

#-------------------------------------------------
#
# Project created by QtCreator 2020-11-21T11:34:13
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = opencv_qt
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp \
    form.cpp

HEADERS += \
        mainwindow.h \
    form.h

INCLUDEPATH += /mnt/hgfs/share/opencv \
                /usr/local/include\
                /home/china/opencv/opencv-4.3.0_install/include/opencv4/opencv2 \
            /home/china/opencv/opencv-4.3.0_install/include/opencv4 \
               /usr/local/include/opencv \
               /usr/local/include/opencv2


LIBS += /home/china/opencv/opencv-4.3.0_install/lib/libopencv_highgui.so     \
        /home/china/opencv/opencv-4.3.0_install/lib/libopencv_face.so  \
         /home/china/opencv/opencv-4.3.0_install/lib/libopencv_freetype.so    \
         /home/china/opencv/opencv-4.3.0_install/lib/libopencv_core.so      \
         /home/china/opencv/opencv-4.3.0_install/lib/libopencv_imgproc.so   \
          /home/china/opencv/opencv-4.3.0_install/lib/libopencv_imgcodecs.so     \
        /home/china/opencv/opencv-4.3.0_install/lib/libopencv_objdetect.so  \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_calib3d.so  \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_dnn.so  \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_features2d.so  \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_flann.so  \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_video.so \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_videoio.so \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_photo.so \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_stitching.so \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_gapi.so \
/home/china/opencv/opencv-4.3.0_install/lib/libopencv_ml.so \
/usr/lib/x86_64-linux-gnu/libsqlite3.so.0\




FORMS += \
        mainwindow.ui \
    form.ui

RESOURCES += \
    ziti.qrc \
    1.qrc

//mainwindow.cpp用于实现人脸识别和录入的主要功能
/*
 * 人名和标签主要使用sqlite3数据库存储,图片库的的图片名和标签用name.txt文件存贮,
  图片和人名的联系主要通过标签索引
*/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<opencv2/opencv.hpp>
#include"face.hpp"
#include<iostream>
#include <fstream>
#include <opencv2/highgui/highgui_c.h>
#include <sstream>
#include "face/facerec.hpp"
#include <opencv2/core.hpp>
#include<unistd.h>
#include<opencv2/imgproc.hpp>
//#include<opencv/highgui.h>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<freetype.hpp>

using namespace cv;
using namespace cv::face;
using namespace std;
//人脸识别库
string haar_face_datapath="haarcascade_frontalface_alt_tree.xml";
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    form = new Form;
    connect(form,SIGNAL(sig_in(QString)),this,SLOT(name_in(QString)));
}

MainWindow::~MainWindow()
{
    delete ui;
}


//初始化数据库
int init_db(sqlite3* db)
{

    int flag;
    char *errmsg;
    //创建表
    const char *sql="create table opencv_t(num int primary key,name text(255) not null);";
    //计算数据库的总行数,以便之后的索引
    const char *sql1="select count(*) from opencv_t; ";
     sqlite3_stmt *stmt = NULL; 	   //stmt语句句柄
    int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    sqlite3_step(stmt);

    sqlite3_prepare_v2(db, sql1, -1, &stmt, NULL);
    sqlite3_step(stmt);
    int result1 = sqlite3_column_int(stmt,0);
    cout<<result1;
    //sqlite3_close(db);
    return result1;

}

//图片计数--为了给图片计数命名 如face_1,face_2....
void get_count(int *count)
{
    char flag;
    ifstream fin("name.txt" );
    //FILE *fp=fopen("name.txt","r+");//open the TXT file, can only read, cannot write

    while(fin.get(flag))
        {
            if(flag=='\n')
            *count++;
        }

     qDebug()<<"--++++--";

    fin.close();
    //fclose(fp);


}


//人脸识别按钮实现
void MainWindow::on_pushButton_clicked()
{
        //加载姓名文件
        string filename=string("./name.txt");
        ifstream file(filename.c_str(), ifstream::in);
        if(!file)
        {
            printf("can't find load file");
            return ;
        }

        string line,path,classlabel;
        vector<Mat> images;
        vector<int> labels;
        //用分号把姓名和标签分开
        char separator = ';';
        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()));

            }
        }

        if(images.size()<1 || labels.size()<1)
        {
            printf("invaild image path\n");
            return ;
        }
        int height=images[0].rows;
        int width= images[0].cols;
        printf("heiget: %d ,width: %d \n",height,width);
        Mat testSample =images[images.size()-1];
        int testLabel=labels[labels.size()-1];
        images.pop_back();
        labels.pop_back();
        //三种人脸识别算法
    //	Ptr<BasicFaceRecognizer>model =FisherFaceRecognizer::create();
        Ptr<LBPHFaceRecognizer>model =LBPHFaceRecognizer::create();
    //	Ptr<EigenFaceRecognizer>model =EigenFaceRecognizer :: create();
        //进行模型训练
        model->train(images,labels);
        int predictedLabel=model->predict(testSample);
        printf("actual label: %d,predict label: %d\n",testLabel,predictedLabel);

        CascadeClassifier faceDetector;
        faceDetector.load(haar_face_datapath);      //加载人脸数据
        //打开摄像头
        VideoCapture capture(0);
        if(!capture.isOpened())
        {
            cout<<"打开失败!!"<<endl;
            return ;
        }
        sqlite3* db1;
        int re=sqlite3_open("opencv_db.db",&db1);
        //加载字体
        Ptr<freetype::FreeType2> ft2;
        ft2=freetype::createFreeType2();
        ft2->loadFontData("./simhei.ttf",0);

        Mat frame;
        //namedWindow("人脸识别",CV_WINDOW_AUTOSIZE);
        vector<Rect> faces;
        Mat dst;
        //读取面部
        while(capture.read(frame))
        {
            flip(frame,frame,1);

            faceDetector.detectMultiScale(frame,faces,1.1,1,0,Size(80,100),Size(380,400));
            for(int i=0;i<faces.size();i++)
            {
                Mat roi=frame(faces[i]);
                //图像预处理
                cvtColor(roi,dst,COLOR_BGR2GRAY);

                cv::resize(dst,testSample,testSample.size());

                int label=model->predict(testSample);
                //用矩形框出来
                rectangle(frame,faces[i],Scalar(255,0,0),2,8,0);

                string text;

                 //在数据库中查找人脸标签,如果找到就输出人名
                char sql[128] = {0};
                sprintf(sql,"select * from opencv_t where num=%d;",label);
               // cout<<sql;
                sqlite3_stmt *stmt = NULL; 	   //stmt语句句柄
                int result = sqlite3_prepare_v2(db1, sql, -1, &stmt, NULL);
                if(result != SQLITE_OK )
                {
                    printf("open error %s\n:",sqlite3_errmsg(db1));

                }

                if( sqlite3_step(stmt) ==SQLITE_ROW )
                {
                    int id =sqlite3_column_int( stmt, 0);
                    const unsigned char * names = sqlite3_column_text(stmt,1);
                    ft2->putText(frame,(char *)names,cvPoint(faces[i].x,faces[i].y -10),40,Scalar(255,0,0),-1,8,true);
                    cout << names<<endl;

               }


            }
            //显示
            imshow("face",frame);
            //等键盘输入ESC键退出
            if(waitKey(50)==27)
            {
                sqlite3_close(db1);
                break;
            }
}

        sqlite3_close(db1);
        waitKey(0);
        return ;
}

//人脸录入
void face_in(QString name1)
{
    char*  name;

    QByteArray ba = name1.toLatin1(); // 把QString类型转换成char *
    name=ba.data();
    int count=0;
    get_count(&count);

    sqlite3* db;
    int re=sqlite3_open("opencv_db.db",&db);

    int pic_label=init_db(db);			//获得标签数 -- 有几个人

    //插入新人名和标签`
    char sql[128] = {0};
    sprintf(sql,"insert into opencv_t(num, name) values(%d,'%s');",pic_label,name);
    cout<<sql;
    sqlite3_stmt *stmt = NULL; 	   //stmt语句句柄
    int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if(result != SQLITE_OK )
    {
      printf("open error %s\n:",sqlite3_errmsg(db));

    }

    re=sqlite3_step(stmt);
    if(re != SQLITE_DONE)
    {
      printf("insert data error:%s\n",sqlite3_errmsg(db));
    //  return ;
    }

    string filename=string("./name.txt");
    //在文件末尾增加人脸图片数据
    ofstream file(filename,ios::app);
    if(!file)
    {
      printf("can't find load file");
      return ;
    }

    VideoCapture capture(-1);
    if(!capture.isOpened())
    {
      cout<<"打开失败!!"<<endl;
      return ;
    }
    //级联分类器
    CascadeClassifier faceDetector;
    faceDetector.load(haar_face_datapath);
    Mat frame,img;
    vector<Rect> faces;
    //faceCascade.detectMultiScale(imgGray, faces,1.2,5,0,Size(30,30));
    while(capture.read(frame))
    {
      flip(frame, frame ,1);
      faceDetector.detectMultiScale(frame, faces,1.1,1,0,Size(100,100));
      for(int i =0 ;i<faces.size();i++)
      {
          img=frame;
          rectangle(frame,faces[i],Scalar(0,0,255),2,0,0);
          imshow("camera-demo",frame);
          char c=waitKey(0);
          //空格键拍照并录入训练库
          if(c==32)
          {
              Mat dst;

              cv::resize(img(faces[i]),dst,Size(100,100));
              imwrite(format("./image/face_%d.jpg",++count),dst);
              //打开文件
              //写入文件"image/face_1;"
              file<<"image/face_"<<count<<".jpg;"<<pic_label<<endl;
              cout<<"save:face_"<<count<<endl;

          }
          else if(c==27)
          {
              //按ESC键退出
              capture.release();
              sqlite3_finalize(stmt);
               sqlite3_close(db);
              return ;
          }
          else if(c=='n')           //按n键不要这张图片
              break;
      }
    }
    capture.release();
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return ;


}

void MainWindow::on_pushButton_2_clicked()
{
    //显示人脸信息输入框
         form->show();
}


void MainWindow::name_in(QString na)
{
    qDebug()<<"------"<<na;
    name=na;
    face_in(name);

}

大致的效果图:

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值