VS2022+QT6.7.2+opencv 实时人脸跟踪 (详细)(注释)

一、核心(实时跟踪器)

来源(AI)翻译:
这个CascadeDetectorAdapter类是一个适配器Adapter模式的实现,它主要用于将OpenCV的CascadeClassifier级联分类器封装成DetectionBasedTracker::IDetector接口的形式,以便在基于检测的跟踪器(Detection-Based Tracker)中使用。这样做的好处是提高了代码的复用性和模块化,使得跟踪器能够更容易地替换或集成不同的检测算法。

class CascadeDetectorAdapter : public DetectionBasedTracker::IDetector //跟踪器适配器
{
public:

    //指向级联分类器的智能指针
    CascadeDetectorAdapter(cv::Ptr<cv::CascadeClassifier> detector) :  IDetector(), Detector(detector) 
    {
        CV_Assert(detector);
    }

    //检测函数 输入图像Image中检测对象,并将检测到的对象以矩形框(cv::Rect)的形式存储在objects向量中。
    void detect(const cv::Mat& Image, std::vector<cv::Rect>& objects)
    {
        Detector->detectMultiScale(Image, objects, scaleFactor, minNeighbours, 0, minObjSize, maxObjSize);
    }

private:
    CascadeDetectorAdapter();
    cv::Ptr<cv::CascadeClassifier> Detector;
};

1、 人脸检测调用detectMultiScale方法适合用来检测静态图像

2、使用官方Android包中的CascadeDetectorAdapter类来实时跟踪检测摄像头人脸。

 参考:在Visual Studio上,使用OpenCV实现人脸识别

二、代码

QtWidgetsApplication13.h

#pragma once

#include <QtWidgets/QMainWindow>
#include <ui_QtWidgetsApplication13.h>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/videoio/videoio.hpp>
#include<opencv2/imgproc//imgproc.hpp>

#include<QDebug>
#include<QString>
#include<QThread>
#include<QTimer>
#include<QImage>

using namespace cv;
using namespace std;

class QtWidgetsApplication13 : public QMainWindow //主窗口
{
    Q_OBJECT

public:
    QtWidgetsApplication13(QWidget* parent = nullptr);
    ~QtWidgetsApplication13();

    QTimer* timer = new QTimer(this); //创建定时器
    QThread* thread = new QThread; //创建线程

public slots:
    void readDate(QImage); //槽函数,接受image数据显示在label中

private:
    Ui::QtWidgetsApplication13Class ui;
};

class CascadeDetectorAdapter : public DetectionBasedTracker::IDetector //跟踪器适配器
{
public:

    //指向级联分类器的智能指针
    CascadeDetectorAdapter(cv::Ptr<cv::CascadeClassifier> detector) :  IDetector(), Detector(detector) 
    {
        CV_Assert(detector);
    }

    //检测函数 输入图像Image中检测对象,并将检测到的对象以矩形框(cv::Rect)的形式存储在objects向量中。
    void detect(const cv::Mat& Image, std::vector<cv::Rect>& objects)
    {
        Detector->detectMultiScale(Image, objects, scaleFactor, minNeighbours, 0, minObjSize, maxObjSize);
    }

private:
    CascadeDetectorAdapter();
    cv::Ptr<cv::CascadeClassifier> Detector;
};

class mythread : public QObject //线程类
{
    Q_OBJECT

public:
    void work();
    VideoCapture cap; //视频捕获类
    Ptr<DetectionBasedTracker> tracker; //跟踪器
    Mat frame; //彩色
    Mat grayFrame; //灰度
    Mat equalizeframe; //直方图
    QImage MatImageToQT(const Mat &src); //将Mat转为QImage,显示在label上
    mythread(); //构造函数
    ~mythread(); //析构函数

signals:
    void sendData(QImage);
};

 QtWidgetsApplication13.cpp

#include "QtWidgetsApplication13.h"

