From 64ba32994685536a273635afff04c44b16d686ef Mon Sep 17 00:00:00 2001 From: RCi <15089880081@163.com> Date: Tue, 14 Oct 2025 13:45:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=98=E5=9B=BE=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E3=80=82=20=E4=BF=AE=E5=A4=8D=E5=9B=A0=E5=AD=98?= =?UTF-8?q?=E5=9B=BE=E8=B7=AF=E5=BE=84=E5=BC=95=E8=B5=B7=E6=9C=AA=E8=83=BD?= =?UTF-8?q?=E5=AD=98=E5=88=B0=E7=9B=AE=E6=A0=87=E6=96=87=E4=BB=B6=E5=A4=B9?= =?UTF-8?q?=E7=9A=84bug=E3=80=82=20=E4=BF=AE=E6=94=B9=E4=BA=86=E8=AF=BB?= =?UTF-8?q?=E6=9D=A1=E7=A0=81=E4=B8=BA=E7=A9=BA=E7=9A=84=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/back/imgSaveThreadManager.h | 35 +++--- src/Core/back/triggerManager.h | 13 +-- .../581_YiCiZhuYe_canye.cpp | 106 ++++++++++++++++++ .../581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h | 58 ++++++++++ .../581_YiCiZhuYe_canye/CMakeLists.txt | 77 +++++++++++++ 5 files changed, 265 insertions(+), 24 deletions(-) create mode 100644 src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp create mode 100644 src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h create mode 100644 src/mission/581_YiCiZhuYe_canye/CMakeLists.txt diff --git a/src/Core/back/imgSaveThreadManager.h b/src/Core/back/imgSaveThreadManager.h index a882cff..dc77f71 100644 --- a/src/Core/back/imgSaveThreadManager.h +++ b/src/Core/back/imgSaveThreadManager.h @@ -101,16 +101,17 @@ public: // 一级目录(根路径) const QString basePath = path; - // 二级目录(图片类型) + // 二级目录 (日期与小时) + QDateTime now = QDateTime::currentDateTime(); + QString dateDir = now.toString("yyyy-MM-dd"); + QString hourDir = QString("%1H").arg(now.time().hour()); + + // 三级目录(图片类型) static const QMap typeMap{ { oriImg, "原图" }, { resImg, "结果图" } }; QString imgTypeDir = typeMap.value(type, "error"); - // 日期与小时 - QDateTime now = QDateTime::currentDateTime(); - QString dateDir = now.toString("yyyy-MM-dd"); - QString hourDir = QString("%1H").arg(now.time().hour()); // 检测结果 QString resultDir; @@ -126,10 +127,10 @@ public: // 拼接路径 QDir dir(basePath); - dir = QDir(dir.filePath(imgTypeDir)); if (data->saveObjectName != "") dir = QDir(dir.filePath(data->saveObjectName)); dir = QDir(dir.filePath(dateDir)); + dir = QDir(dir.filePath(imgTypeDir)); dir = QDir(dir.filePath(hourDir)); dir = QDir(dir.filePath(resultDir)); if (mode != oneFile) @@ -173,14 +174,14 @@ public: } return resultFileNames; } - void packageData(QQueue>& jobQueue, std::vector fileNames, std::vector& mats) { + void packageData(QQueue>& jobQueue, std::string imgSavaPath, std::vector fileNames, std::vector& mats) { if (fileNames.size() != mats.size()) qWarning() << "检测到存图文件名数量与图片数量不符"; for (int index = 0; index < fileNames.size() && index < mats.size(); index++) { try { - if (mats[index].data == nullptr || &mats[index] == nullptr) { + if (mats[index].data == nullptr) { qDebug() << "在存图线程中发现无效图像"; continue; } @@ -192,17 +193,17 @@ public: cv::Mat img; mats[index].copyTo(img); - jobQueue.enqueue(std::make_pair(fileNames[index], img)); + jobQueue.enqueue(std::make_pair(imgSavaPath + fileNames[index], img)); } } - void packageData(QQueue>& jobQueue, std::vector fileNames, std::vector>& mats) { + void packageData(QQueue>& jobQueue, std::string imgSavaPath, std::vector fileNames, std::vector>& mats) { if (fileNames.size() != mats.size()) qWarning() << "检测到存图文件名数量与图片数量不符"; for (int index = 0; index < fileNames.size() && index < mats.size(); index++) { try { - if (mats[index].second.data == nullptr || &mats[index].second == nullptr) { + if (mats[index].second.data == nullptr) { qDebug() << "在存图线程中发现无效图像"; continue; } @@ -214,7 +215,7 @@ public: cv::Mat img; mats[index].second.copyTo(img); - jobQueue.enqueue(std::make_pair(fileNames[index], img)); + jobQueue.enqueue(std::make_pair(imgSavaPath + fileNames[index], img)); } } @@ -225,8 +226,8 @@ public: QString fileSavePath = genDirName(data, oriImg, data->_saveMode);//获取文件夹名 createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建 std::vectorfileNames = genFileNames(data, oriImg);//按规则为文件创建命名 - std::shared_ptr job (new saveJob("[ORI_JOB]+ data->SNcode")); - packageData(job->imgQueue, fileNames, data->oriImgs);//打包数据 + std::shared_ptr job (new saveJob("[ORI_JOB]" + data->SNcode)); + packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(), fileNames, data->oriImgs);//打包数据 saveThread.addJob(job); } } @@ -238,17 +239,17 @@ public: //结果图保存 if (data->resultImgs.size() != 0) { std::vectorfileNames = genFileNames(data, resImg);//按规则为文件创建命名 - packageData(job->imgQueue, fileNames, data->resultImgs);//打包数据 + packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(),fileNames, data->resultImgs);//打包数据 } //SEG原图 if (data->segOriginImgs.size() != 0) { std::vectorfileNames = genFileNames(data, segImg);//按规则为文件创建命名 - packageData(job->imgQueue, fileNames, data->segOriginImgs);//打包数据 + packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(),fileNames, data->segOriginImgs);//打包数据 } //CLS原图 if (data->clsOriginImgs.size() != 0) { std::vectorfileNames = genFileNames(data, clsImg);//按规则为文件创建命名 - packageData(job->imgQueue, fileNames, data->clsOriginImgs);//打包数据 + packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(), fileNames, data->clsOriginImgs);//打包数据 } saveThread.addJob(job, imgSaveThread::priority); //额外储存NG文件夹 diff --git a/src/Core/back/triggerManager.h b/src/Core/back/triggerManager.h index ae461bd..556d47a 100644 --- a/src/Core/back/triggerManager.h +++ b/src/Core/back/triggerManager.h @@ -340,22 +340,21 @@ public: bool highLowConversion, bool clearAfterRead, int Size){ int startPos = 0; for (auto& _struct : readAllCmds) { - if (dmPos > _struct.startPos && - dmPos < _struct.startPos + _struct.readLength) + if (dmPos >= _struct.startPos && dmPos < _struct.startPos + _struct.readLength) startPos = _struct.startPos; } if (startPos == 0) { - qCritical() << "读条码越界"; - return "ERROR_OUT_OF_RANGE"; + qCritical() << dmPos<< "读条码越界"; + return "READ_SN_ERROR_OUT_OF_RANGE[" + std::to_string(dmPos) + "]"; } int triggerPos = (dmPos - startPos) * 2; if (triggerPos < 0){ - std::cout << "Read SN error,trigger is DM:" << dmPos << ",but read start at DM:" << startPos << endl; - return "snErrorsnError" + getCurrentDateTime(); + std::cout << "Read SN ,trigger is DM:" << dmPos << ",but read start at DM:" << startPos << endl; + return "readSnConfigError" + getCurrentDateTime(); } QString str; if (plcByte.at(triggerPos + 1) == 0 && plcByte.at(triggerPos) == 0) - return "snErrorsnError" + getCurrentDateTime(); + return "readSnEmpty" + getCurrentDateTime(); int snCount = 0; try { if (highLowConversion == true) { diff --git a/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp new file mode 100644 index 0000000..b8479f2 --- /dev/null +++ b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp @@ -0,0 +1,106 @@ +#include <581_YiCiZhuYe_canye.h> + +void exceptionResume(std::shared_ptr data, canyeParams* _detParams, sx_581_address address) { + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode); + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 +} +bool yizhuCanYe(std::shared_ptr data, canyeParams* _detParams, sx_581_address address){ + + try + { + if (!_detParams->DOGLIVE) + { + exceptionResume(data, _detParams, address); + return true; + } + else + { + QByteArray plcResult = "1"; + QString detResult = "OK"; + cv::Mat sourceImg = data->oriImgs[0]; + cv::Mat Paint; + sourceImg.copyTo(Paint); + + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + QString okNgSaveText = "OK"; + { + cv::Mat workImg; + cv::resize(sourceImg, workImg, cv::Size(), 0.25, 0.25); + cv::Rect rect1; + /////////////定位 ////////////////// + //cv::resize(workImg, workImg, cv::Size(), 0.25, 0.25); + cv::Mat dingWeiResultImg = ~_detParams->segDingWei->Evaluate(workImg); + cv::Rect dingWeiRect = findMaxAreaContour(dingWeiResultImg); + cv::Point2f center(dingWeiRect.x + dingWeiRect.width / 2, dingWeiRect.y + dingWeiRect.height / 2); + cv::Mat centerImg; + cv::Rect cutArea = cv::Rect(center.x - 64, center.y - 64, 128, 128); + workImg(cutArea).copyTo(centerImg); + //////////////////////////////////// + int res = 0; + res = _detParams->clsCanYe->Evaluate(centerImg); + if (res == 0){ + + cv::putText(Paint, "OK", cv::Point(Paint.cols - 500, 0), 10,10,cv::Scalar(0, 255, 0)); + cv::rectangle(Paint, cv::Rect(cutArea.x * 4, cutArea.y * 4, cutArea.width * 4, cutArea.height * 4), cv::Scalar(0, 255, 0), 3); + } + else{ + + cv::putText(Paint, "NG", cv::Point(Paint.cols - 500, 0), 10, 10, cv::Scalar(0, 255, 0)); + cv::rectangle(Paint, cv::Rect(cutArea.x * 4, cutArea.y * 4, cutArea.width * 4, cutArea.height * 4), cv::Scalar(0, 0, 255), 3); + plcResult = "2"; + data->aiDetOK = false; + } + } + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + data->resultImgs.push_back(Paint); + return true; + } + } + CATCH_EXCEPTIONS + exceptionResume(data, _detParams, address); + return true; +} + +bool erzhuCanYe(std::shared_ptr data, canyeParams* _detParams, sx_581_address address) +{ + QByteArray plcResult = "1"; + QByteArray data1 = "1"; + QByteArray data2 = "1"; + QString detResult = "OK"; + cv::Mat sourceImg = data->oriImgs[0]; + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + + //绘制结果 + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + textPainter.putText(Paint, detResult.toStdString(), cv::Point(4000, 50), cv::Scalar(0, 255, 0)); + + //数据发送 + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + data->service->_triggerManager->writeShort("D" + QByteArray::number(address.valueOffsetAddr + 0) + "_" + data1);//数据1 + data->service->_triggerManager->writeShort("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + data2);//数据1 + data->aiDetOK = true; + data->resultImgs.push_back(Paint); + + return true; +} + +mission* createMission() { + return new _581_YiCiZhuYe_canye(); +} +void destroyMission(mission* _mission) { + delete _mission; +} + diff --git a/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h new file mode 100644 index 0000000..8dc5953 --- /dev/null +++ b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h @@ -0,0 +1,58 @@ +#include +#include +#pragma region 算法 +#include +#include +#include +using namespace HDevEngineCpp; +#pragma endregion +class canyeParams { +public: + handdleAI::pSegmentation* segDingWei = nullptr; + handdleAI::pSegmentation* segDanYe = nullptr; + handdleAI::pClassification* clsCanYe = nullptr; + bool YiZhu = true; + bool DOGLIVE = false; +}; + +bool yizhuCanYe(std::shared_ptr data, canyeParams* _detParams, sx_581_address address); +bool erzhuCanYe(std::shared_ptr data, canyeParams* _detParams, sx_581_address address); + +class _581_YiCiZhuYe_canye : public mission { +public: + _581_SX_Single_triggerTemplate< canyeParams> cam_1; + _581_SX_Single_triggerTemplate< canyeParams> cam_2; + _581_SX_Single_triggerTemplate< canyeParams> cam_3; + std::vector < canyeParams> canyeDetParams = std::vector < canyeParams>(3); + bool initOnce = false; + void onConfigReloaded() { + //HDevEngineCpp::HDevEngine myEngine; + //myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl"); + if (initOnce == false) { + for (auto¶m : canyeDetParams) { + if (param.DOGLIVE == false) + continue; + param.segDingWei = handdleAI::CreateSegObjS("./handleaiModels/canye/pSeg_DingWei.BHD", 16, 0); + param.segDanYe = handdleAI::CreateSegObjS("./handleaiModels/canye/pSeg_CanYe.BHD", 16, 0); + param.clsCanYe = handdleAI::CreateClsObjV3("./handleaiModels/canye/pCls_CanYe.BHD", 0, 1); + } + initOnce = true; + } + } + bool initCustom() { +#pragma region 注册触发器回调 + + cam_1.init("Camera1", "残液检测-相机1", { { 1900, 1,1800,"1910","1920"} }, 1, &canyeDetParams[0], _serviceManager, bridge, yizhuCanYe); + cam_2.init("Camera2", "残液检测-相机2", { { 1901, 1,1830,"1911","1921"} }, 1, &canyeDetParams[1], _serviceManager, bridge, yizhuCanYe); + cam_3.init("Camera3", "残液检测-相机3", { { 1902, 1,1850,"1912","1922"} }, 1, &canyeDetParams[2], _serviceManager, bridge, yizhuCanYe); + +#pragma endregion + return true; + } +}; + + + + + +#pragma once \ No newline at end of file diff --git a/src/mission/581_YiCiZhuYe_canye/CMakeLists.txt b/src/mission/581_YiCiZhuYe_canye/CMakeLists.txt new file mode 100644 index 0000000..af9bb43 --- /dev/null +++ b/src/mission/581_YiCiZhuYe_canye/CMakeLists.txt @@ -0,0 +1,77 @@ +# 获取获取当前目录名 +get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) +string(TIMESTAMP RUN_TIME) +message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) + +set(DLL_NAMES "opencv" "halcon" "handdleAI") +foreach(child ${DLL_NAMES}) + LIST(APPEND ENV_INCLUDE ${${child}_include}) + LIST(APPEND ENV_LIB ${${child}_lib}) + LIST(APPEND ENV_TARGET ${${child}_target_link}) +endforeach() +message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) +message(" ENV_LIB : " ${ENV_LIB} ) +message(" ENV_TARGET : " ${ENV_TARGET} ) +include_directories( + ${PROJECT_ROOT_PATH}/src/core + ${PROJECT_ROOT_PATH}/src/core/handleAi + ${PROJECT_ROOT_PATH}/src/core/back + ${PROJECT_ROOT_PATH}/src/core/sql + ${ENV_INCLUDE} + ) + +link_directories ( + ${ENV_LIB} + + ) +add_compile_options(/utf-8) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +FILE(GLOB HEAD_FILES "*.h" ) +FILE(GLOB SRC_FILES "./*.cpp") +FILE(GLOB UI_FILES "./*.ui") + + +#find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network Sql REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Sql REQUIRED) + +add_library(${CURRENT_FOLDER} SHARED + ${HEAD_FILES} + ${SRC_FILES} + ${UI_FILES} + ${PROJECT_ROOT_PATH}/include/qtBridge.h) + + + +set_target_properties(${CURRENT_FOLDER} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + ) + + +target_link_libraries(${CURRENT_FOLDER} PRIVATE + ${ENV_TARGET} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Gui + Qt${QT_VERSION_MAJOR}::Network + Qt${QT_VERSION_MAJOR}::Sql + ) + + +# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) + + + + +string(TIMESTAMP RUN_TIME) +message( " modelx end : " ${CURRENT_FOLDER}:${RUN_TIME}) +message( " header files "${HEAD_FILES})