#include #include #include #include #include #include enum imgSaveThreadType { oriImg, resImg, segImg, clsImg, additionalSaveNgImg, tiffOriImg }; class imgSaveThread : public QThread { public: enum type{ normal, priority }; QMutex mutex; std::vector compressionParams{ cv::IMWRITE_PNG_COMPRESSION ,9}; QQueue>priorityQueue; QQueue>imgQueue; void run() { while (imgQueue.size() > 0 || priorityQueue.size() > 0) { if (priorityQueue.size() > 0) { mutex.lock(); std::pair data = priorityQueue.dequeue(); mutex.unlock(); qDebug() << "saving priority img " << QString::fromStdString(data.first); cv::imwrite(data.first, data.second); data.second.release(); } else if (imgQueue.size() > 0) { mutex.lock(); std::pair data = imgQueue.dequeue(); mutex.unlock(); qDebug() << "saving img " << QString::fromStdString(data.first); if (data.first.find(".png") != std::string::npos){ cv::resize(data.second, data.second, cv::Size(), 0.25, 0.25); cv::imwrite(data.first, data.second, compressionParams); } else { cv::imwrite(data.first, data.second); } data.second.release(); } } } 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: imgSaveThreadManager(std::string pathIn) { path = pathIn; } ~imgSaveThreadManager() {}; void setPath(std::string pathIn){ path = pathIn; } imgSaveThread saveThread; std::string genDirName(std::shared_ptr data, imgSaveThreadType type) { //sqlTableDatas sqlRes = sql->selectSingleData("saveHour", data->SNcode);//查找之前的数据 //获取关键数据 std::string imgSaveDirStr = path;//所有图片的路径 sample "D://CCD" std::string imgTypeDirStr;//二级目录,图片类型决定 sample "Result" std::string dateDirStr;//三级目录,日期决定 sample"2024-6-8" std::string hourDirStr;//四级目录,小时段决定 sample "14H" std::string detailNameStr;//五级目录 主要是SN,如没有sn则可能是相机名称 #pragma region 赋值 //imgTypeDirStr switch (type) { case oriImg: imgTypeDirStr = "Ori"; break; case resImg: imgTypeDirStr = "Result"; break; case additionalSaveNgImg: imgTypeDirStr = "NGIMG"; break; default: imgTypeDirStr = "error"; } { QDateTime currentDateTime = QDateTime::currentDateTime(); dateDirStr = currentDateTime.toString("yyyy-MM-dd").toStdString(); hourDirStr = std::to_string(currentDateTime.time().hour()) + "H//"; } //detailNameStr if ((data->SNcode).length() != 0) detailNameStr = data->SNcode; else detailNameStr = data->cameraKeyName; #pragma endregion return std::string(imgSaveDirStr + "/" + imgTypeDirStr + "/" + dateDirStr + "/" + hourDirStr + "/" + detailNameStr + "/"); } std::vector genFileNames(std::shared_ptr data, imgSaveThreadType type, std::string format = "") { std::vector resultFileNames; std::string fileName; for (auto str : data->imgSaveNameParameter) fileName += str + "_"; switch (type) { case oriImg: for (int i = 0; i < data->oriImgs.size(); i++) { 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; case additionalSaveNgImg: if (data->aiDetOK == false || data->halconOK == false) { for (int i = 0; i < data->segOriginImgs.size(); i++) resultFileNames.push_back(fileName + "NGIMG_segOriginImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".png"); for (int i = 0; i < data->oriImgs.size(); i++) { if(data->oriImgs[i].depth() == 2) resultFileNames.push_back(fileName + "NGIMG_oriImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".tiff"); else resultFileNames.push_back(fileName + "NGIMG_oriImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".png"); } for (int i = 0; i < data->resultImgs.size(); i++) resultFileNames.push_back(fileName + "NGIMG_resultImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".jpg"); } break; } return resultFileNames; } void saveOri(std::shared_ptr data) { std::string fileSavePath = genDirName(data, oriImg);//获取文件夹名 createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建 std::vectorfileNames = genFileNames(data, oriImg); for (int index = 0; index < fileNames.size(); index++) saveThread.addData(fileSavePath+fileNames[index], data->oriImgs[index]); int queueSize = saveThread.queueSize(); if (queueSize > 10) qDebug() << "queueSize " << queueSize; } void saveRes(std::shared_ptr data) { std::string fileSavePath = genDirName(data, resImg);//获取文件夹名 createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建 //结果图保存 std::vectorresFileNames = genFileNames(data, resImg); for (int index = 0; index < resFileNames.size(); index++) { saveThread.addData(fileSavePath + resFileNames[index], data->resultImgs[index], imgSaveThread::priority); } //seg std::string segAndClsPath = fileSavePath + "detImgs//" + getCurrentDateTime() + "//"; std::vectorsegFileNames = genFileNames(data, segImg); if (segFileNames.size() > 0) createDirectoryIfNotExists(segAndClsPath);//不存在此文件夹则创建 for (int index = 0; index < segFileNames.size(); index++) saveThread.addData(segAndClsPath + segFileNames[index], data->segOriginImgs[index]); //cls std::vectorclsFileNames = genFileNames(data, clsImg); for (int index = 0; index < clsFileNames.size(); index++) saveThread.addData(segAndClsPath + clsFileNames[index], data->clsOriginImgs[index].second); //额外储存NG文件夹 std::string additionalSaveNgImgPath = genDirName(data, additionalSaveNgImg); std::vectoradditionalSaveNgImgNames = 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: std::string path = ""; }; #pragma once