From f50bcb30d1d94768e44de873c6ed85c33dd833e1 Mon Sep 17 00:00:00 2001 From: RCi <15089880081@163.com> Date: Wed, 28 Jan 2026 10:49:49 +0800 Subject: [PATCH] =?UTF-8?q?V20260127-2.3.11=20=E5=AD=98=E5=9B=BE=E6=97=B6?= =?UTF-8?q?=E4=BC=9A=E7=BC=93=E5=AD=98=E5=88=9B=E5=BB=BA=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9=E7=9A=84=E8=B7=AF=E5=BE=84=E4=BB=A5=E9=98=B2=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E5=88=9B=E5=BB=BA=E3=80=82=20=E6=82=AC=E5=81=9C?= =?UTF-8?q?=E5=9C=A8=E5=8F=B3=E4=BE=A7=E7=BC=BA=E9=99=B7=E6=9F=B1=E7=8A=B6?= =?UTF-8?q?=E5=9B=BE=E6=97=B6=E4=BC=9A=E5=87=BA=E7=8E=B0=E5=85=B7=E4=BD=93?= =?UTF-8?q?=E7=BC=BA=E9=99=B7=E5=90=8D=EF=BC=8C=20=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BB=A5=E5=8F=8A=E4=BF=9D=E6=8A=A4=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/global.h | 4 +- include/opencvPaintAlgo.hpp | 47 +++--- include/sxGlobal.h | 2 +- include/yhGlobal.h | 3 +- include/yhGlobal_601.h | 3 +- src/core/backendInterface.h | 8 +- src/core/service/imgSaveThreadManager.h | 145 ++++++++++++++---- src/core/service/triggerManager.cpp | 58 +++---- .../GUI/uiModule/uiModule_histogramWidget.h | 23 ++- src/launcher/logger/qtLogRediretor.cpp | 5 +- src/launcher/main.cpp | 31 +++- .../581-BaoMo-Cam1213/581-BaoMo-Cam1213.cpp | 2 +- .../581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp | 4 +- src/mission/581-Dgh-CB-1/581-Dgh-CB-1.h | 2 +- .../581_Ruanlianjie_dianjiao_tiejiao.cpp | 8 +- .../581_Ruanlianjie_hanqian_hanhou.cpp | 102 ++++++++---- .../601/601_RLJ_DingGai/601_RLJ_DingGai.cpp | 97 ++++++------ .../601/601_RLJ_DingGai/601_RLJ_DingGai.h | 2 +- src/mission/601/601_RLJ_HH/601_RLJ_HH.cpp | 4 +- 19 files changed, 366 insertions(+), 184 deletions(-) diff --git a/include/global.h b/include/global.h index 2e122b3..35d62d3 100644 --- a/include/global.h +++ b/include/global.h @@ -11,7 +11,7 @@ #include #pragma execution_character_set("utf-8") -const std::string softwareVersion = "20260122-2.3.10"; +const std::string softwareVersion = "20260127-2.3.11"; const std::string euiJsonVersion = "1.0.6"; #define GigaByte 1073741824 #define globalDatabasePth "./sqlDatabase/eui_db.db" //全局数据库路径 @@ -22,7 +22,7 @@ const std::string euiJsonVersion = "1.0.6"; #define imgSaveTreadMaxCount 4 //最大存图线程数 #define jsonRpcEnable false //是否启用JSON RPC服务器 #define minimumWindowSize 1280, 720//最小窗口大小 -#define histogramLabelTiltAngle 30 //柱状图标签倾斜角度 +#define histogramLabelTiltFontSize 8 //柱状图标签字体大小 #define windowMoveFreshRate 60//窗口移动每秒的刷新率 #define sColor_Blue "51, 56, 69" #define sColor_BlueWithWhite "64, 68, 81" diff --git a/include/opencvPaintAlgo.hpp b/include/opencvPaintAlgo.hpp index 02cffb7..24af312 100644 --- a/include/opencvPaintAlgo.hpp +++ b/include/opencvPaintAlgo.hpp @@ -107,12 +107,16 @@ public: virtual void putText(cv::Mat& image, const std::string& text, cv::Point org, cv::Scalar color = cv::Scalar(255, 0, 0)) = 0; }; -class TextRendererZH : public TextRendererBase { +class TextRendererZH{ public: + TextRendererZH(const TextRendererZH&) = delete; + TextRendererZH& operator=(const TextRendererZH&) = delete; + + TextRendererZH(TextRendererZH&&) noexcept = default; + TextRendererZH& operator=(TextRendererZH&&) noexcept = default; TextRendererZH(int width, int height, int fontSize = 20, const std::wstring& fontName = L"微软雅黑") : width_(width), height_(height), fontSize_(fontSize), fontName_(fontName) { - QMutexLocker locker(&mutex_); screenDC_ = GetDC(nullptr); if (!screenDC_) { throw std::runtime_error("Failed to get screen DC"); @@ -121,12 +125,11 @@ public: } ~TextRendererZH() { - QMutexLocker locker(&mutex_); releaseResources(); if (screenDC_) ReleaseDC(nullptr, screenDC_); } - void putText(cv::Mat& image, const std::string& text, cv::Point org, cv::Scalar color = cv::Scalar(255, 0, 0)) override { + void putText(cv::Mat& image, const std::string& text, cv::Point org, cv::Scalar color = cv::Scalar(255, 0, 0)) { QMutexLocker locker(&mutex_); if (image.channels() != 3) @@ -182,45 +185,45 @@ public: struct contourPaintJob { std::vector contour; cv::Scalar color; - int thikness; + int thickness; }; - void appendPaintJob(std::vector contour, cv::Scalar color, int thikness) { + void appendPaintJob(std::vector contour, cv::Scalar color, int thickness) { QMutexLocker locker(&mutex_); - contourPaintJobs.push_back(contourPaintJob{ contour,color,thikness }); + contourPaintJobs.push_back(contourPaintJob{ contour,color,thickness }); } struct linePaintJob { cv::Point p1; cv::Point p2; cv::Scalar color; - int thikness; + int thickness; }; - void appendPaintJob(cv::Point p1, cv::Point p2, cv::Scalar color, int thikness) { + void appendPaintJob(cv::Point p1, cv::Point p2, cv::Scalar color, int thickness) { QMutexLocker locker(&mutex_); - linePaintJobs.push_back(linePaintJob{ p1,p2,color,thikness }); + linePaintJobs.push_back(linePaintJob{ p1,p2,color,thickness }); } struct circleAndCorssPaintJob { cv::Point center; double radius; cv::Scalar color; - int thikness; + int thickness; int type; }; //type0 圆 type1 十字 - void appendPaintJob(cv::Point center, double radius,cv::Scalar color, int thikness,int type) { + void appendPaintJob(cv::Point center, double radius,cv::Scalar color, int thickness,int type) { QMutexLocker locker(&mutex_); - circleAndCorssPaintJobs.push_back(circleAndCorssPaintJob{ center,radius,color,thikness,type }); + circleAndCorssPaintJobs.push_back(circleAndCorssPaintJob{ center,radius,color,thickness,type }); } struct rectPaintJob { cv::Rect rect; cv::Scalar color; - int thikness; + int thickness; }; - void appendPaintJob(cv::Rect rect, cv::Scalar color,int thikness) { + void appendPaintJob(cv::Rect rect, cv::Scalar color,int thickness) { QMutexLocker locker(&mutex_); - rectPaintJobs.push_back(rectPaintJob{ rect,color,thikness }); + rectPaintJobs.push_back(rectPaintJob{ rect,color,thickness }); } struct textPaintJob { @@ -233,7 +236,7 @@ public: textPaintJobs.push_back(textPaintJob{ text,p,color }); } - void excusePaintJobs(cv::Mat& image,double resizeRate = 1.0) { + void executePaintJobs(cv::Mat& image,double resizeRate = 1.0) { QMutexLocker locker(&mutex_); if (textPaintJobs.empty() && pointPaintJobs.empty() && circleAndCorssPaintJobs.empty() && rectPaintJobs.empty() && contourPaintJobs.empty() && linePaintJobs.empty()) return; @@ -253,24 +256,24 @@ public: // 绘制圆或十字 for (const auto& job : circleAndCorssPaintJobs) { if(job.type == 0) - cv::circle(image, job.center, job.radius, job.color, job.thikness); + cv::circle(image, job.center, job.radius, job.color, job.thickness); else - cv::drawMarker(image, job.center, job.color, cv::MARKER_CROSS, job.radius, job.thikness); + cv::drawMarker(image, job.center, job.color, cv::MARKER_CROSS, job.radius, job.thickness); } // 绘制点集 for (const auto& job : contourPaintJobs) { - cv::drawContours(image, { job.contour }, 0, job.color, job.thikness); + cv::drawContours(image, { job.contour }, 0, job.color, job.thickness); } // 绘制线段 for (const auto& job : linePaintJobs) { - cv::line(image, job.p1, job.p2, job.color, job.thikness); + cv::line(image, job.p1, job.p2, job.color, job.thickness); } // 绘制矩形 for (const auto& job : rectPaintJobs) { - cv::rectangle(image, job.rect, job.color, job.thikness); + cv::rectangle(image, job.rect, job.color, job.thickness); } // 绘制文本(需要GDI处理) diff --git a/include/sxGlobal.h b/include/sxGlobal.h index 7362462..d0b491d 100644 --- a/include/sxGlobal.h +++ b/include/sxGlobal.h @@ -150,10 +150,10 @@ public: camera->clearCache();//清除缓存 std::shared_ptr data = _serviceManager->_detDataManager->createDetData( QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包 + data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); data->saveObjectName = saveObjectName; camera->captureImage(data);//拍照 generalDet->asyncProcess(data, address[batteryOffset], ("D" + address[batteryOffset].completeAddr + "_1"));//处理算法 并在取到图片后发送完成信号 - data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); } private: QString saveObjectName = ""; diff --git a/include/yhGlobal.h b/include/yhGlobal.h index 6a929d1..c394d24 100644 --- a/include/yhGlobal.h +++ b/include/yhGlobal.h @@ -290,11 +290,10 @@ public: std::shared_ptr data = _serviceManager->_detDataManager->createDetData( QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包 data->saveObjectName = saveObjectName; - + data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); camera->captureImage(data);//拍照 generalDet->asyncProcess(data, address[batteryOffset]);//处理算法 - data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); _serviceManager->_triggerManager->writeShort("D" + address[batteryOffset].completeAddr + "_1");//完成信号 根据偏移发送 } private: diff --git a/include/yhGlobal_601.h b/include/yhGlobal_601.h index e157072..feebe7b 100644 --- a/include/yhGlobal_601.h +++ b/include/yhGlobal_601.h @@ -290,11 +290,10 @@ public: std::shared_ptr data = _serviceManager->_detDataManager->createDetData( QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包 data->saveObjectName = saveObjectName; - + data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); camera->captureImage(data);//拍照 generalDet->asyncProcess(data, address[batteryOffset]);//处理算法 - data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); _serviceManager->_triggerManager->writeShort("D" + address[batteryOffset].completeAddr + "_1");//完成信号 根据偏移发送 } private: diff --git a/src/core/backendInterface.h b/src/core/backendInterface.h index 238806a..af462ee 100644 --- a/src/core/backendInterface.h +++ b/src/core/backendInterface.h @@ -12,10 +12,10 @@ #include class Backend : public IBackend { public: - DataRecorder* _dataRecorder = nullptr; - missionResultHandle* _missionResultHandle = nullptr; - ServiceManager _serviceManager; - paramSyncManager* _paramSyncManager = nullptr;//供客户在UI修改/查看 + DataRecorder* _dataRecorder = nullptr;// 数据记录器 + missionResultHandle* _missionResultHandle = nullptr;// 任务结果处理器 + ServiceManager _serviceManager;//服务类接口 + paramSyncManager* _paramSyncManager = nullptr;//检测参数同步类//供客户在UI修改/查看 CLIManager* _cliManager; // 命令行接口管理器 #if jsonRpcEnable rpc::JsonRpcServer _rpcServer; diff --git a/src/core/service/imgSaveThreadManager.h b/src/core/service/imgSaveThreadManager.h index 17d4d6c..63774f3 100644 --- a/src/core/service/imgSaveThreadManager.h +++ b/src/core/service/imgSaveThreadManager.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,7 @@ public: for (int i = 0; i < data->resultSaveText.size(); i++) { processResult.append("_" + data->resultSaveText[i]); } - result.replace("{processResult}", processResult); + result.replace("{processResult}", QString::fromStdString(repairWindowsFileName(processResult.toStdString()))); // 替换SN/设备信息占位符 QString snCode = (data->SNcode.size() > 0 && data->SNcode.size() < 50) @@ -167,6 +168,7 @@ public: return result; } + private: QString defaultPath = "{imgSaveRootDir}/{yyyy-MM-dd}/{saveObjectName}{imageType}/{HH}H/{processResult}/{SN}/"; @@ -174,8 +176,8 @@ private: }; struct saveJob { saveJob(std::string jobNameIn) :jobName(jobNameIn) {} - std::string jobName; - QQueue> imgQueue; + std::string jobName;// 任务名称 + QQueue> imgQueue;// 图片队列 }; // 数据库存储线程类 @@ -283,7 +285,6 @@ private: QMutex queueMutex; std::atomic pendingCount = 0; }; - class imgSaveThread : public QThread { public: @@ -314,20 +315,18 @@ public: if (job == nullptr) { break; } - +#if saveImgEnable imgRemainCount -= job->imgQueue.size(); qDebug() << "saveJob start" << QString::fromStdString(job->jobName) << "remain" << imgRemainCount; localQueue.swap(job->imgQueue); // 批量保存 while (!localQueue.isEmpty()) { auto data = std::move(localQueue.dequeue()); -#if saveImgEnable cv::imwrite(data.first, data.second); QMutexLocker locker(&threadBufferSizeMutex); threadBufferSize -= data.second.total() * data.second.elemSize(); -#endif } - +#endif qDebug() << "saveJob end " << QString::fromStdString(job->jobName); } } @@ -381,6 +380,90 @@ private: int threadIndex = 0, threadBufferSize = 0, imgRemainCount = 0; QMutex queueMutex, threadBufferSizeMutex; }; + +//用于缓存需要创建的文件夹路径,防止重复创建 +class LRUCache { +public: + explicit LRUCache(int capacity) : maxCapacity(capacity) { + if (capacity <= 0) { + throw std::invalid_argument("LRU缓存容量必须大于0"); + } + } + + // 检查字符串是否在缓存中 + bool contains(const QString& value) { + QMutexLocker locker(&mutex); + int index = cacheList.indexOf(value); + if (index != -1) { + // 移动到列表头部(最近使用) + cacheList.move(index, 0); + return true; + } + return false; + } + + // 添加字符串到缓存 + void put(const QString& value) { + QMutexLocker locker(&mutex); + if (value.isEmpty()) { + return; // 不缓存空字符串 + } + + int index = cacheList.indexOf(value); + if (index != -1) { + // 已存在,移动到头部 + cacheList.move(index, 0); + return; + } + + // 不存在,需要添加 + if (cacheList.size() >= maxCapacity) { + // 缓存已满,移除最久未使用的元素(尾部) + cacheList.removeLast(); + } + + // 添加新元素到头部 + cacheList.prepend(value); + } + + // 移除指定元素 + bool remove(const QString& value) { + QMutexLocker locker(&mutex); + int index = cacheList.indexOf(value); + if (index != -1) { + cacheList.removeAt(index); + return true; + } + return false; + } + + // 获取缓存大小 + int size() const { + return cacheList.size(); + } + + // 获取最大容量 + int capacity() const { + return maxCapacity; + } + + // 检查是否为空 + bool isEmpty() const { + return cacheList.isEmpty(); + } + + // 清空缓存 + void clear() { + QMutexLocker locker(&mutex); + cacheList.clear(); + } + + +private: + QMutex mutex; + int maxCapacity; + QStringList cacheList; // QStringList,头部是最近使用的,尾部是最久未使用的 +}; class imgSaveThreadManager { public: imgSaveThreadManager(std::string pathIn, paramSyncManager* paramSyncManagerIn) @@ -391,7 +474,6 @@ public: saveRes = _paramSyncManager->get("通用设置", "存储结果图", true).toBool(); saveSeg = _paramSyncManager->get("通用设置", "存储Seg图", true).toBool(); saveCls = _paramSyncManager->get("通用设置", "存储Cls图", true).toBool(); - //初始化存图线程 QMutexLocker locker(&saveThreadMutexVec); saveThreads.emplace_back(std::make_unique(saveThreads.size())); @@ -446,12 +528,32 @@ public: } } try { - std::shared_ptr oriJob(new saveJob("[ORI_JOB]" + data->SNcode)); std::shared_ptr resJob(new saveJob("[RES_JOB]" + data->SNcode)); + std::shared_ptr oriJob(new saveJob("[ORI_JOB]" + data->SNcode)); + + QString resSavePath = _ImageSavePathFormatter.genPath(data, "结果图", data->customPath, data->customImageSaveTemplateParams);//获取文件夹名 + if (saveRes == true) { + if (createPathCache.contains(resSavePath) == false) {//不存在此文件夹则创建 + createDirectoryIfNotExists(resSavePath); + allDirectoryPaths.push_back(resSavePath);//记录文件夹路径 + createPathCache.put(resSavePath);//加入缓存 + } + + //结果图保存 + if (data->getResultImgSize() != 0) { + std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, ImageSavePathFormatter::resImg, data->getResultImgVec());//按规则为文件创建命名 + packageData(resJob->imgQueue, resSavePath.toLocal8Bit().toStdString(), fileNames, data->getResultImgVec());//打包数据 + } + } + QString oriSavePath = _ImageSavePathFormatter.genPath(data, "原图", data->customPath, data->customImageSaveTemplateParams);//获取文件夹名 if (saveOri == true || saveSeg == true || saveCls == true) { - createDirectoryIfNotExists(oriSavePath);//不存在此文件夹则创建 - allDirectoryPaths.push_back(oriSavePath);//记录文件夹路径 + + if (createPathCache.contains(oriSavePath) == false) {//不存在此文件夹则创建 + createDirectoryIfNotExists(oriSavePath); + allDirectoryPaths.push_back(oriSavePath);//记录文件夹路径 + createPathCache.put(oriSavePath);//加入缓存 + } if (data->getOriImgSize() != 0 && saveOri == true) { std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, ImageSavePathFormatter::oriImg, data->getOriImgVec());//按规则为文件创建命名 packageData(oriJob->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->getOriImgVec());//打包数据 @@ -468,22 +570,10 @@ public: } } - - QString resSavePath = _ImageSavePathFormatter.genPath(data, "结果图", data->customPath, data->customImageSaveTemplateParams);//获取文件夹名 - if (saveRes == true) { - createDirectoryIfNotExists(resSavePath);//不存在此文件夹则创建 - allDirectoryPaths.push_back(resSavePath);//记录文件夹路径 - //结果图保存 - if (data->getResultImgSize() != 0) { - std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, ImageSavePathFormatter::resImg, data->getResultImgVec());//按规则为文件创建命名 - packageData(resJob->imgQueue, resSavePath.toLocal8Bit().toStdString(), fileNames, data->getResultImgVec());//打包数据 - } - } - - if (oriJob->imgQueue.size() != 0) - getSaveThread()->addJob(oriJob); if (resJob->imgQueue.size() != 0) getSaveThread()->addJob(resJob, imgSaveThread::priority); + if (oriJob->imgQueue.size() != 0) + getSaveThread()->addJob(oriJob); #pragma region 将存储目录写入数据库中 #if savePathToDataBase @@ -522,11 +612,12 @@ public: return saveThreads.back().get(); } private: + LRUCache createPathCache{ 200 };//用于缓存已经创建过的文件夹路径,防止重复创建 std::unique_ptr dbThread; // 数据库存储线程 QMutex paramTimerMutex; // 保护参数计时器的互斥锁 int maxSaveThreadCount = imgSaveTreadMaxCount; QMutex saveThreadMutexVec; - std::vector> saveThreads; + std::vector> saveThreads;//存图线程池 bool saveOri = true, saveRes = true, saveSeg = true, saveCls = true; QElapsedTimer getParamTimer;//防止加锁次数过多导致卡顿 paramSyncManager* _paramSyncManager; diff --git a/src/core/service/triggerManager.cpp b/src/core/service/triggerManager.cpp index f5b3de3..79710da 100644 --- a/src/core/service/triggerManager.cpp +++ b/src/core/service/triggerManager.cpp @@ -103,11 +103,14 @@ void triggerManager::receiveCommand() { for (auto& _struct : readAllCmds) { QByteArray readByte = _struct.readAllCmd; - mutex.lock(); - if (!reciveFinsMsg(readByte)) - qCritical() << "[TCP] " << " finstcp_ptr readData error!"; - mutex.unlock(); + //接收数据 + { + QMutexLocker locker(&mutex); + if (!reciveFinsMsg(readByte)) + qCritical() << "[TCP] " << " finstcp readData error!"; + } tLocker[_struct.readAllCmd].reFreshLocker(readByte);//经过检查后再触发 + //解析数据 decodeCameraCMD(_struct,readByte); } @@ -147,10 +150,10 @@ void triggerManager::decodeCameraCMD(readAllStruct& _struct, QByteArray byte) else if (isConnected == false) { emit bridge->setPlcConnectionOk(); isConnected = true; - qDebug() << "掉线时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒"; - std::cout << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒" << std::endl; + qDebug() << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒"; + std::cout << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒" << std::endl; } - checkCallback(_struct,byte); + checkCallback(_struct, byte); checkUnionCallback(_struct, byte); checkPlcValueViewer(_struct, byte); } @@ -162,18 +165,17 @@ void triggerManager::checkCallback(readAllStruct _struct, QByteArray& byteArray) if (checkTrigger(callback.triggerAddress, callback.triggerValue, _struct, byteArray) == true) { qDebug() << "func:" << QString::fromStdString(callback.funcName) << "->已触发 " << callback.triggerValue; - std::async(std::launch::async, [callback, byteArray]() mutable { - try { - callback.func(callback.triggerAddress, callback.triggerValue, byteArray); // 执行回调函数 - } - catch (const std::exception& e) { - qCritical() << "Error in callback " << QString::fromStdString(callback.funcName) << ": " << QString::fromStdString(e.what()); - } - catch (...) { - qCritical() << "Error in callback : unexpected" << QString::fromStdString(callback.funcName); - } - }); + try { + callback.func(callback.triggerAddress, callback.triggerValue, byteArray); // 执行回调函数 + } + catch (const std::exception& e) { + qCritical() << "Error in callback " << QString::fromStdString(callback.funcName) << ": " << QString::fromStdString(e.what()); + } + catch (...) { + qCritical() << "Error in callback : unexpected" << QString::fromStdString(callback.funcName); + }; } + } } @@ -216,17 +218,15 @@ void triggerManager::checkUnionCallback(readAllStruct& _struct, QByteArray& byte } } qDebug() << "Union func:" << QString::fromStdString(cb.funcName) << "->已触发 ("<< triggerSource <<")"; - std::async(std::launch::async, [cb, copyByte = byteArray, triggerSource]() mutable { - try { - cb.func(triggerSource, copyByte); - } - catch (const std::exception& e) { - qCritical() << "Error in union callback " << QString::fromStdString(cb.funcName) << ": " << QString::fromStdString(e.what()) ; - } - catch (...) { - qCritical() << "Error in union callback : unexpected" << QString::fromStdString(cb.funcName); - } - }); + try { + cb.func(triggerSource, byteArray); + } + catch (const std::exception& e) { + qCritical() << "Error in union callback " << QString::fromStdString(cb.funcName) << ": " << QString::fromStdString(e.what()) ; + } + catch (...) { + qCritical() << "Error in union callback : unexpected" << QString::fromStdString(cb.funcName); + }; } } diff --git a/src/launcher/GUI/uiModule/uiModule_histogramWidget.h b/src/launcher/GUI/uiModule/uiModule_histogramWidget.h index a2b3bf6..d262546 100644 --- a/src/launcher/GUI/uiModule/uiModule_histogramWidget.h +++ b/src/launcher/GUI/uiModule/uiModule_histogramWidget.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include #include @@ -111,7 +113,7 @@ private: chartView->setRenderHint(QPainter::Antialiasing); mainLayout->addWidget(chartView); - setStyleSheet("QLabel { color: white; }"); + setStyleSheet("QLabel { color: white; } QToolTip { color: white; background-color: rgb(40, 45, 50); border: 1px solid rgb(80, 85, 90); }"); } void initChart() { @@ -119,6 +121,20 @@ private: barSet->setColor(QColor(255, 0, 0)); // 红色柱体 barSet->setBorderColor(QColor(255, 255, 255)); // 白色边框 + connect(barSet, &QBarSet::hovered, this, [this](bool status, int index) { + QMutexLocker locker(&mutex); + if (!status) { + QToolTip::hideText(); + return; + } + if (index < 0 || index >= categories.size()) + return; + const QString text = QString::fromUtf8("%1\n数量: %2") + .arg(categories.at(index)) + .arg(barSet->at(index)); + QToolTip::showText(QCursor::pos(), text, chartView, QRect(), 30000); + }); + series = new QBarSeries(); series->append(barSet); @@ -130,7 +146,6 @@ private: axisX = new QBarCategoryAxis(); axisX->setLabelsBrush(QBrush(Qt::white)); - axisX->setLabelsAngle(histogramLabelTiltAngle); // 设置标签倾斜 chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); @@ -142,7 +157,7 @@ private: series->attachAxis(axisY); chartView->setChart(chart); - chart->setMargins(QMargins(0, 0, 0, 0)); + chart->setMargins(QMargins(0, 0, 0, 0)); chart->setBackgroundBrush(QColor(50, 55, 60)); chartView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); chartView->setContentsMargins(0, 0, 0, 0); @@ -151,7 +166,7 @@ private: void updateValueLabels() { QFont font; - font.setPointSize(10); + font.setPointSize(histogramLabelTiltFontSize); font.setBold(true); // 删除旧标签 diff --git a/src/launcher/logger/qtLogRediretor.cpp b/src/launcher/logger/qtLogRediretor.cpp index 3bc4122..34612b3 100644 --- a/src/launcher/logger/qtLogRediretor.cpp +++ b/src/launcher/logger/qtLogRediretor.cpp @@ -1,6 +1,9 @@ #include "qtLogRediretor.h" #include #include +#include +#include +#include // 全局指针,用于消息处理函数 static qtRediretor* qtRediretor_Ptr = nullptr; @@ -22,7 +25,7 @@ static void qtMessageHandler(QtMsgType type, const QMessageLogContext& context, typeText = "ERROR"; break; case QtFatalMsg: - typeText = "ERROR"; + typeText = "FATAL"; break; default: typeText = "INFO"; diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index 1252629..92b7f45 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -7,6 +7,7 @@ #include #include //日志 #include +#include #include #include #include @@ -102,9 +103,10 @@ static bool dumpCallback(const wchar_t* dump_path, bool succeeded) { QString dumpFile = QString::fromWCharArray(dump_path) + "\\" + QString::fromWCharArray(minidump_id) + ".dmp"; + QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); if (succeeded) { - qDebug() << "========== 程序崩溃 =========="; + qDebug() << "========== 程序崩溃 ==========" << timestamp; qDebug() << "崩溃转储文件已生成:" << dumpFile; if (exinfo && exinfo->ExceptionRecord) { @@ -125,19 +127,33 @@ static bool dumpCallback(const wchar_t* dump_path, default: exceptionType = "未知异常"; break; } qDebug() << "异常类型:" << exceptionType; + + // 记录更多上下文信息 + if (exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && + exinfo->ExceptionRecord->NumberParameters >= 2) { + ULONG_PTR operation = exinfo->ExceptionRecord->ExceptionInformation[0]; + ULONG_PTR address = exinfo->ExceptionRecord->ExceptionInformation[1]; + QString operationType = (operation == 0) ? "读取" : (operation == 1) ? "写入" : "执行"; + qDebug() << "访问类型:" << operationType << "地址:" << Qt::hex << Qt::showbase << address; + } } + + // 记录当前线程ID + qDebug() << "崩溃线程ID:" << GetCurrentThreadId(); qDebug() << "=============================="; // 程序崩溃后自动重启 qDebug() << "程序即将自动重启..."; - } else { + qDebug() << "========== 崩溃转储失败 ==========" << timestamp; qDebug() << "生成崩溃转储文件失败!"; qDebug() << "程序即将自动重启..."; - - + qDebug() << "=============================="; } + + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + restartProgram(false, true, 5000); return succeeded; } @@ -317,6 +333,12 @@ int main(int argc, char* argv[]) std::cout << "程序将在五秒后重启..." << std::endl; restartProgram(false,true,5000); } + qDebug() << "程序退出,返回值" << qtRes; + if (qtRes != 0) { + qDebug() << "返回值不为0,非正常退出,即将重启程序"; + restartProgram(false, true, 5000); + } + QThread::msleep(200); return qtRes; } catch (const std::exception& e) { @@ -343,4 +365,5 @@ int main(int argc, char* argv[]) restartProgram(false, true, 5000); return -2; } + return -99; } \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam1213/581-BaoMo-Cam1213.cpp b/src/mission/581-BaoMo-Cam1213/581-BaoMo-Cam1213.cpp index e5830f5..2052c4c 100644 --- a/src/mission/581-BaoMo-Cam1213/581-BaoMo-Cam1213.cpp +++ b/src/mission/581-BaoMo-Cam1213/581-BaoMo-Cam1213.cpp @@ -131,7 +131,7 @@ halconResult dituo(std::shared_ptr data, cv::Mat& src, cv::Mat& Paint, } //释放存储画图文字 - textPainterdefect.excusePaintJobs(Paint); + textPainterdefect.executePaintJobs(Paint); } } CATCH_EXCEPTIONS diff --git a/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp index dfed6db..e0ee69d 100644 --- a/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp +++ b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp @@ -514,8 +514,8 @@ bool ALGO_BaoMoHouCeMian(std::shared_ptr data, baoMoHouDaMianDetParams } else cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); - textPainter.excusePaintJobs(Paint); - textPainterCls.excusePaintJobs(Paint); + textPainter.executePaintJobs(Paint); + textPainterCls.executePaintJobs(Paint); data->service->_missionResultHandle->toBarChart(data->SNcode, defects); int Rate = (Paint.rows > Paint.cols ? Paint.cols : Paint.rows) / 20; TextRendererZH textPainter1(Paint.cols, Paint.rows, Rate); diff --git a/src/mission/581-Dgh-CB-1/581-Dgh-CB-1.h b/src/mission/581-Dgh-CB-1/581-Dgh-CB-1.h index 5cbde25..9b985b4 100644 --- a/src/mission/581-Dgh-CB-1/581-Dgh-CB-1.h +++ b/src/mission/581-Dgh-CB-1/581-Dgh-CB-1.h @@ -162,7 +162,7 @@ static bool yuHanQian3D(std::shared_ptr data, detParams* _detParams, y data->service->_missionResultHandle->toBarChart(data->SNcode, defects); Paint = HObject2Mat(out_DisplayImage); - textPainter.excusePaintJobs(Paint); + textPainter.executePaintJobs(Paint); int rate = MIN(Paint.rows, Paint.cols) / 20; TextRendererZH textPainter1(Paint.cols, Paint.rows, rate); textPainter1.putText(Paint, "当前条码:" + data->SNcode, cv::Point(50, Paint.rows - (rate * 2)), cv::Scalar(0, 255, 255)); diff --git a/src/mission/581_Ruanlianjie_dianjiao_tiejiao/581_Ruanlianjie_dianjiao_tiejiao.cpp b/src/mission/581_Ruanlianjie_dianjiao_tiejiao/581_Ruanlianjie_dianjiao_tiejiao.cpp index 88fee7c..9cfa188 100644 --- a/src/mission/581_Ruanlianjie_dianjiao_tiejiao/581_Ruanlianjie_dianjiao_tiejiao.cpp +++ b/src/mission/581_Ruanlianjie_dianjiao_tiejiao/581_Ruanlianjie_dianjiao_tiejiao.cpp @@ -195,7 +195,7 @@ bool DianJiaoJianCe(std::shared_ptr data, dianJiaoParams* _detParams, _detParams->batteryIsNg = (_detParams->lastResultIsNg == true || plcResult == "2"); _detParams->lastResultIsNg = false; - textPainter.excusePaintJobs(Paint); + textPainter.executePaintJobs(Paint); Paint.copyTo(_detParams->lastDetImg); } else if (address.triggerValue == 4) { @@ -209,7 +209,7 @@ bool DianJiaoJianCe(std::shared_ptr data, dianJiaoParams* _detParams, _detParams->lastResultIsNg = false; _detParams->batteryIsNg = false; - textPainter.excusePaintJobs(Paint); + textPainter.executePaintJobs(Paint); if (_detParams->lastDetImg.empty() == false) cv::hconcat(_detParams->lastDetImg, Paint, Paint); data->insertResultImg(Paint); @@ -320,8 +320,8 @@ bool TieJiaoJianCe(std::shared_ptr data, tieJiaoParams* _detParams, sx if (plcResult == "2") _detParams->lastResultIsNg = true; } - textPainter.excusePaintJobs(Paint); - textPainter2.excusePaintJobs(Paint); + textPainter.executePaintJobs(Paint); + textPainter2.executePaintJobs(Paint); data->insertResultImg(Paint); return true; } diff --git a/src/mission/581_Ruanlianjie_hanqian_hanhou/581_Ruanlianjie_hanqian_hanhou.cpp b/src/mission/581_Ruanlianjie_hanqian_hanhou/581_Ruanlianjie_hanqian_hanhou.cpp index 73f25c8..ee37484 100644 --- a/src/mission/581_Ruanlianjie_hanqian_hanhou/581_Ruanlianjie_hanqian_hanhou.cpp +++ b/src/mission/581_Ruanlianjie_hanqian_hanhou/581_Ruanlianjie_hanqian_hanhou.cpp @@ -193,9 +193,9 @@ bool HanQianDingWei(std::shared_ptr data, hanQianDingWeiParams* _detPa data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 data->service->_missionResultHandle->toBarChart(data->SNcode, defects); - textPainter.excusePaintJobs(Paint); - textPainter2.excusePaintJobs(Paint); - textPainter3.excusePaintJobs(Paint); + textPainter.executePaintJobs(Paint); + textPainter2.executePaintJobs(Paint); + textPainter3.executePaintJobs(Paint); TextRendererZH textPainterx(Paint.cols, Paint.rows, 160); textPainterx.putText(Paint, "SN:" + data->SNcode, cv::Point(3000,0), cv::Scalar(0, 255, 0)); textPainterx.putText(Paint, QDateTime::currentDateTime().toString().toStdString(), cv::Point(3000, 80), cv::Scalar(0, 255, 0)); @@ -215,7 +215,9 @@ struct halconResult_2D { bool halconOK = false; }; halconResult_2D HanHou2D_halconEvaluate(const cv::Mat& sourceImg,const cv::Mat& segImg, TextRendererZH* textPainter, int times, - double tongXingDuLimitHigh, double tongXingDuLimitLow, bool tongXingDuLimitEnable) { + double tongXingDuLimitHigh, double tongXingDuLimitLow, bool tongXingDuLimitEnable, + double neiYuanPianYiTongXinDuLimitHigh, double neiYuanPianYiTongXinDuLimitLow, bool neiYuanPianYiTongXinDuEnable, + double waiYuanPianYiTongXinDuLimitHigh, double waiYuanPianYiTongXinDuLimitLow, bool waiYuanPianYiTongXinDuEnable) { halconResult_2D result; HDevEngineCpp::HDevProcedure proc("_3_Cal_HY_CC_Distance"); @@ -253,7 +255,15 @@ halconResult_2D HanHou2D_halconEvaluate(const cv::Mat& sourceImg,const cv::Mat& y1Text = y1Text.substr(0, y1Text.find(".") + 4); std::string txd1Text = std::to_string(result.neiYuanTongXinDu); txd1Text = txd1Text.substr(0, txd1Text.find(".") + 4); - textPainter->appendPaintJob("内圆偏移X:" + x1Text + "mm Y:" + y1Text + "mm 同心度" + txd1Text, cv::Point(0, 250), cv::Scalar(0, 255, 0)); + if (result.neiYuanTongXinDu > neiYuanPianYiTongXinDuLimitHigh || result.neiYuanTongXinDu < neiYuanPianYiTongXinDuLimitLow) { + textPainter->appendPaintJob("内圆偏移X:" + x1Text + "mm Y:" + y1Text + "mm 同心度" + txd1Text, cv::Point(0, 250), cv::Scalar(0, 255, 0)); + result.halconOK = false; + if (waiYuanPianYiTongXinDuEnable == true) + result.isNg = true; + } + else + textPainter->appendPaintJob("内圆偏移X:" + x1Text + "mm Y:" + y1Text + "mm 同心度" + txd1Text, cv::Point(0, 250), cv::Scalar(0, 255, 0)); + result.waiYuanPianYi_X = OuterCircle_offset[0].D(); result.waiYuanPianYi_Y = OuterCircle_offset[1].D(); @@ -265,7 +275,14 @@ halconResult_2D HanHou2D_halconEvaluate(const cv::Mat& sourceImg,const cv::Mat& y2Text = y2Text.substr(0, y2Text.find(".") + 4); std::string txd2Text = std::to_string(result.waiYuanTongXinDu); txd2Text = txd2Text.substr(0, txd2Text.find(".") + 4); - textPainter->appendPaintJob("外圆偏移X:" + x2Text + "mm Y:" + y2Text + "mm 同心度:" + txd2Text, cv::Point(0, 450), cv::Scalar(0, 255, 0)); + if (result.waiYuanTongXinDu > waiYuanPianYiTongXinDuLimitHigh || result.waiYuanTongXinDu < waiYuanPianYiTongXinDuLimitLow) { + textPainter->appendPaintJob("外圆偏移X:" + x2Text + "mm Y:" + y2Text + "mm 同心度:" + txd2Text, cv::Point(0, 450), cv::Scalar(0, 0, 255)); + result.halconOK = false; + if (waiYuanPianYiTongXinDuEnable == true) + result.isNg = true; + } + else + textPainter->appendPaintJob("外圆偏移X:" + x2Text + "mm Y:" + y2Text + "mm 同心度:" + txd2Text, cv::Point(0, 450), cv::Scalar(0, 255, 0)); for (int i = 0; i < out_Circle.Length() / 3; i++) { textPainter->appendPaintJob(cv::Point(out_Circle[i * 3 + 1].D(), out_Circle[i * 3].D()), out_Circle[i * 3 + 2].D(), cv::Scalar(0, 255, 0), 15,0); @@ -340,6 +357,17 @@ QByteArray getHanHouJianCe2DSendResult(bool isNg1,bool isNg2) { bool HanHouJianCe2D(std::shared_ptr data, hanHouJianCe* _detParams, sx_581_address address){ try { + double tongXingDuLimitHigh = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(上限)", 1.8).toDouble(); + double tongXingDuLimitLow = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(下限)", 0).toDouble(); + bool tongXingDuLimitEnable = data->service->_paramSyncManager->get("焊后", "焊后同心度判定启用", true).toBool(); + + double neiYuanPianYiTongXinDuLimitHigh = data->service->_paramSyncManager->get("焊后", "内圆偏移同心度mm(上限)", 2.0).toDouble(); + double neiYuanPianYiTongXinDuLimitLow = data->service->_paramSyncManager->get("焊后", "内圆偏移同心度mm(下限)", 0).toDouble(); + bool neiYuanPianYiTongXinDuEnable = data->service->_paramSyncManager->get("焊后", "内圆偏移同心度判定启用", false).toBool(); + + double waiYuanPianYiTongXinDuLimitHigh = data->service->_paramSyncManager->get("焊后", "外圆偏移同心度mm(上限)", 1.0).toDouble(); + double waiYuanPianYiTongXinDuLimitLow = data->service->_paramSyncManager->get("焊后", "外圆偏移同心度mm(下限)", 0).toDouble(); + bool waiYuanPianYiTongXinDuEnable = data->service->_paramSyncManager->get("焊后", "外圆偏移同心度判定启用", false).toBool(); #pragma region 错误处理 if (data->getOriImgSize() < 2) { @@ -414,11 +442,13 @@ bool HanHouJianCe2D(std::shared_ptr data, hanHouJianCe* _detParams, sx data->insertResultImg(PaintSum); return true; } - double tongXingDuLimitHigh = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(上限)", 1.8).toDouble(); - double tongXingDuLimitLow = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(下限)", 0).toDouble(); - bool tongXingDuLimitEnable = data->service->_paramSyncManager->get("焊后", "焊后同心度判定启用", true).toBool(); - auto futrue1 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src1, seg1Ori, &textPainter1, 0, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable); - auto futrue2 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src2, seg2Ori, &textPainter2, 2, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable); + + auto futrue1 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src1, seg1Ori, &textPainter1, 0, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable, + neiYuanPianYiTongXinDuLimitHigh, neiYuanPianYiTongXinDuLimitLow, neiYuanPianYiTongXinDuEnable, + waiYuanPianYiTongXinDuLimitHigh, waiYuanPianYiTongXinDuLimitLow, waiYuanPianYiTongXinDuEnable); + auto futrue2 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src2, seg2Ori, &textPainter2, 2, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable, + neiYuanPianYiTongXinDuLimitHigh, neiYuanPianYiTongXinDuLimitLow, neiYuanPianYiTongXinDuEnable, + waiYuanPianYiTongXinDuLimitHigh, waiYuanPianYiTongXinDuLimitLow, waiYuanPianYiTongXinDuEnable); auto futrue3 = std::async(std::launch::async, &HanHou2D_handleAiEvaluate, data, _detParams, src1, &textPainter1, _detParams->seg_rljHanZha1, _detParams->cls_rljHanZha1); auto futrue4 = std::async(std::launch::async, &HanHou2D_handleAiEvaluate, data, _detParams, src2, &textPainter2, _detParams->seg_rljHanZha2, _detParams->cls_rljHanZha2); @@ -488,8 +518,8 @@ bool HanHouJianCe2D(std::shared_ptr data, hanHouJianCe* _detParams, sx data->insertClsOriginImg(hanYinClsImg); data->service->_missionResultHandle->toBarChart(data->SNcode, defects); - textPainter1.excusePaintJobs(Paint1); - textPainter2.excusePaintJobs(Paint2); + textPainter1.executePaintJobs(Paint1); + textPainter2.executePaintJobs(Paint2); //拼装结果图 cv::Mat PaintSum; cv::vconcat(Paint1, Paint2, PaintSum); @@ -525,9 +555,9 @@ bool HanHouJianCe2D(std::shared_ptr data, hanHouJianCe* _detParams, sx struct halconResult_3D { bool isNg = false; double hanPanGaoDu = -99; - cv::Point ellipseCenter; - double angle; - cv::Size ellipseSize; + cv::Point ellipseCenter = cv::Point(0,0); + double angle = 0; + cv::Size ellipseSize = cv::Size(0,0); bool halconOK = false; }; halconResult_3D HanHou3D_halconEvaluate(const cv::Mat& heightImg, const double& xResolution, const double& yResolution, const double& zResolution @@ -542,30 +572,42 @@ halconResult_3D HanHou3D_halconEvaluate(const cv::Mat& heightImg, const double& procedureCall.SetInputCtrlParamTuple("in_XResolution", xResolution); procedureCall.SetInputCtrlParamTuple("in_YResolution", yResolution); procedureCall.SetInputCtrlParamTuple("in_ZResolution", zResolution); - procedureCall.SetInputCtrlParamTuple("in_FliePath", "./halconFiles/"); + procedureCall.SetInputCtrlParamTuple("in_FilePath", "./halconFiles/hanhou3D/"); procedureCall.Execute();//执行halcon程序 HalconCpp::HTuple out_Height = procedureCall.GetOutputCtrlParamTuple("out_Height");//获取输出控制类变量 HalconCpp::HTuple out_Ellipse = procedureCall.GetOutputCtrlParamTuple("out_Ellipse");//获取输出控制类变量 HalconCpp::HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量 HalconCpp::HTuple out_NGDetails = procedureCall.GetOutputCtrlParamTuple("out_NGDetails");//获取输出控制类变量 + qDebug() << "testFlag0"; int flag = out_Flag.D(); if (flag == 1) { + qDebug() << "testFlag1"; double height = out_Height.D(); - textPainter->appendPaintJob("焊盘高度:" + std::to_string(height), cv::Point(0, 50), cv::Scalar(0, 255, 0)); - result.ellipseCenter = cv::Point(out_Ellipse[0].D(), out_Ellipse[1].D()); - result.angle = out_Ellipse[2].D(); - result.ellipseSize = cv::Point(out_Ellipse[3].D(), out_Ellipse[4].D()); + textPainter->appendPaintJob("焊盘高度:" + std::to_string(height), cv::Point(0, 110), cv::Scalar(0, 255, 0)); + qDebug() << "testFlag2"; + if (out_Ellipse.Length() == 5) { + result.ellipseCenter = cv::Point(out_Ellipse[0].D(), out_Ellipse[1].D()); + result.angle = out_Ellipse[2].D(); + result.ellipseSize = cv::Point(out_Ellipse[3].D(), out_Ellipse[4].D()); + } + else { + qDebug() << "无椭圆数据 size"<< out_Ellipse.Length(); + } + qDebug() << "testFlag3"; } else { - textPainter->appendPaintJob("算法NG:" + std::to_string(out_NGDetails[0].D()), cv::Point(10, 50), cv::Scalar(0, 0, 255)); + qDebug() << "testFlag4"; + textPainter->appendPaintJob("算法NG:" + gbkToUtf8(out_NGDetails.ToString().Text()), cv::Point(10, 50), cv::Scalar(0, 0, 255)); result.isNg = true; result.halconOK = false; + qDebug() << "testFlag5"; } return result; } bool HanHouJianCe3D(std::shared_ptr data, hanHouJianCe* _detParams, sx_581_address address) { try { + bool enable = data->service->_paramSyncManager->get("焊后3D", "焊后3D结果判定启用", false).toBool();; data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果 qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; std::vector < std::string> defects = { }; @@ -590,13 +632,13 @@ bool HanHouJianCe3D(std::shared_ptr data, hanHouJianCe* _detParams, sx cv::Mat height1 = data->getOriImg(1);//高度图1 cv::Mat src2 = data->getOriImg(2);//亮度图2 cv::Mat height2 = data->getOriImg(3);//高度图2 - TextRendererZH textPainter1(src1.cols, src1.rows, 300), textPainter2(src2.cols, src2.rows, 300); - auto futrue1 = std::async(std::launch::async, &HanHou3D_halconEvaluate, height1, + TextRendererZH textPainter1(src1.cols, src1.rows, 100), textPainter2(src2.cols, src2.rows, 100); + auto result1 = HanHou3D_halconEvaluate(height1, data->service->_paramSyncManager->get("3D相机1精度","x向精度",0.005).toDouble(), data->service->_paramSyncManager->get("3D相机1精度", "y向精度", 0.02).toDouble(), data->service->_paramSyncManager->get("3D相机1精度", "z向精度", 0.0008).toDouble(), &textPainter1); - auto futrue2 = std::async(std::launch::async, &HanHou3D_halconEvaluate, height1, + auto result2 = HanHou3D_halconEvaluate(height2, data->service->_paramSyncManager->get("3D相机2精度", "x向精度", 0.005).toDouble(), data->service->_paramSyncManager->get("3D相机2精度", "y向精度", 0.02).toDouble(), data->service->_paramSyncManager->get("3D相机2精度", "z向精度", 0.0008).toDouble(), @@ -608,10 +650,16 @@ bool HanHouJianCe3D(std::shared_ptr data, hanHouJianCe* _detParams, sx cv::cvtColor(Paint1, Paint1, cv::COLOR_GRAY2BGR); if (Paint2.channels() != 3) cv::cvtColor(Paint2, Paint2, cv::COLOR_GRAY2BGR); + + if(result1.ellipseCenter.x != 0) + cv::ellipse(Paint1, result1.ellipseCenter, result1.ellipseSize, result1.angle, 0, 360, cv::Scalar(0, 255, 0), 3); + + if (result2.ellipseCenter.x != 0) + cv::ellipse(Paint2, result2.ellipseCenter, result2.ellipseSize, result2.angle, 0, 360, cv::Scalar(0, 255, 0), 3); textPainter1.putText(Paint1, "OK", cv::Point(10, 10), cv::Scalar(0, 255, 0)); - textPainter1.excusePaintJobs(Paint1); + textPainter1.executePaintJobs(Paint1); textPainter2.putText(Paint2, "OK", cv::Point(10, 10), cv::Scalar(0, 255, 0)); - textPainter1.excusePaintJobs(Paint2); + textPainter2.executePaintJobs(Paint2); cv::vconcat(Paint1, Paint2, PaintSum); putSnAndDetTime(PaintSum, data->SNcode, 60); diff --git a/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.cpp b/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.cpp index f1f03f6..27aa465 100644 --- a/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.cpp +++ b/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.cpp @@ -125,10 +125,9 @@ bool ALGO_maJiaReRong(std::shared_ptr data, maJiaParam* _detParams, sx data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送异常结果 return false; } -bool ALGO_hanQianDingWei(std::shared_ptr data, detParams* _detParams, sx_581_address address) { +static bool ALGO_hanQianDingWei(std::shared_ptr data, detParams* _detParams, sx_581_address address) { try { qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; - data->service->_triggerManager->writeShort("D100_1_1"); ///////////////////取图//处理////////////////// if (data->getOriImgSize() < 1) { @@ -137,6 +136,8 @@ bool ALGO_hanQianDingWei(std::shared_ptr data, detParams* _detParams, } auto sourceImg = data->getOriImg(0); sourceImg = cv::imread("D:\\testImage\\601\\hanqian.bmp", -1); + QThread::msleep(200); + if (sourceImg.rows == 100) { cv::Mat Paint; sourceImg.copyTo(Paint); @@ -145,31 +146,35 @@ bool ALGO_hanQianDingWei(std::shared_ptr data, detParams* _detParams, } cv::Mat Paint; sourceImg.copyTo(Paint); - HDevEngineCpp::HDevProcedure proc("HQDW_Color_Inspection"); - HDevEngineCpp::HDevProcedureCall procedureCall(proc); - - HObject inputImage = MatToHObject(sourceImg); - HTuple in_Resolution(0.040766), in_FilePath("./halconFiles/"); - - - double HeightLeft_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前左侧Y向高度差", 2.0).toDouble(); - double HeightRight_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前右侧Y向高度差", 2.0).toDouble(); - double SlantAngle_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前盖板上下边缘膜的角度", 0.6).toDouble(); - - procedureCall.SetInputIconicParamObject("in_Image", inputImage); - procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution); - procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath); - procedureCall.Execute();//执行halcon程序 - HTuple out_ColorType, out_Distance, make, out_SlantAngle, out_Height;; + HTuple out_ColorType, out_Distance, make; HObject out_DisplayImage; - //out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint");//获取输出控制类变量 - out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出控制类变量 - //out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");//获取输出控制类变量 - out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");//获取输出控制类变量 - out_Height = procedureCall.GetOutputCtrlParamTuple("out_Height");//获取输出控制类变量 - out_SlantAngle = procedureCall.GetOutputCtrlParamTuple("out_SlantAngle");//获取输出控制类变量 - make = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量 - out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");//获取输出控制类变量 + { + HDevEngineCpp::HDevProcedure proc("HQDW_Color_Inspection"); + HDevEngineCpp::HDevProcedureCall procedureCall(proc); + + HObject inputImage = MatToHObject(sourceImg); + HTuple in_Resolution(0.040766), in_FilePath("./halconFiles/"); + + + double HeightLeft_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前左侧Y向高度差", 2.0).toDouble(); + double HeightRight_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前右侧Y向高度差", 2.0).toDouble(); + double SlantAngle_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前盖板上下边缘膜的角度", 0.6).toDouble(); + + procedureCall.SetInputIconicParamObject("in_Image", inputImage); + procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution); + procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath); + procedureCall.Execute();//执行halcon程序 + + + //out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint");//获取输出控制类变量 + out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出控制类变量 + //out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");//获取输出控制类变量 + out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");//获取输出控制类变量 + //out_Height = procedureCall.GetOutputCtrlParamTuple("out_Height");//获取输出控制类变量 + //out_SlantAngle = procedureCall.GetOutputCtrlParamTuple("out_SlantAngle");//获取输出控制类变量 + make = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量 + out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");//获取输出控制类变量 + } int flag = make.D(); QString tmpFlag = "1"; // Output(HTuple): out_ColorType, 1, 铜; 2,铝 @@ -187,29 +192,29 @@ bool ALGO_hanQianDingWei(std::shared_ptr data, detParams* _detParams, Paint = HObject2Mat(out_DisplayImage); textPainter.appendPaintJob("膜上边到注液孔:" + std::to_string(out_Distance[0].D()), cv::Point(800, 50), cv::Scalar(0, 255, 0)); textPainter.appendPaintJob("膜下边到注液孔:" + std::to_string(out_Distance[1].D()), cv::Point(800, 350), cv::Scalar(0, 255, 0)); - textPainter.excusePaintJobs(Paint); - if (out_Height[0].D() > HeightLeft_jsonvlaue) + textPainter.executePaintJobs(Paint); + /* if (out_Height[0].D() > HeightLeft_jsonvlaue) { HeightLeftFlag = 2; textPainter.putText(Paint, "左侧Y向高度差:" + std::to_string(out_Height[0].D()), cv::Point(800, 650), cv::Scalar(0, 0, 255)); } else - textPainter.putText(Paint, "左侧Y向高度差:" + std::to_string(out_Height[0].D()), cv::Point(800, 650), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "左侧Y向高度差:" + std::to_string(out_Height[0].D()), cv::Point(800, 650), cv::Scalar(0, 255, 0));*/ - if (out_Height[1].D() > HeightRight_jsonvlaue) - { - HeightRightFlag = 2; - textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 0, 255)); - } - else - textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 255, 0)); - if (out_SlantAngle.D() > SlantAngle_jsonvlaue) - { - AlgelFlag = 2; - textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 0, 255)); - } - else - textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 255, 0)); + //if (out_Height[1].D() > HeightRight_jsonvlaue) + //{ + // HeightRightFlag = 2; + // textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 0, 255)); + //} + //else + // textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 255, 0)); + //if (out_SlantAngle.D() > SlantAngle_jsonvlaue) + //{ + // AlgelFlag = 2; + // textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 0, 255)); + //} + //else + // textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 255, 0)); int left = out_ColorType[0].D(); if (left == 2) textPainter.putText(Paint, "铜", cv::Point(0, 3100), cv::Scalar(0, 0, 255)); @@ -244,12 +249,8 @@ bool ALGO_hanQianDingWei(std::shared_ptr data, detParams* _detParams, plcResult = "2"; } - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//发送异常结果 - if (plcResult == "2") - data->service->_missionResultHandle->toBarChart(data->SNcode, { "焊前NG" }); - else - data->service->_missionResultHandle->toBarChart(data->SNcode, { }); + data->service->_missionResultHandle->toBarChart(data->SNcode, { "焊前NG" + data->SNcode}); cv::resize(Paint, Paint, cv::Size(), 0.25, 0.25); data->insertResultImg(Paint); diff --git a/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.h b/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.h index 38bfe4f..cb7f149 100644 --- a/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.h +++ b/src/mission/601/601_RLJ_DingGai/601_RLJ_DingGai.h @@ -14,7 +14,7 @@ struct hanQianDingWeiSubresult { double Out_Vale_L_centerUp = -1;//铝(负)极连接片中心的和上极耳水平边缘距离(mm) double Out_Vale_L_centerDown = -1;//铝(负)极连接片中心的和下极耳水平边缘距离(mm) double extremumValue = -1; - + cv::Point circleCenter; double radius = 1; std::vector lines; diff --git a/src/mission/601/601_RLJ_HH/601_RLJ_HH.cpp b/src/mission/601/601_RLJ_HH/601_RLJ_HH.cpp index 27c0c17..cd962ec 100644 --- a/src/mission/601/601_RLJ_HH/601_RLJ_HH.cpp +++ b/src/mission/601/601_RLJ_HH/601_RLJ_HH.cpp @@ -144,8 +144,8 @@ bool hanhou2D(std::shared_ptr data, hanHou2dParam* _detParams, sx_581_ data->service->_missionResultHandle->toBarChart(data->SNcode, defects); futrue3.wait(); futrue4.wait(); - textPainter1.excusePaintJobs(Paint1); - textPainter2.excusePaintJobs(Paint2); + textPainter1.executePaintJobs(Paint1); + textPainter2.executePaintJobs(Paint2); cv::Mat PaintSum; cv::vconcat(Paint1, Paint2, PaintSum);