Files
eUi/src/Core/back/imgSaveThreadManager.h
T

253 lines
8.0 KiB
C++
Raw Normal View History

#include <qthread.h>
#include <opencv.hpp>
#include <qqueue.h>
#include <qdatetime.h>
#include <backStruct.h>
2025-07-16 16:43:20 +08:00
#define saveImgEnable 1
enum imgSaveThreadType
{
oriImg,
resImg,
segImg,
clsImg,
tiffOriImg
};
class imgSaveThread : public QThread
{
public:
enum type{
normal,
priority
};
QMutex mutex;
std::vector<int> compressionParams{ cv::IMWRITE_PNG_COMPRESSION ,9};
QQueue<std::pair<std::string, cv::Mat>>priorityQueue;
QQueue<std::pair<std::string, cv::Mat>>imgQueue;
void run()
{
2025-07-11 02:02:09 +08:00
while (true)
{
2025-07-11 02:02:09 +08:00
QQueue<std::pair<std::string, cv::Mat>> localQueue;
// 优先处理 priorityQueue
{
QMutexLocker locker(&mutex);
if (!priorityQueue.isEmpty()) {
localQueue.swap(priorityQueue);
}
else if (!imgQueue.isEmpty()) {
localQueue.swap(imgQueue);
}
}
2025-07-11 02:02:09 +08:00
// 没有任务就跳出
if (localQueue.isEmpty()) {
break;
}
// 批量保存
while (!localQueue.isEmpty()) {
auto data = std::move(localQueue.dequeue());
qDebug() << "saving img " << QString::fromStdString(data.first);
2025-07-16 16:43:20 +08:00
#if saveImgEnable
2025-07-11 02:02:09 +08:00
cv::imwrite(data.first, data.second);
2025-07-16 16:43:20 +08:00
#endif
2025-07-11 02:02:09 +08:00
// 不需要手动 release(), cv::Mat 会自动析构
}
}
}
2025-07-11 02:02:09 +08:00
void addData(std::string str, cv::Mat& mat,type type_ = normal)
{
try
{
if (mat.data == nullptr || &mat == nullptr)
{
qDebug() << "在存图线程中发现无效图像";
return;
}
}
catch(...)
{
qDebug() << "在存图线程中发现无效图像";
return;
}
mutex.lock();
cv::Mat img;
mat.copyTo(img);
switch (type_) {
case normal:
imgQueue.append(std::make_pair(str, img));
break;
case priority:
priorityQueue.append(std::make_pair(str, img));
break;
}
qDebug() << "img enqueue" << QString::fromStdString(str)<<"current size"<< priorityQueue.size()<<","<< imgQueue.size();
mutex.unlock();
this->start();
}
int queueSize()
{
mutex.lock();
int size = imgQueue.size();
mutex.unlock();
return size;
}
};
class imgSaveThreadManager
{
public:
2025-06-13 01:55:47 +08:00
imgSaveThreadManager(std::string pathIn) {
2025-07-16 16:43:20 +08:00
path = QString::fromStdString(pathIn);
2025-06-13 01:55:47 +08:00
}
~imgSaveThreadManager() {};
2025-07-16 16:43:20 +08:00
void setPath(QString pathIn){
2025-06-11 10:00:09 +08:00
path = pathIn;
}
imgSaveThread saveThread;
2025-07-16 16:43:20 +08:00
QString genDirName(std::shared_ptr <detData> data, imgSaveThreadType type) {
//sqlTableDatas sqlRes = sql->selectSingleData("saveHour", data->SNcode);//查找之前的数据
//获取关键数据
2025-07-16 16:43:20 +08:00
QString imgSaveDirStr = path;//所有图片的路径 sample "D://CCD"
QString imgTypeDirStr;//二级目录,图片类型决定 sample "Result"
QString dateDirStr;//三级目录,日期决定 sample"2024-6-8"
QString hourDirStr;//四级目录,小时段决定 sample "14H"
QString okNgStr;//五级目录,OK/NG决定 sample "OK"
QString detailNameStr;//六级目录 主要是SN,如没有sn则可能是相机名称
#pragma region 赋值
//imgTypeDirStr
switch (type)
{
case oriImg:
2025-07-16 16:43:20 +08:00
imgTypeDirStr = "原图";
break;
case resImg:
2025-07-16 16:43:20 +08:00
imgTypeDirStr = "结果图";
break;
default:
imgTypeDirStr = "error";
}
{
QDateTime currentDateTime = QDateTime::currentDateTime();
2025-07-16 16:43:20 +08:00
dateDirStr = currentDateTime.toString("yyyy-MM-dd");
hourDirStr = QString::number(currentDateTime.time().hour()) + "H//";
}
2025-07-16 16:43:20 +08:00
if(data->aiDetOK == false && data->halconOK == false)
2025-07-11 02:02:09 +08:00
okNgStr = "NG";
2025-07-16 16:43:20 +08:00
else if (data->aiDetOK == false)
okNgStr = "aiNG";
else if (data->halconOK == false)
okNgStr = "halconNG";
else
okNgStr = "OK";
//detailNameStr
2025-07-25 00:29:52 +08:00
if (data->SNcode.length() != 0 && data->SNcode.length() < 50)
2025-07-16 16:43:20 +08:00
detailNameStr = QString::fromStdString(data->SNcode);
else
2025-07-16 16:43:20 +08:00
detailNameStr = QString::fromStdString(data->cameraKeyName);
#pragma endregion
2025-07-16 16:43:20 +08:00
return QString(imgSaveDirStr + "/" +
imgTypeDirStr + "/" +
dateDirStr + "/" +
hourDirStr + "/" +
2025-07-11 02:02:09 +08:00
okNgStr + "/" +
detailNameStr + "/");
}
2025-06-15 03:06:01 +08:00
std::vector<std::string> genFileNames(std::shared_ptr <detData> data, imgSaveThreadType type, std::string format = "")
{
std::vector<std::string> resultFileNames;
std::string fileName;
2025-07-25 00:29:52 +08:00
if (data->SNcode.length() != 0 && data->SNcode.length() < 50)
fileName += data->SNcode;
else
fileName += data->cameraKeyName;
2025-06-15 03:06:01 +08:00
for (auto str : data->imgSaveNameParameter)
fileName += str + "_";
switch (type)
{
case oriImg:
for (int i = 0; i < data->oriImgs.size(); i++)
{
2025-06-15 03:06:01 +08:00
if (i < data->oriFormat.size() )
resultFileNames.push_back(fileName + getCurrentDateTime() + "_Count" + std::to_string(i) + "." + data->oriFormat[i]);
else
resultFileNames.push_back(fileName + getCurrentDateTime() + "_Count" + std::to_string(i) + ".bmp");
}
break;
case resImg:
for (int i = 0; i < data->resultImgs.size(); i++)
resultFileNames.push_back(fileName + getCurrentDateTime() + "_Count" + std::to_string(i) + ".jpg");
break;
case segImg:
for (int i = 0; i < data->segOriginImgs.size(); i++)
resultFileNames.push_back(fileName + "SEG_" + getCurrentDateTime() + "_" + std::to_string(i) + ".png");
break;
case clsImg:
for (int i = 0; i < data->clsOriginImgs.size(); i++)
resultFileNames.push_back(fileName + "CLS_RES" + getCurrentDateTime() + "_" + data->clsOriginImgs[i].first + "_Count" + std::to_string(i) + ".bmp");
break;
}
return resultFileNames;
}
void saveOri(std::shared_ptr <detData> data)
{
2025-07-16 16:43:20 +08:00
QString fileSavePath = genDirName(data, oriImg);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
2025-06-15 03:06:01 +08:00
std::vector<std::string>fileNames = genFileNames(data, oriImg);
2025-07-16 16:43:20 +08:00
for (int index = 0; index < fileNames.size(); index++)
2025-07-16 16:43:20 +08:00
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + fileNames[index], data->oriImgs[index]);
int queueSize = saveThread.queueSize();
if (queueSize > 10)
qDebug() << "queueSize " << queueSize;
}
void saveRes(std::shared_ptr <detData> data)
{
2025-07-16 16:43:20 +08:00
QString fileSavePath = genDirName(data, resImg);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
//结果图保存
2025-06-15 03:06:01 +08:00
std::vector<std::string>resFileNames = genFileNames(data, resImg);
for (int index = 0; index < resFileNames.size(); index++)
2025-07-16 16:43:20 +08:00
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + resFileNames[index], data->resultImgs[index], imgSaveThread::priority);
//seg
2025-06-15 03:06:01 +08:00
std::vector<std::string>segFileNames = genFileNames(data, segImg);
for (int index = 0; index < segFileNames.size(); index++)
2025-07-16 16:43:20 +08:00
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + segFileNames[index], data->segOriginImgs[index]);
//cls
2025-06-15 03:06:01 +08:00
std::vector<std::string>clsFileNames = genFileNames(data, clsImg);
for (int index = 0; index < clsFileNames.size(); index++)
2025-07-16 16:43:20 +08:00
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + clsFileNames[index], data->clsOriginImgs[index].second);
//额外储存NG文件夹
2025-07-11 02:02:09 +08:00
//std::string additionalSaveNgImgPath = genDirName(data, additionalSaveNgImg);
//std::vector<std::string>additionalSaveNgImgNames = genFileNames(data, additionalSaveNgImg);
//if (additionalSaveNgImgNames.size() > 0)
// createDirectoryIfNotExists(additionalSaveNgImgPath);//不存在此文件夹则创建
//int additionalSaveNgImgNamesIndex = 0;
//for (int index = 0; index < data->segOriginImgs.size()&& additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
//{
// saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->segOriginImgs[index]);
// additionalSaveNgImgNamesIndex++;
//}
//for (int index = 0; index < data->oriImgs.size() && additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
//{
// saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->oriImgs[index]);
// additionalSaveNgImgNamesIndex++;
//}
//for (int index = 0; index < data->resultImgs.size() && additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
//{
// saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->resultImgs[index]);
// additionalSaveNgImgNamesIndex++;
//}
}
private:
2025-07-16 16:43:20 +08:00
QString path = "";
};
#pragma once