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

2024-08-21 12:48

本文主要是介绍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
    在这里插入图片描述

  • mingw32-make
    在这里插入图片描述

  • CMake-3.14.1-win64-x64
    在这里插入图片描述

  • opencv_contrib-3.2.0
    在这里插入图片描述

  • opencv-3.2.0

1. 下载cpenCV和opencv_contrib源码

  • 从官网获取到安装程序:
    在这里插入图片描述在这里插入图片描述
    如果官网下载太慢可以选择再CSDN里面搜索下载:
    在这里插入图片描述

下载下来过后运行安装,请选择纯英文路径:
在这里插入图片描述
等待安装完成:
在这里插入图片描述

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

在这里插入图片描述
把两个都下载下来,下面那一个包含了一些其它模块功能,比如常用的人脸识别。在这里插入图片描述
保存在纯英文路径,路径中最好也不要有特殊符号。

2. 安装CMake

官方下载CMake:https://cmake.org/download/
在这里插入图片描述
下载完后双击安装,安装到纯英文路径,安装完后把bin目录加入环境变量:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
环境变量配置:
在这里插入图片描述
顺便也将Qt的环境变量配置一下
在这里插入图片描述

3. 编译openCV

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

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

选择好后点击左下角Configure出现如下对话框,照图选择选择:
在这里插入图片描述
在这里插入图片描述
等待配置完成,过程可能需要等待几分钟,在配置的过程中需要下载一些文件,最好有vpn:
在这里插入图片描述
完成过后在列表中勾选 WITH_QT和 WITH_OPENGL(在靠后一点位置),并选择opencv_contrib的路径:
在这里插入图片描述
在这里插入图片描述
勾选过后再点击Configure等待运行完成,出现Configuring done,如果还有红色就再点一次Configure,直到界面没有红色框:
在这里插入图片描述
再点击Generate:
在这里插入图片描述
完成过后即可关闭此窗口。

开始编译

使用cmd到最开始自己新建的目录下执行mingw32-make
在这里插入图片描述

也可以目录下在按住shift点击鼠标右键:
在这里插入图片描述
在这个目录下执行mingw32-make
在这里插入图片描述
等待编译完成,根据电脑配置,过程可能需要15~30分钟:
在这里插入图片描述
继续执行mingw32-make install,并等待结束:
在这里插入图片描述
结束后把如下路径添加到环境变量(注意看这个路径位置):
在这里插入图片描述
在这里插入图片描述

4. 新建工程调用openCV

如果不想敲可以直接下载这个应用的工程源码。
新建一个应用:
在这里插入图片描述
在这里插入图片描述
.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

在这里插入图片描述
布局文件中就有两个QLabel,3个QPushButton,为了让读者看得清楚点把两个QLabel背景设置成了绿色,这个对使用没有一点影响,读者可以不用管这个颜色,其中对象的名字也写在图里面了:(camera,photo,open,take,close)
在这里插入图片描述
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_OBJECTpublic: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);    //从摄像头读入视频如果设备只有一个摄像头就传入参数0qDebug("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上}elseqDebug("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上}elseqDebug("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文件同级目录下,否则会编译出错:
在这里插入图片描述
在这里插入图片描述
到此就可以编译成功运行了,左边的是摄像头实时图像,右边是点击拍照后保存的图片:
在这里插入图片描述

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

openCV资源里面有一些现成的.xml文件,就是用来检测人脸的,这些文件在本文最开始openCV的安装路径下就可以找到:
在这里插入图片描述
本文就测试两个就一个是眼睛检测,一个是人脸检测并用方框圈出来,是在上面的工程中修改的,只修改了如下两处:

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

在这里插入图片描述

  • 修改mainwindow.cppreadFarme()方法的内容为如下:
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\haarcascadesif (!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上}elseqDebug("can not ");
}

效果如下:
在这里插入图片描述
可以看出官方提供分类训练器也有一些误检测。

6. 人脸识别

分清两个概念:

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

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

人脸库创建

为了提高识别率最好准备各个角度的面部照片(测试过jpg和pgm两种格式均可),就像下面一样,同一个人有10张不同角度的照片:
在这里插入图片描述

可以直接下载Database of Faces下来作为自己的参考人脸库:
在这里插入图片描述
下载完解压出来有如下目录:
在这里插入图片描述
共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);

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

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文件:
在这里插入图片描述

人脸识别

有了它就可以开始进行识别了,也就不再新建工程了,其它代码和上一小节的工程中代码一致,只是修改了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上}elseqDebug("can not ");
}

运行过后就会出现就可以识别到视频中的人脸:
在这里插入图片描述

CMake过程可能会有的问题

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

  1. 将 opencv_ffmpeg.dll和opencv_ffmpeg_64.dll 复制到openCv资源的3rdparty\ffmpeg目录下
    在这里插入图片描述
  2. 将 ippicv_windows_20151201.zip 解压到:\3rdparty\ippicv\unpack 如果没有unpack文件夹,新建一个。形成这样的目录树: \3rdparty\ippicv\unpack\ippicv_win…,请仔细对比路径:
    在这里插入图片描述
  3. opencv_contrib里面的添加如下文件。
    在这里插入图片描述

这篇关于Qt 使用摄像头通过openCV进行人脸识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093208

相关文章

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

如何使用Nginx配置将80端口重定向到443端口

《如何使用Nginx配置将80端口重定向到443端口》这篇文章主要为大家详细介绍了如何将Nginx配置为将HTTP(80端口)请求重定向到HTTPS(443端口),文中的示例代码讲解详细,有需要的小伙... 目录1. 创建或编辑Nginx配置文件2. 配置HTTP重定向到HTTPS3. 配置HTTPS服务器

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自