程序功能说明:
这个程序是自己的下班之后,看看那个坏东西想来偷看我的电脑。我就随手做的一个程序。
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;
};