基于opencv和qt的人脸检测小系统

Posted luoyijie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于opencv和qt的人脸检测小系统相关的知识,希望对你有一定的参考价值。

摘要:利用opencv读取视频、图片并检测人脸,利用QT显示窗口,功能选择等

环境:Ubuntu18.04、OpenCV3.4.0、QT5.10.1

效果图:

技术分享图片

代码如下(比较简单没什么注释):

main.cpp

#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.setWindowTitle("FaceDetect By lyj");
    w.show();
    return a.exec();
}

widget.cpp(xml文件路径要根据个人情况修改)

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QPaintEvent>
#include <QTimer>
#include <QPainter>
#include <QPixmap>
#include <QLabel>
#include <QImage>
#include <QFileDialog>
#include <QString>
using namespace std;

QString mydialog(QString title)
{
    QString path;
    QFileDialog *fileDialog = new QFileDialog();//创建一个QFileDialog对象,构造函数中的参数可以有所添加。
    fileDialog->setWindowTitle(title);//设置文件保存对话框的标题
    fileDialog->setFileMode(QFileDialog::AnyFile);//设置文件对话框弹出的时候显示任何文件,不论是文件夹还是文件
    fileDialog->setViewMode(QFileDialog::Detail);//文件以详细的形式显示,显示文件名,大小,创建日期等信息;
    fileDialog->setGeometry(0,0,200,150);//设置文件对话框的显示位置
    fileDialog->setDirectory(".");//设置文件对话框打开时初始打开的位置
    if(fileDialog->exec() == QDialog::Accepted)
    {
        //注意使用的是QFileDialog::Accepted或者QDialog::Accepted,不是QFileDialog::Accept
        path = fileDialog->selectedFiles()[0];//得到用户选择的文件名
    }
    delete fileDialog;
    return path;
}

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    state = 0;
    connect(&theTimer, &QTimer::timeout, this, &Widget::updateImage);//连接信号与槽,图像刷新
    if(!face_cascade.load("/home/luoyijie/myprogram/qt_project/face_detection/haarcascade_frontalface_alt.xml"))
    {
        qDebug() << "load xml file failed";
    }
    num = 0;
    ui->label->setText("FaceNum: " + QString::number(num));
    srcImage = Mat::zeros(480, 640, CV_8UC3);//图像显示部分初始设置黑色
    this->update();
}

Widget::~Widget()
{
    delete ui;
}
void Widget::on_button1_clicked()
{
    if(state == 0)
    {
        state = 1;
        if(videoCap.open(0))//摄像头读取视频流
        {
            srcImage = Mat::zeros(videoCap.get(CV_CAP_PROP_FRAME_HEIGHT), videoCap.get(CV_CAP_PROP_FRAME_WIDTH), CV_8UC3);
            theTimer.start(33);//time信号
        }
    }
}

void Widget::on_button2_clicked()
{
    if(state == 0)
    {
        state = 2;
        string path_ = mydialog("Open Video").toStdString();
        if(videoCap.open(path_))
        {
            srcImage = Mat::zeros(videoCap.get(CV_CAP_PROP_FRAME_HEIGHT), videoCap.get(CV_CAP_PROP_FRAME_WIDTH), CV_8UC3);
            theTimer.start(33);
        }
    }
}
void Widget::on_button3_clicked()
{
    if(state == 0)
    {
        state = 3;
        string path_ = mydialog("Open Picture").toStdString();
        srcImage = imread(path_);
        updateImage();
    }
}
void Widget::on_button4_clicked()
{
    num = 0;
    switch(state)
    {
        case 0: break;
        case 1:
                srcImage = Mat::zeros(480, 640, CV_8UC3);
                theTimer.stop();
                this->update();
                videoCap.release();
                break;
        case 2:
                srcImage = Mat::zeros(480, 640, CV_8UC3);
                theTimer.stop();
                this->update();
                videoCap.release();
                break;
        case 3:
                srcImage = Mat::zeros(480, 640, CV_8UC3);
                this->update();
                break;
    }
    state = 0;
}
void Widget::updateImage()
{
    if(state == 1 || state == 2)
    {
        videoCap >> srcImage;
    }
    if(srcImage.data)
    {
        vector<Rect> faces;
        face_cascade.detectMultiScale(srcImage, faces, 1.1, 3, 0, Size(50,50), Size(500,500));
        num = faces.size();
        if(faces.size() >= 1)
        {
            for(size_t i=0;i<faces.size();i++)
            {
                Point p1(faces[i].x, faces[i].y);
                Point p2(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
                rectangle(srcImage, p2, p1, cvScalar(0, 0, 255), 1, 4, 0);
            }
        }
        cvtColor(srcImage, srcImage, CV_BGR2RGB);//Qt中支持的是RGB图像, OpenCV中支持的是BGR
        cv::resize(srcImage, srcImage, Size(640,480));
        this->update();  //发送刷新消息
     }
}
void Widget::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    ui->label->setText("FaceNum: " + QString::number(num));
    QImage image1 = QImage((uchar*)(srcImage.data), srcImage.cols, srcImage.rows, QImage::Format_RGB888);
    painter.drawImage(QPoint(0,0), image1);
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTimer>
#include <QLabel>
#include <QPaintEvent>
#include <QPainter>
#include <QPixmap>
#include <QImage>
#include "cv.h"
#include "highgui.h"
#include "opencv.hpp"
using namespace cv;
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:       //声明槽
    void on_button1_clicked();
    void on_button2_clicked();
    void updateImage();
    void on_button4_clicked();
    void on_button3_clicked();
private:
    Ui::Widget *ui;          //ui界面对象指针
    QTimer theTimer;
    //QTimer 计时用;
    QLabel *imageLabel;
    Mat srcImage;
    VideoCapture videoCap;
    CascadeClassifier face_cascade;
    int state;//状态 camera是1,video是2,picture是3,back返回0
    int num;//检测到的人脸数量
protected:
    void paintEvent(QPaintEvent *e);
};
#endif // WIDGET_H

.pro工程配置文件和.ui文件在整个工程的链接里面

https://files.cnblogs.com/files/luoyijie/face_detection.tar.gz

 

以上是关于基于opencv和qt的人脸检测小系统的主要内容,如果未能解决你的问题,请参考以下文章

基于QT和OpenCV的人脸检测识别系统

基于QT和OpenCV的人脸识别系统

人脸检测 OpenCV + Qt + cvMat

OpenCV&Qt学习之四——OpenCV 实现人脸检测与相关知识整理

如何以及在何处使用带有 QT 的 basler 相机实现 opencv 人脸检测代码

使用 Qt Gui 执行慢速实时视频源的 Opencv 人脸检测