修改存图格式。

修复因存图路径引起未能存到目标文件夹的bug。
修改了读条码为空的提示。
This commit is contained in:
2025-10-14 13:45:53 +08:00
parent 1b7451ba07
commit 64ba329946
5 changed files with 265 additions and 24 deletions
+18 -17
View File
@@ -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<imgSaveThreadType, QString> 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<std::pair<std::string, cv::Mat>>& jobQueue, std::vector<std::string> fileNames, std::vector<cv::Mat>& mats) {
void packageData(QQueue<std::pair<std::string, cv::Mat>>& jobQueue, std::string imgSavaPath, std::vector<std::string> fileNames, std::vector<cv::Mat>& 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<std::pair<std::string, cv::Mat>>& jobQueue, std::vector<std::string> fileNames, std::vector<std::pair<std::string, cv::Mat>>& mats) {
void packageData(QQueue<std::pair<std::string, cv::Mat>>& jobQueue, std::string imgSavaPath, std::vector<std::string> fileNames, std::vector<std::pair<std::string, cv::Mat>>& 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::vector<std::string>fileNames = genFileNames(data, oriImg);//按规则为文件创建命名
std::shared_ptr<saveJob> job (new saveJob("[ORI_JOB]+ data->SNcode"));
packageData(job->imgQueue, fileNames, data->oriImgs);//打包数据
std::shared_ptr<saveJob> 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::vector<std::string>fileNames = 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::vector<std::string>fileNames = 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::vector<std::string>fileNames = genFileNames(data, clsImg);//按规则为文件创建命名
packageData(job->imgQueue, fileNames, data->clsOriginImgs);//打包数据
packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(), fileNames, data->clsOriginImgs);//打包数据
}
saveThread.addJob(job, imgSaveThread::priority);
//额外储存NG文件夹
+6 -7
View File
@@ -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) {
@@ -0,0 +1,106 @@
#include <581_YiCiZhuYe_canye.h>
void exceptionResume(std::shared_ptr<detData> 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<detData> 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<detData> 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;
}
@@ -0,0 +1,58 @@
#include <missionBase.hpp>
#include <sxGlobal.h>
#pragma region 算法
#include <simpleAlgo.h>
#include <hdevengine/HDevEngineCpp.h>
#include <opencvPaintAlgo.hpp>
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 <detData> data, canyeParams* _detParams, sx_581_address address);
bool erzhuCanYe(std::shared_ptr <detData> 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&param : 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
@@ -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})