QT 一个简明的多线程存图队列

目录

前言:

1. 源码

2. 结构体设计

3. 多线程设计


前言:

        本文基于QT框架提供一个简单明了的“多线程存图队列”的模板,我们也可以基于结构体提供更多信息,增加更多对图像的处理操作。咱们还是先上源码再讲设计,建议结合设计再看代码哦。

1. 源码

        SaveImageThread.h

// SaveImageThread.h
#pragma once
#include "opencv2/opencv.hpp"
#include <QThread>
#include <QMutex>
#include <QQueue>
#include <QImage>

typedef struct _ImageInfo
{
	cv::Mat image;// QImage image;
	// double scale;
	// QString fileName;
	// ...
}ImageInfo;

class SaveImageThread :public QThread
{
public:
	SaveImageThread(QObject* parent = nullptr);
	~SaveImageThread();

public:
	void enQueue(const ImageInfo &info);
	void run();

	//=====================启动子线程前的操作=================//
	
	// 设置存图路径
	void setPath(QString path);
	// 清空队列
	void reset();

protected:
	QMutex m_Mutex;
	QQueue<ImageInfo> m_ImageInfoQueue;
	QString m_sFilePath;
	uint64_t m_nSaveNum;
};

        SaveImageThread.cpp

// SaveImageThread.cpp
#include "SaveImageThread.h"
#include <QApplication>
#include <QDebug>
#include <QFile>

using cv::Mat;

SaveImageThread::SaveImageThread(QObject* parent) : QThread(parent)
{

}

SaveImageThread::~SaveImageThread()
{
	m_ImageInfoQueue.clear();
	quit();
	wait();
	qDebug() << "SaveImageThread:: Thread Over";
	deleteLater();
}

void SaveImageThread::enQueue(const ImageInfo &info)
{
	// 只有一个主线程执行入队操作,若多线程操作入队,需加锁
	//m_Mutex.lock();
	m_ImageInfoQueue.enqueue(info);
	//m_Mutex.unlock();

	if (!isRunning())
	{
		start();// 子线程执行run()
	}
}

void SaveImageThread::run()
{
	cv::Mat mat;
	ImageInfo imageInfo;
	bool quit = m_ImageInfoQueue.empty();

	while (!quit)
	{
		// 出队操作
		imageInfo = m_ImageInfoQueue.dequeue();
		mat = imageInfo.image;

		// 图像处理、存图
		if(m_sFilePath != "")
			cv::imwrite((m_sFilePath + QString::number(m_nSaveNum++) + ".bmp").toLocal8Bit().data(), mat);

		quit = m_ImageInfoQueue.empty();
		// 这里你注意 ❛‿˂̵✧
		// 如果quit放在dequeue后面,在开头更新判断为空,而主线程在入队后SaveImage线程在正在处理图像,
		// 那么就会丢失最后一张图,所以quit得放最后更新。
	}
}

void SaveImageThread::setPath(QString path)
{
	if (QFile::exists(path))
		m_sFilePath = path + QString("/image");
	else
		m_sFilePath = "";
}

void SaveImageThread::reset()
{
	m_nSaveNum = 0;
	m_ImageInfoQueue.clear();
}


2. 结构体设计

        入队的数据为包含图像数据的结构体ImageInfo,要处理更多的图像操作,当然要提供更多的数据,例如缩放比例,文件名......

typedef struct _ImageInfo
{
	cv::Mat image;// QImage image;
	// double scale;
	// QString fileName;
	// ...
}ImageInfo;

        处理图像当然要用cv::Mat了,如果你懒的配置opencv,也可以使用QImage代替,并使用QImage的存图函数。

3. 多线程设计

        入队操作enQueue()是在主线程进行的,而存图操作run()则是在SaveImage线程进行。要注意锁,不必要的加锁会成为线程的枷锁。实际上,这里主线程入队操作是很快的,因为并没有拷贝图像,而子线程存图是极为耗时的。

如果对QT多线程QThread操作有疑问,也可以看博主另一篇,包大全套。

Qt完成Socket通讯_qt socket-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值