using namespace cv;
using namespace std;

QtWidgetsApplication13::QtWidgetsApplication13(QWidget* parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
   
    mythread *th = new mythread(); //创建线程类对象
    th->moveToThread(thread); //将线程绑定到主线程

    connect(timer, &QTimer::timeout, th, &mythread::work); //连接定时器与槽函数

    connect(th,&mythread::sendData,this,&QtWidgetsApplication13::readDate); //线程发送数据

    connect(ui.pushButton, &QPushButton::clicked, this, [=]() {
        thread->start(); //启动线程
        timer->start(30); //设置定时器间隔
        });
}

void mythread::work()
{
    cap.read(frame); //读取彩图
    cvtColor(frame, grayFrame, COLOR_BGR2GRAY); //灰度转换
    equalizeHist(grayFrame, equalizeframe); //直方图转换

    vector<Rect> faces; //定义一个vector容器faces,用于存储检测到的面部信息

    //使用跟踪器的process方法对灰度图像帧grayFrame进行处理,
    tracker->process(grayFrame);

    //调用getObjects方法,从跟踪器中获取当前跟踪到的面部信息,并将这些信息存储在faces容器中
    tracker->getObjects(faces);

    // 在帧上绘制检测到的面部边界框(如果有的话) 
    for (size_t i = 0; i < faces.size(); i++)
    {
        rectangle(frame, faces[i], Scalar(255, 0, 0), 2, 8, 0);  //遍历faces容器,绘制矩形框
        // faces[i] 是要绘制的面部位置信息
    }

    QImage image= MatImageToQT(frame);  //将Mat转换为QImage
    sendData(image); //信号,发送image
}

void QtWidgetsApplication13::readDate(QImage image)
{
    QPixmap pixmap = QPixmap::fromImage(image); //将QImage转换为QPixmap
    ui.label->resize(pixmap.size()); // 调整QLabel的大小以匹配QPixmap的大小
    ui.label->setPixmap(QPixmap::fromImage(image)); //将QPixmap转换为QLabel
}

QImage mythread::MatImageToQT(const Mat& src) // //将Mat转为QImage
{
    // 得到图像的的首地址
    const uchar * pSrc = (const uchar*)src.data;
    //以src构造图片
    QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888);
    //在不改变实际图像数据的条件下,转换红蓝通道
     return qImage.rgbSwapped(); //返回QImage
}

mythread::mythread() //构造函数
{
    //级联分类器作用是进行目标检测,下面的路径是加载它
    string stdFileName = "D:/opencv/opencv/build/etc/haarcascades/haarcascade_frontalface_alt.xml"; //Haar级联分类器的XML文件路径

    //创建一个主检测适配器
    Ptr<CascadeDetectorAdapter> mainDetector = makePtr<CascadeDetectorAdapter>(makePtr<CascadeClassifier>(stdFileName));

    //创建一个跟踪检测适配器
    Ptr<CascadeDetectorAdapter> trackingDetector = makePtr<CascadeDetectorAdapter>(makePtr<CascadeClassifier>(stdFileName));

    //创建跟踪器
    DetectionBasedTracker::Parameters DetectorParams;
    tracker = makePtr<DetectionBasedTracker>(mainDetector, trackingDetector, DetectorParams);

    tracker->run(); //运行跟踪器
    cap.open(0); //打开摄像头
}

mythread::~mythread() //析构函数
{
    tracker->stop(); //停止跟踪器
    cap.release(); //释放视频资源
}

QtWidgetsApplication13::~QtWidgetsApplication13() //析构函数
{
    destroyAllWindows(); //释放所有窗口资源
    timer->stop(); //停止定时器
    thread->quit();
    thread->wait();
}

main.cpp

#include "QtWidgetsApplication13.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QtWidgetsApplication13 w;
    w.show();
    return a.exec();
}

 ui界面如下:label、pushButton

三、效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值