opencv系列(1)--使用opencv和Qt6做一个视频监控器人脸识别

程序功能说明:

这个程序是自己的下班之后,看看那个坏东西想来偷看我的电脑。我就随手做的一个程序。
1.能都显示摄像头的内容。
2.如果有人进入摄像头。
3.利用opencv的模型识别人脸,识别到了就保存到自己的电脑里面。
4.并把他的照片显示到界面上一段时间,告诉他,偷窥有罪。
5.程序是完全可以隐藏的,就是没有界面,可以通过快捷键来显示界面(ctr+p),再次点击则隐藏。按下(ctr+s)结束程序。
6.程序在做的时候,增加了任务栏托盘的功能,也可以通过任务栏托盘进行显示。

说明:

用了全局热键捕捉。第三方库:QHotkey
然后用的opencv 的话是用mingw的编译的,版本是411的,可以自己编译,也可以去github上面去下载已经编译好的,我使用github上编译好的

功能就讲到这里,下边是简单的代码。

文件.pro

QT       += core gui
QT += multimedia
QT += multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

INCLUDEPATH += D:\\Z_DLL\\OpenCV-MinGW4.1.1\\include
LIBS += -LD:\\Z_DLL\\OpenCV-MinGW4.1.1\\x64\\mingw\\lib \
    -lopencv_core411 \
    -lopencv_highgui411 \
    -lopencv_imgproc411 \
    -lopencv_imgcodecs411 \
    -lopencv_objdetect411 \
    -lopencv_videoio411
include(QHotkey/QHotkey.pri)

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${
    
    TARGET}/bin
else: unix:!android: target.path = /opt/$${
    
    TARGET}/bin
!isEmpty(target.path): INSTALLS += target

文件main.cpp

int main(int argc, char *argv[]) {
    
    
    QApplication app(argc, argv);
    //QLabel显示界面
    MyLabel *label=new MyLabel;
    //label->show();
    return app.exec();
}

文件MyLabel

由于我使用QLable来显示图片的

class MyLabel : public QLabel {
    
    
public:
    MyLabel(){
    
    
        //设置热键
        hotkey_Ctrl_S = new QHotkey(QKeySequence("Ctrl+s"), true,this);
        connect(hotkey_Ctrl_S, &QHotkey::activated, qApp, &QCoreApplication::quit);
        hotkey_Ctrl_P = new QHotkey(QKeySequence("Ctrl+p"), true,this);
        connect(hotkey_Ctrl_P, &QHotkey::activated, [&](){
    
    
            if(isHidden())
                show();
            else
                hide();});

        trayIcon = new QSystemTrayIcon;
        trayIcon->setIcon(QIcon("D:\\icon.png")); // 设置托盘图标
        trayIcon->setVisible(true);
        // 创建托盘菜单
        trayIconMenu = new QMenu();
        QAction *quitAction = new QAction("退出", this);
        connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
        trayIconMenu->addAction(quitAction);
        // 设置托盘菜单
        trayIcon->setContextMenu(trayIconMenu);
        connect(trayIcon, &QSystemTrayIcon::activated, this, [&](QSystemTrayIcon::ActivationReason reason){
    
    
        switch (reason) {
    
    
                case QSystemTrayIcon::Trigger:
                case QSystemTrayIcon::DoubleClick:
                    show();
                    break;
                default:
                    break;
            }
        });

        //信号
        connect(&faceDetector, &FaceDetector::imageReady, [&](const QImage &image) {
    
    
            setPixmap(QPixmap::fromImage(image));
            resize(image.size()); // 调整窗口大小以适应图像大小
        });
    }
protected:
    void closeEvent(QCloseEvent *event) override
    {
    
    
        if (trayIcon->isVisible()) {
    
    
            hide();
            event->ignore();
        }
    }
private:
    QSystemTrayIcon *trayIcon;
    QMenu           *trayIconMenu;
    //全局按键监控
    QHotkey *hotkey_Ctrl_P;
    QHotkey *hotkey_Ctrl_S;

