Qt 使用摄像头通过openCV进行人脸识别

Qt 使用摄像头通过openCV进行人脸识别

  • 资源下载
  • 环境信息
  • 1. 下载cpenCV和opencv_contrib源码
  • 2. 安装CMake
  • 3. 编译openCV
    • 开始编译
  • 4. 新建工程调用openCV
  • 5. openCV中的基础人脸检测调用
  • 6. 人脸识别
    • 人脸库创建
    • 人脸识别
  • CMake过程可能会有的问题

资源下载

如果想快速开始使用,可以直接使用编译好的,可跳过本文的前3步,由于CSDN上传文件大小限制就分卷压缩上传了(解压保存的路径最好是英文,代码中会用到):

  • 不包含opencv_contrib编译的库:
    卷一:https://download.csdn.net/download/u012902367/11079135
    卷二:https://download.csdn.net/download/u012902367/11079147
    卷三:https://download.csdn.net/download/u012902367/11079153
    第四小节的demo工程:https://download.csdn.net/download/u012902367/11079205
  • 包含opencv_contrib编译的库:
    https://download.csdn.net/download/u012902367/11103882
  • 解决报错的文件(本文最后有提到)
    https://download.csdn.net/download/sunny_lc/9474246
    https://download.csdn.net/download/u012902367/11099517

环境信息

由于版本众多,各个版本之间编译过程可能有所区别,本文选择了一个历史版本(提醒一下不同版本使用方法会存在差异,如果读者想要按照下面的方式尝试,第一次建议选择和笔者同样的版本,成功以后再尝试新版本,还有就是本文所选择的路径在代码中会用到,如果读者怕麻烦修改,甚至可以把盘符和安装路径设置成与本文一致),如下是本文所用的环境参数:

  • 操作系统:win10
    Qt 使用摄像头通过openCV进行人脸识别_第1张图片

  • mingw32-make
    Qt 使用摄像头通过openCV进行人脸识别_第2张图片

  • CMake-3.14.1-win64-x64
    Qt 使用摄像头通过openCV进行人脸识别_第3张图片

  • opencv_contrib-3.2.0
    Qt 使用摄像头通过openCV进行人脸识别_第4张图片

  • opencv-3.2.0

1. 下载cpenCV和opencv_contrib源码

  • 从官网获取到安装程序:
    在这里插入图片描述
    如果官网下载太慢可以选择再CSDN里面搜索下载:
    Qt 使用摄像头通过openCV进行人脸识别_第5张图片

下载下来过后运行安装,请选择纯英文路径:
Qt 使用摄像头通过openCV进行人脸识别_第6张图片
等待安装完成:
Qt 使用摄像头通过openCV进行人脸识别_第7张图片

  • 也可以在git上获取,同时把opencv_contrib下载下来,注意:opencv和opencv_contrib两个版本一定要一致

Qt 使用摄像头通过openCV进行人脸识别_第8张图片
把两个都下载下来,下面那一个包含了一些其它模块功能,比如常用的人脸识别。Qt 使用摄像头通过openCV进行人脸识别_第9张图片
保存在纯英文路径,路径中最好也不要有特殊符号。

2. 安装CMake

官方下载CMake:https://cmake.org/download/
Qt 使用摄像头通过openCV进行人脸识别_第10张图片
下载完后双击安装,安装到纯英文路径,安装完后把bin目录加入环境变量:
Qt 使用摄像头通过openCV进行人脸识别_第11张图片
Qt 使用摄像头通过openCV进行人脸识别_第12张图片
Qt 使用摄像头通过openCV进行人脸识别_第13张图片
Qt 使用摄像头通过openCV进行人脸识别_第14张图片
Qt 使用摄像头通过openCV进行人脸识别_第15张图片
Qt 使用摄像头通过openCV进行人脸识别_第16张图片
Qt 使用摄像头通过openCV进行人脸识别_第17张图片
Qt 使用摄像头通过openCV进行人脸识别_第18张图片
环境变量配置:
Qt 使用摄像头通过openCV进行人脸识别_第19张图片
顺便也将Qt的环境变量配置一下
Qt 使用摄像头通过openCV进行人脸识别_第20张图片

