一、核心(实时跟踪器)
来源(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