    //人脸检测器
    FaceDetector faceDetector;
};

文件FaceDetector

提示警告框我是直接使用了QMessageBox来显示的,重写了一下这个类的事件。
每隔30ms就检测一下是否有人脸存在,如果存在就停止检测并显示警告。
30秒之后就自动的关闭警告窗口,继续监控。

#include <opencv2/opencv.hpp>
#include <opencv2/objdetect.hpp>
#include <QApplication>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QAction>
#include <QCamera>
#include <QImageCapture>
#include <QMediaDevices>
#include <QMediaCaptureSession>
#include <QVideoWidget>
#include <QMouseEvent>
#include <QDateTime>
#include <QMediaRecorder>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QHotkey>
#include <QVideoSink>
#include <QCameraFormat>
#include <QPainter>
#include <QMessageBox>
#include <QTimer>
#include <QImage>
#include <QLabel>

const int CLOSE_TIME = 10000;

class CustomMessageBox : public QMessageBox {
    
    
    Q_OBJECT
public:
    CustomMessageBox(QWidget *parent = nullptr) : QMessageBox(parent) {
    
    
        // 隐藏标准按钮
        setStandardButtons(QMessageBox::NoButton);
    }

signals:
    void timeout();

protected:
    void closeEvent(QCloseEvent *event) override {
    
    
        // 阻止用户关闭对话框
        event->ignore();
    }
};
class FaceDetector : public QObject {
    
    
    Q_OBJECT
public:
    FaceDetector(QObject *parent = nullptr) : QObject(parent) {
    
    
        // 加载人脸检测器
        faceCascade.load("D:\\Code\\Camera\\haarcascade.xml");

        // 打开摄像头
        cap.open(0);

        // 启动定时器,每隔30ms捕获一帧图像
        timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, &FaceDetector::captureFrame);
        timer->start(30);
    }
    ~FaceDetector(){
    
    };

signals:
    void imageReady(const QImage &image);

private slots:
    void captureFrame() {
    
    
        cv::Mat frame;
        cap >> frame;

        // 检测人脸
        std::vector<cv::Rect> faces;
        faceCascade.detectMultiScale(frame, faces);

        // 在检测到的人脸周围画矩形框
        for (const auto &face : faces) {
    
    
            cv::rectangle(frame, face, cv::Scalar(255, 0, 0));
        }

        // 如果检测到人脸,保存图像
        if (!faces.empty()) {
    
    
            QDateTime currentDateTime = QDateTime::currentDateTime();
            QString formattedDateTime = currentDateTime.toString("yyyy_MM_dd_hh_mm_ss");
            QString file="D:\\pic\\"+ formattedDateTime + ".jpg";
            std::string f = file.toStdString();
            cv::imwrite(f, frame);
        }

        // 将cv::Mat转换为QImage
        cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
        QImage image(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);

        if(!faces.empty())
        {
    
    
            // 弹出对话框并显示人脸图像
            QLabel bel;
            CustomMessageBox msgBox(&bel);//=new CustomMessageBox();
            msgBox.setStyleSheet("QLabel {"
                              "font-size: 25px;"
                              "color: red;"
                              "}");
            msgBox.setText("个人使用的电脑有隐私,\n不要偷看!");
            msgBox.setIconPixmap(QPixmap::fromImage(image));
            timer->stop();
            connect(&msgBox, &CustomMessageBox::timeout, [&](){
    
    msgBox.reject();timer->start(30);});

            // CLOSE_TIME秒后发射timeout信号,关闭对话框
            QTimer::singleShot(CLOSE_TIME, &msgBox, &CustomMessageBox::timeout);

            // 显示模态对话框
            msgBox.exec();
        }
        // 发送信号,通知外部图像已准备好
        emit imageReady(image);
    }

private:
    cv::VideoCapture cap;
    cv::CascadeClassifier faceCascade;
    QTimer *timer;
};

猜你喜欢

转载自blog.csdn.net/simple_core/article/details/130648894
今日推荐