OPENCV QT线程池示例,主线程采集摄像头视频,两个子线程显示图像和保存图像
时间: 2023-07-08 20:22:50 浏览: 380
好的,这里给您提供一个 OpenCV 和 Qt 的线程池示例,主线程采集摄像头视频,两个子线程分别显示图像和保存图像:
```cpp
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <opencv2/opencv.hpp>
using namespace cv;
class DisplayThread : public QThread
{
Q_OBJECT
public:
DisplayThread(QObject *parent = nullptr) : QThread(parent) {}
signals:
void imageReady(QImage image);
protected:
void run() override
{
VideoCapture cap(0);
if (!cap.isOpened()) {
qDebug() << "Cannot open camera";
return;
}
while (true) {
Mat frame;
cap >> frame;
if (frame.empty()) {
qDebug() << "Capture frame failed";
break;
}
QImage image = QImage(frame.data, frame.cols, frame.rows, QImage::Format_RGB888).rgbSwapped();
emit imageReady(image);
}
}
};
class SaveThread : public QThread
{
Q_OBJECT
public:
SaveThread(QObject *parent = nullptr) : QThread(parent) {}
void setSavePath(const QString &path)
{
m_savePath = path;
}
signals:
void saveDone(const QString &path);
protected:
void run() override
{
VideoCapture cap(0);
if (!cap.isOpened()) {
qDebug() << "Cannot open camera";
return;
}
int i = 0;
while (true) {
Mat frame;
cap >> frame;
if (frame.empty()) {
qDebug() << "Capture frame failed";
break;
}
QString fileName = QString("%1/frame_%2.jpg").arg(m_savePath).arg(i++);
imwrite(fileName.toStdString(), frame);
emit saveDone(fileName);
}
}
private:
QString m_savePath;
};
class VideoPlayer : public QObject
{
Q_OBJECT
public:
VideoPlayer(QObject *parent = nullptr) : QObject(parent)
{
m_displayThread = new DisplayThread(this);
m_saveThread = new SaveThread(this);
connect(m_displayThread, &DisplayThread::imageReady, this, &VideoPlayer::onImageReady);
connect(m_saveThread, &SaveThread::saveDone, this, &VideoPlayer::onSaveDone);
m_displayThread->start();
m_saveThread->start();
}
~VideoPlayer()
{
m_displayThread->quit();
m_displayThread->wait();
m_saveThread->quit();
m_saveThread->wait();
}
signals:
void imageReady(QImage image);
void saveDone(const QString &path);
private slots:
void onImageReady(QImage image)
{
emit imageReady(image);
}
void onSaveDone(const QString &path)
{
emit saveDone(path);
}
private:
DisplayThread *m_displayThread;
SaveThread *m_saveThread;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
VideoPlayer player;
QObject::connect(&player, &VideoPlayer::imageReady, [](QImage image){
// 显示图像
});
QObject::connect(&player, &VideoPlayer::saveDone, [](const QString &path){
// 保存图像
});
return a.exec();
}
#include "main.moc"
```
在这个示例中,我们创建了一个 `VideoPlayer` 类,它包含了一个 `DisplayThread` 和一个 `SaveThread` 线程。`DisplayThread` 用于采集摄像头视频,并将每一帧图像通过信号 `imageReady` 发送给主线程,主线程再将图像显示出来。`SaveThread` 用于采集摄像头视频,并将每一帧图像保存到硬盘上,每保存一帧图像就通过信号 `saveDone` 发送给主线程,主线程再进行相应的处理。
在 `main` 函数中,我们创建了一个 `VideoPlayer` 对象,并连接了两个信号 `imageReady` 和 `saveDone`。当 `DisplayThread` 发送 `imageReady` 信号时,我们就在主线程中显示图像;当 `SaveThread` 发送 `saveDone` 信号时,我们就在主线程中进行相应的处理,比如更新 UI 界面等。
阅读全文