diff --git a/AlgorithmModule/include/CheckUtil.hpp b/AlgorithmModule/include/CheckUtil.hpp index deaf02a..56a334c 100644 --- a/AlgorithmModule/include/CheckUtil.hpp +++ b/AlgorithmModule/include/CheckUtil.hpp @@ -33,6 +33,10 @@ public: static std::string getCurTimeHMS(); static std::string Op_float2String(float nvalue); static int64_t getSnowId(); + // 当前日期(年月日, 8 位纯数字), 形如 "20261029", 便于存图文件名检索/排序 + static std::string getCurrentDateYMD(); + // 生成不重名的存图完整路径 = strDir + strPrefix + [ "_序号" ] + "_" + strName + strExt + static std::string GetUniqueImgPath(const std::string &strDir, const std::string &strPrefix, const std::string &strName, const std::string &strExt); static bool JudgRect(cv::Rect roi, int img_w, int img_h); static bool JudgRect_SZ(cv::Rect roi, int w, int h); static bool compareIgnoreCase(const std::string &str1, const std::string &str2); diff --git a/AlgorithmModule/src/AI_Edge_Algin.cpp b/AlgorithmModule/src/AI_Edge_Algin.cpp index 35cf600..85f168d 100644 --- a/AlgorithmModule/src/AI_Edge_Algin.cpp +++ b/AlgorithmModule/src/AI_Edge_Algin.cpp @@ -386,10 +386,11 @@ int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDe if (pDetConfig->pBaseCheckFunction->saveImg.bSaveAlginImg) { - std::string cur_time_s = CheckUtil::getCurTimeHMS(); - std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + pDetConfig->strProductID + "/"; - CheckUtil::CreateDir(strSaveDir); - std::string strSavePath_out = strSaveDir + cur_time_s + "_" + pDetConfig->strChannel + "_" + std::to_string(AIModel_type) + "_Align_out.png"; + // 前缀用日期(年月日): 同一产品当天的所有图前缀一致; 文件已存在时在日期后追加序号, 不覆盖旧图 + std::string strDatePre = CheckUtil::getCurrentDateYMD(); + std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + pDetConfig->strProductID + "/KK/"; + std::string strName = pDetConfig->strChannel + "_" + std::to_string(AIModel_type) + "_Align_out"; + std::string strSavePath_out = CheckUtil::GetUniqueImgPath(strSaveDir, strDatePre, strName, ".png"); CheckUtil::SaveImgAsync(strSavePath_out, mask); } diff --git a/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp b/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp index a4f9e52..c91c9d6 100644 --- a/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp +++ b/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp @@ -691,7 +691,7 @@ int ALLImgCheckAnalysisy::PushInImg_New(std::shared_ptr p) // 对传入图片做一步判断,如果高大于宽,则顺时针旋转90° if (p->Det_Mode != DET_MODE_ReJson) { - if (!p->img.empty() && p->img.rows > p->img.cols) + if (!p->img.empty()) { cv::Mat imgRot; cv::rotate(p->img, imgRot, cv::ROTATE_90_CLOCKWISE); @@ -700,7 +700,7 @@ int ALLImgCheckAnalysisy::PushInImg_New(std::shared_ptr p) p->img.cols, p->img.rows, imgRot.cols, imgRot.rows); p->img = imgRot; } - if (!p->img_B.empty() && p->img_B.rows > p->img_B.cols) + if (!p->img_B.empty()) { cv::Mat imgBRot; cv::rotate(p->img_B, imgBRot, cv::ROTATE_90_CLOCKWISE); diff --git a/AlgorithmModule/src/CheckUtil.cpp b/AlgorithmModule/src/CheckUtil.cpp index f1a38a9..e2d3060 100644 --- a/AlgorithmModule/src/CheckUtil.cpp +++ b/AlgorithmModule/src/CheckUtil.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "snowflake.hpp" int _sysmkdir_2(const std::string &dir) @@ -80,6 +81,25 @@ std::string CheckUtil::getCurrentDate() return oss.str(); // 返回日期字符串 } +std::string CheckUtil::getCurrentDateYMD() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + time_t raw_time = tv.tv_sec; + // localtime_r 为线程安全版本 + struct tm time_buf; + struct tm *time_info = localtime_r(&raw_time, &time_buf); + + // 固定 8 位 "YYYYMMDD", 便于文件名检索与排序 + std::ostringstream oss; + oss << std::setfill('0') + << std::setw(4) << (time_info->tm_year + 1900) + << std::setw(2) << (time_info->tm_mon + 1) + << std::setw(2) << time_info->tm_mday; + + return oss.str(); +} std::string CheckUtil::getCurTimeHMS() { struct timeval tv; @@ -122,6 +142,40 @@ int64_t CheckUtil::getSnowId() return 0; } +std::string CheckUtil::GetUniqueImgPath(const std::string &strDir, const std::string &strPrefix, const std::string &strName, const std::string &strExt) +{ + if (strDir.empty()) + { + return strDir + strPrefix + strName + strExt; + } + // 目录不存在时 O_CREAT 会失败, 先建目录(已存在时内部无副作用) + CreateDir(strDir); + + // 去重序号插在前缀之后: <年月日>[_序号]_<通道>_<用途>.png + // 同一产品的每个 strName 每轮只会写一次, 所以各文件序号天然同步: + // 第 1 轮 -> <年月日>_<名称>.png、第 2 轮 -> <年月日>_1_<名称>.png、第 3 轮 -> <年月日>_2_<名称>.png ... + const std::string strHead = strPrefix.empty() ? std::string("") : (strPrefix + "_"); + for (int i = 0; i < 100000; i++) + { + std::string strPath = strDir + strHead + (i == 0 ? std::string("") : std::to_string(i) + "_") + strName + strExt; + // O_EXCL: 文件不存在才能创建成功, 即是"原子占位", 并发安全 + int fd = ::open(strPath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd >= 0) + { + ::close(fd); + return strPath; + } + if (errno != EEXIST) + { + // 非"已存在"类错误(权限/路径等)不再重试, 直接返回让 imwrite 把错误暴露出来 + printf("create img file[%s] error: %d %s\n", strPath.c_str(), errno, strerror(errno)); + return strPath; + } + } + // 序号用尽的兜底(实际不会发生) + return strDir + strHead + std::to_string(CheckUtil::getcurTime()) + "_" + strName + strExt; +} + bool CheckUtil::JudgRect(cv::Rect roi, int img_w, int img_h) { if (img_w <= 0 || img_h <= 0) diff --git a/AlgorithmModule/src/ImgCheckAnalysisy.cpp b/AlgorithmModule/src/ImgCheckAnalysisy.cpp index 06cf79e..bdb5452 100644 --- a/AlgorithmModule/src/ImgCheckAnalysisy.cpp +++ b/AlgorithmModule/src/ImgCheckAnalysisy.cpp @@ -1830,7 +1830,6 @@ int ImgCheckAnalysisy::ConfigCheck(cv::Mat img) int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg) { - std::string cur_time_s = CheckUtil::getCurTimeHMS(); // 依次使用多个检测模型,各模型输出 mask 取并集作为最终 outmask; // Defect_QueXi 模型是否参与合并由基础参数 Merge_QueXi 开关控制 std::vector> pAIDetList; @@ -1960,9 +1959,11 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg) // 目录结构:/home/aidlux/BOE/ZB_SOCKET/AI_Detect/<模型名称>/<产品ID>/ if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg && !modelMaskFull.empty()) { - std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + DetImgInfo_shareP->strImgProductID + "/"; - CheckUtil::CreateDir(strSaveDir); - std::string strSavePath_out = strSaveDir + cur_time_s + "_" + m_strCurDetChannel + "_" + strModelName + "_out.png"; + // 前缀用日期(年月日): 同一产品当天的所有图前缀一致; 文件已存在时在日期后追加序号, 不覆盖旧图 + std::string strDatePre = CheckUtil::getCurrentDateYMD(); + std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + DetImgInfo_shareP->strImgProductID + "/KK/"; + std::string strName = m_strCurDetChannel + "_" + strModelName + "_out"; + std::string strSavePath_out = CheckUtil::GetUniqueImgPath(strSaveDir, strDatePre, strName, ".png"); CheckUtil::SaveImgAsync(strSavePath_out, modelMaskFull); } @@ -2020,9 +2021,11 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg) if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg ) { - std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + DetImgInfo_shareP->strImgProductID + "/"; - CheckUtil::CreateDir(strSaveDir); - std::string strSavePath_in = strSaveDir + cur_time_s + "_" + m_strCurDetChannel + "_in.png"; + // 前缀用日期(年月日): 同一产品当天的所有图前缀一致; 文件已存在时在日期后追加序号, 不覆盖旧图 + std::string strDatePre = CheckUtil::getCurrentDateYMD(); + std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + DetImgInfo_shareP->strImgProductID + "/KK/"; + std::string strName = m_strCurDetChannel + "_in"; + std::string strSavePath_in = CheckUtil::GetUniqueImgPath(strSaveDir, strDatePre, strName, ".png"); CheckUtil::SaveImgAsync(strSavePath_in, m_CheckResult_shareP->cutSrcimg); } // 临时存图 diff --git a/AlgorithmModule/src/Pin_QX_Det.cpp b/AlgorithmModule/src/Pin_QX_Det.cpp index cea1a64..c33a0d0 100644 --- a/AlgorithmModule/src/Pin_QX_Det.cpp +++ b/AlgorithmModule/src/Pin_QX_Det.cpp @@ -49,10 +49,11 @@ int Pin_QX_Det::GetPinMask(const cv::Mat &img, DetConfigResult *pDetConfig, Mat // 输入图存未做通道转化(灰度化)之前的图; 文件名首位用产品ID if (pDetConfig->pBaseCheckFunction != NULL && pDetConfig->pBaseCheckFunction->saveImg.bSavePinImg) { - std::string cur_time_s = CheckUtil::getCurTimeHMS(); - std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + pDetConfig->strProductID + "/"; - CheckUtil::CreateDir(strSaveDir); - std::string strSavePath_out = strSaveDir + cur_time_s + "_" + pDetConfig->strChannel + "_pin_out.png"; + // 前缀用日期(年月日): 同一产品当天的所有图前缀一致; 文件已存在时在日期后追加序号, 不覆盖旧图 + std::string strDatePre = CheckUtil::getCurrentDateYMD(); + std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/" + pDetConfig->strProductID + "/KK/"; + std::string strName = pDetConfig->strChannel + "_pin_out"; + std::string strSavePath_out = CheckUtil::GetUniqueImgPath(strSaveDir, strDatePre, strName, ".png"); CheckUtil::SaveImgAsync(strSavePath_out, mask); }