3. 编译openCV

本文就具体描述包含opencv_contrib的编译,不想包含他只需要不添加他的路径就好了,其它的步骤完全一样。
为了cmake正常通过,先下载几个文件放到opencv_contrib的\modules\xfeatures2d\src目录,在CMake过程中也会下载,但是笔者尝试了很多遍都下载失败了,所以就事先把这几个文件都下载下来放到指定目录下就安全多了,当然如果不包含opencv_contrib就可以不要做这一步。需要添加的文件如下:
Qt 使用摄像头通过openCV进行人脸识别_第21张图片
运行安装的CMake。选择路径:
在这里插入图片描述
注意: 若果是选择的使用exe安装的openCV,路径是选择的source。如果是通过git获取的会发现解压出来和exe安装的source下文件一样,选择到对应的目录即可:
Qt 使用摄像头通过openCV进行人脸识别_第22张图片
Qt 使用摄像头通过openCV进行人脸识别_第23张图片

如果是选择git下载解压下来的会发下解压出来的文件目录和exe安装的source文件加下目录几乎一样。

选择好后点击左下角Configure出现如下对话框,照图选择选择:
Qt 使用摄像头通过openCV进行人脸识别_第24张图片
Qt 使用摄像头通过openCV进行人脸识别_第25张图片
等待配置完成,过程可能需要等待几分钟,在配置的过程中需要下载一些文件,最好有:
Qt 使用摄像头通过openCV进行人脸识别_第26张图片
完成过后在列表中勾选 WITH_QT和 WITH_OPENGL(在靠后一点位置),并选择opencv_contrib的路径:
Qt 使用摄像头通过openCV进行人脸识别_第27张图片
Qt 使用摄像头通过openCV进行人脸识别_第28张图片
勾选过后再点击Configure等待运行完成,出现Configuring done,如果还有红色就再点一次Configure,直到界面没有红色框:
Qt 使用摄像头通过openCV进行人脸识别_第29张图片
再点击Generate:
Qt 使用摄像头通过openCV进行人脸识别_第30张图片
完成过后即可关闭此窗口。

开始编译

使用cmd到最开始自己新建的目录下执行mingw32-make:
Qt 使用摄像头通过openCV进行人脸识别_第31张图片

也可以目录下在按住shift点击鼠标右键:
Qt 使用摄像头通过openCV进行人脸识别_第32张图片
在这个目录下执行mingw32-make:
Qt 使用摄像头通过openCV进行人脸识别_第33张图片
等待编译完成,根据电脑配置,过程可能需要15~30分钟:
Qt 使用摄像头通过openCV进行人脸识别_第34张图片
继续执行mingw32-make install,并等待结束:
Qt 使用摄像头通过openCV进行人脸识别_第35张图片
结束后把如下路径添加到环境变量(注意看这个路径位置):
Qt 使用摄像头通过openCV进行人脸识别_第36张图片
Qt 使用摄像头通过openCV进行人脸识别_第37张图片

4. 新建工程调用openCV

如果不想敲可以直接下载这个应用的工程源码。
新建一个应用:
Qt 使用摄像头通过openCV进行人脸识别_第38张图片
Qt 使用摄像头通过openCV进行人脸识别_第39张图片
在.pro文件下添加如下代码,注意里面的路径需要换成读者自己安装的路径

INCLUDEPATH+=D:/openCV3_2/build/install/include/opencv \
             D:/openCV3_2/build/install/include/opencv2 \
             D:/openCV3_2/build/install/include
LIBS += -L D:/openCV3_2/build/install/x86/mingw/lib/libopencv_*.a

Qt 使用摄像头通过openCV进行人脸识别_第40张图片
布局文件中就有两个QLabel,3个QPushButton,为了让读者看得清楚点把两个QLabel背景设置成了绿色,这个对使用没有一点影响,读者可以不用管这个颜色,其中对象的名字也写在图里面了:(camera,photo,open,take,close)
Qt 使用摄像头通过openCV进行人脸识别_第41张图片
mainwindow.h代码

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QTimer>
#include <QImage>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    QImage  Mat2QImage(Mat cvImg);
private slots:
    void openCamara();      // 打开摄像头
    void readFarme();       // 读取当前帧信息
    void closeCamara();     // 关闭摄像头。
    void takingPictures();  // 拍照

private:
    Ui::MainWindow *ui;

    QTimer          *timer;
    QImage          imag;
    Mat             cap,cap_gray,cap_tmp; //定义一个Mat变量,用于存储每一帧的图像
    VideoCapture    capture; //声明视频读入类
};

#endif // MAINWINDOW_H

mainwindow.cpp代码

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    timer   = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(readFarme()));  // 时间到,读取当前摄像头信息
    connect(ui->open, SIGNAL(clicked()), this, SLOT(openCamara()));
    connect(ui->take, SIGNAL(clicked()), this, SLOT(takingPictures()));
    connect(ui->close, SIGNAL(clicked()), this, SLOT(closeCamara()));
}


//打开摄像头
void MainWindow::openCamara()
{
    capture.open(0);    //从摄像头读入视频如果设备只有一个摄像头就传入参数0
    qDebug("open");
    if (!capture.isOpened()) //先判断是否打开摄像头
    {
         qDebug("err");
    }
    timer->start(20);              // 开始计时,20ms获取一帧
}

//读取摄像头信息
void MainWindow::readFarme()
{
    capture>>cap; //读取当前帧
    if (!cap.empty()) //判断当前帧是否捕捉成功 **这步很重要
    {
        imag = Mat2QImage(cap);
        imag = imag.scaled(ui->camera->width(), ui->camera->height(),
                                            Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
        //imshow(name, cap); //若当前帧捕捉成功,显示
        ui->camera->setPixmap(QPixmap::fromImage(imag));  // 将图片显示到label上
    }
    else
        qDebug("can not ");

}


// 拍照
void MainWindow::takingPictures()
{
    capture>>cap; //读取当前帧
    if (!cap.empty()) //判断当前帧是否捕捉成功 **这步很重要
    {
        imag = Mat2QImage(cap);
        imag = imag.scaled(ui->photo->width(), ui->photo->height(),
                                            Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致

        //imshow(name, cap); //若当前帧捕捉成功,显示
        ui->photo->setPixmap(QPixmap::fromImage(imag));  // 将图片显示到label上
    }
    else
        qDebug("can not ");
}


//关闭摄像头,释放资源,必须释放***
void MainWindow::closeCamara()
{
    timer->stop();         // 停止读取数据。
}


// 图片转换(网上抄的)
QImage  MainWindow::Mat2QImage(Mat cvImg)
{
    QImage qImg;
    if(cvImg.channels()==3)     //3 channels color image
    {

        cv::cvtColor(cvImg,cvImg,CV_BGR2RGB);
        qImg =QImage((const unsigned char*)(cvImg.data),
                    cvImg.cols, cvImg.rows,
                    cvImg.cols*cvImg.channels(),
                    QImage::Format_RGB888);
    }
    else if(cvImg.channels()==1)                    //grayscale image
    {
        qImg =QImage((const unsigned char*)(cvImg.data),
                    cvImg.cols,cvImg.rows,
                    cvImg.cols*cvImg.channels(),
                    QImage::Format_Indexed8);
    }
    else
    {
        qImg =QImage((const unsigned char*)(cvImg.data),
                    cvImg.cols,cvImg.rows,
                    cvImg.cols*cvImg.channels(),
                    QImage::Format_RGB888);
    }
    return qImg;
}

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

需要把如下的文件全部拷贝到应用编译生成的.exe文件同级目录下,否则会编译出错:
Qt 使用摄像头通过openCV进行人脸识别_第42张图片
Qt 使用摄像头通过openCV进行人脸识别_第43张图片
到此就可以编译成功运行了,左边的是摄像头实时图像,右边是点击拍照后保存的图片:
Qt 使用摄像头通过openCV进行人脸识别_第44张图片

5. openCV中的基础人脸检测调用

openCV资源里面有一些现成的.xml文件,就是用来检测人脸的,这些文件在本文最开始openCV的安装路径下就可以找到:
Qt 使用摄像头通过openCV进行人脸识别_第45张图片
本文就测试两个就一个是眼睛检测,一个是人脸检测并用方框圈出来,是在上面的工程中修改的,只修改了如下两处:

  • 将如下代码放入到mainwindow.h中:
    CascadeClassifier eye_Classifier;  //载入分类器
    CascadeClassifier face_cascade;    //载入分类器
    //vector 是个类模板 需要提供明确的模板实参 vector则是个确定的类 模板的实例化  需要指点std域名才可以用:using namespace std;
    vector<Rect> eyeRect;
    vector<Rect> faceRect;
    vector<Rect> faces;

Qt 使用摄像头通过openCV进行人脸识别_第46张图片

  • 修改mainwindow.cpp中readFarme()方法的内容为如下:
void MainWindow::readFarme()
{
    capture>>cap; //读取当前帧
    if (!cap.empty()) //判断当前帧是否捕捉成功 **这步很重要
    {
        cvtColor(cap, cap_gray, CV_BGR2GRAY);//转为灰度图
        equalizeHist(cap_gray, cap_gray);//直方图均衡化,增加对比度方便处理

        //加载分类训练器,OpenCv官方文档提供的xml文档,可以直接调用
        //xml文档路径,  opencv\sources\data\haarcascades
        if (!eye_Classifier.load("D:\\opencvSet\\opencv\\sources\\data\\haarcascades\\haarcascade_eye.xml"))  //需要将xml文档放在自己指定的路径下
        {
            qDebug("Load haarcascade_eye.xml failed!");
            return;
        }
        if (!face_cascade.load("D:\\opencvSet\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml"))
        {
            qDebug("Load haarcascade_frontalface_alt failed!");
            return;
        }

        //检测关于眼睛部位位置
        eye_Classifier.detectMultiScale(cap_gray, eyeRect, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));//检测
        for (size_t eyeIdx = 0; eyeIdx < eyeRect.size(); eyeIdx++)
        {
            rectangle(cap, eyeRect[eyeIdx], Scalar(0, 0, 255));   //用红色矩形画出检测到的位置
        }
        //检测关于脸部位置
        face_cascade.detectMultiScale(cap_gray, faceRect, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));//检测
        for (size_t i = 0; i < faceRect.size(); i++)
        {
            rectangle(cap, faceRect[i], Scalar(0, 255, 0));      //用绿色矩形画出检测到的位置
        }
        imag = Mat2QImage(cap);     // 将Mat转换成QImage对象来显示
        imag = imag.scaled(ui->camera->width(), ui->camera->height(),
                                            Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
        //imshow(name, cap); //若当前帧捕捉成功,显示
        ui->camera->setPixmap(QPixmap::fromImage(imag));  // 将图片显示到label上
    }
    else
        qDebug("can not ");
}

效果如下:
Qt 使用摄像头通过openCV进行人脸识别_第47张图片
可以看出官方提供分类训练器也有一些误检测。

6. 人脸识别

分清两个概念:

  • 人脸检测:检测出画面中是否存在人脸。
  • 人脸识别:根据人脸特征识别出这个人具体是谁。

上一小节已经利用opencv现成的人脸模型实现了检测人脸,这一小节就描写一下如何利用opencv提供的平台实现人脸识别,这里得所谓的人脸识别实际就是从摄像头视频或者照片里面查找人脸,然后把查找到的人脸处理成指定大小,再与人脸库对比,获取到对比结果。

人脸库创建

为了提高识别率最好准备各个角度的面部照片(测试过jpg和pgm两种格式均可),就像下面一样,同一个人有10张不同角度的照片:
Qt 使用摄像头通过openCV进行人脸识别_第48张图片

可以直接下载Database of Faces下来作为自己的参考人脸库:
Qt 使用摄像头通过openCV进行人脸识别_第49张图片
下载完解压出来有如下目录:
Qt 使用摄像头通过openCV进行人脸识别_第50张图片
共40个文件夹,每一个文件夹里面为同一个人的不同角度10张图片,是pgm格式的,windows的图片查看软件打不开,不过可以是使用opencv提供的方法来查看,代码的路径就是刚才下载下来的文件第一个人脸:

Mat img;
img = imread("C:/Users/XF/Desktop/orl_faces/s1/1.pgm", CV_LOAD_IMAGE_GRAYSCALE);
imshow("img", img);

Qt 使用摄像头通过openCV进行人脸识别_第51张图片
准备我们自己需要的人脸照片处理跟下载下来为图片参数一致,人脸图为灰度图,大小为92*112,保存为第41个文件夹,如果自己需要添加几个人的面部信息就按照如此规律往后添加即可:
Qt 使用摄像头通过openCV进行人脸识别_第52张图片
网上看的文章很多都会有一个类似如下的文本文件:
Qt 使用摄像头通过openCV进行人脸识别_第53张图片
这个文件主要是给代码快速获取图片路径的,所说的标签也仅仅只是表示这张图片代表的是库里面的第几个人,所以这个文件不是必要的,本文就不用这个文件直接手动来获取,我想这样读者会更容易理解,
如下代码就是用来生成人脸库的, 当然这里只选了几个人的脸部照片,要把每一个都添加进去靠动手输入是很麻烦,这也就是为什么会有上面那个文本文档来保存路径和标签信息,通过读取文档里面的路径和标签信息可以快速准简单的实现如下功能,也是一劳永逸:

void MainWindow::on_pushButton_clicked()
{
    vector<Mat> images;
    Mat img;
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/1.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/2.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/3.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/4.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/5.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/6.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/7.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/8.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/9.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s1/10.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中

    img = imread("C:/Users/XF/Desktop/orl_faces/s2/1.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/2.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/3.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/4.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/5.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/6.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/7.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/8.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/9.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s2/10.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中

    img = imread("C:/Users/XF/Desktop/orl_faces/s3/1.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/2.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/3.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/4.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/5.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/6.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/7.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/8.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/9.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/orl_faces/s3/10.pgm", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中


    img = imread("C:/Users/XF/Desktop/face_jpg/1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/2.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/3.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/4.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/5.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/6.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/7.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/8.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/9.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中
    img = imread("C:/Users/XF/Desktop/face_jpg/10.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    images.push_back(img); // 将图片 添加到images中


    vector<int> labels;
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);
    labels.push_back(0);

    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);
    labels.push_back(1);

    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);
    labels.push_back(2);

    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);
    labels.push_back(3);

    Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
    model->train(images, labels);
    model->save("MyFacePCAModel.xml");
}

可以看得出上面是通过一个按钮来实现开始训练自己的人脸库,运行过后会在exe的上一级目录下多一个MyFacePCAModel.xml文件:
Qt 使用摄像头通过openCV进行人脸识别_第54张图片

人脸识别

有了它就可以开始进行识别了,也就不再新建工程了,其它代码和上一小节的工程中代码一致,只是修改了readFarme()方法如下,里面有些路径需要修改成自己电脑中文件所在路径

//读取摄像头信息
void MainWindow::readFarme()
{
    capture>>cap; //读取当前帧
    if (!cap.empty()) //判断当前帧是否捕捉成功 **这步很重要
    {
        cvtColor(cap, cap_gray, CV_BGR2GRAY);   //转为灰度图
        equalizeHist(cap_gray, cap_gray);       //直方图均衡化,增加对比度方便处理

        if (!face_cascade.load("D:\\openCV3_2\\opencv-3.2.0\\data\\haarcascades\\haarcascade_frontalface_alt.xml"))
        {
            qDebug("Load haarcascade_frontalface_alt failed!");
            return;
        }

        Ptr<FaceRecognizer> modelPCA = createEigenFaceRecognizer();
        modelPCA->load("E:\\workspace\\Qt_workspace\\build-face-Desktop_Qt_5_11_1_MinGW_32bit-Debug\\MyFacePCAModel.xml");//加载分类器

        if (!eye_Classifier.load("D:\\openCV3_2\\opencv-3.2.0\\data\\haarcascades\\haarcascade_eye.xml"))  //需要将xml文档放在自己指定的路径下
        {
            qDebug("Load haarcascade_eye.xml failed!");
            return;
        }

        //检测关于脸部位置
        face_cascade.detectMultiScale(cap_gray, faceRect, 1.1, 3, 0 | CV_HAAR_DO_ROUGH_SEARCH, Size(50, 50));//检测
        for (size_t i = 0; i < faceRect.size(); i++)
        {
            rectangle(cap, faceRect[i], Scalar(0, 255, 0));      //用绿色矩形画出检测到的位置
            Mat faceROI = cap_gray(faceRect[i]);


            int predictPCA = 0;
            Mat face_test;
            Point text_lb;
			// 不加前面的cv::的话resize()方法会和MainWindow中的resize()冲突。
            cv::resize(faceROI,face_test,Size(92, 112));
            imshow("frame", face_test);
            //测试图像应该是灰度图
            predictPCA = modelPCA->predict(face_test);
            qDebug("%d",predictPCA);
            if(predictPCA==3)  // 这个3也就是上面labels.push_back(3);和图片是一一对应的
            {
                string name = "xufan";  // 文本提示
                text_lb = Point(faceRect[i].x, faceRect[i].y);
                putText(cap, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
            }
            
            //imshow("frame", faceROI);
            //检测关于眼睛部位位置
            int eye_num=0;
            eye_Classifier.detectMultiScale(faceROI, eyeRect, 1.1, 1, 0 | CV_HAAR_DO_ROUGH_SEARCH, Size(30, 30));//检测
            for (size_t j = 0; j < eyeRect.size(); j++)
            {
                Rect rect(faceRect[i].x + eyeRect[j].x, faceRect[i].y + eyeRect[j].y, eyeRect[j].width, eyeRect[j].height);
                rectangle(cap, rect, Scalar(255, 0, 0));   //用蓝色矩形画出检测到的位置
                eye_num++;
                if(eye_num==2)
                    break;
            }
        }
        imag = Mat2QImage(cap);     // 将Mat转换成QImage对象来显示
        imag = imag.scaled(ui->camera->width(), ui->camera->height(),
                                            Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
        ui->camera->setPixmap(QPixmap::fromImage(imag));  // 将图片显示到label上
    }
    else
        qDebug("can not ");
}

运行过后就会出现就可以识别到视频中的人脸:
Qt 使用摄像头通过openCV进行人脸识别_第55张图片

CMake过程可能会有的问题

CMake时会下载几个文件,下载失败会导致提示工程不可用,可直接手动从网上下载然后按照如下操作,添加到源文件中即可,如下所用到资源在本文最上面可以找到连接,添加文件如下:

  1. 将 opencv_ffmpeg.dll和opencv_ffmpeg_64.dll 复制到openCv资源的3rdparty\ffmpeg目录下
    Qt 使用摄像头通过openCV进行人脸识别_第56张图片
  2. 将 ippicv_windows_20151201.zip 解压到:\3rdparty\ippicv\unpack 如果没有unpack文件夹,新建一个。形成这样的目录树: \3rdparty\ippicv\unpack\ippicv_win…,请仔细对比路径:
    Qt 使用摄像头通过openCV进行人脸识别_第57张图片
  3. opencv_contrib里面的添加如下文件。
    Qt 使用摄像头通过openCV进行人脸识别_第58张图片

你可能感兴趣的:(Qt)