diff --git a/AlgorithmModule/include/DetLog.h b/AlgorithmModule/include/DetLog.h index dacd356..8c900a7 100644 --- a/AlgorithmModule/include/DetLog.h +++ b/AlgorithmModule/include/DetLog.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "ImgCheckConfig.h" #include "CheckErrorCodeDefine.hpp" using namespace std; @@ -62,17 +63,29 @@ struct DetLog bool bPrintStr; // 是否打印日志 int addLogLevel; + // 保护 logList:同一个 DetLog(如图片结果的日志)会被实例主线程(Run/CheckRun) + // 与任务线程(AI 推理/分类) 并发写入,无锁 push_back 会造成 vector 堆破坏。 + std::mutex mtx_log; + DetLog() { Init(); } void Init() { + std::lock_guard lock(mtx_log); logList.clear(); bPrintStr = false; addLogLevel = DET_LOG_LEVEL_3; } + // 线程安全地获取日志快照 + std::vector GetLogs() + { + std::lock_guard lock(mtx_log); + return logList; + } + template void AddCheckstr(PrintLevel_ step, std::string stepStr, const std::string &format, Args... args) { @@ -105,6 +118,7 @@ struct DetLog printf("%s\n", str.c_str()); } + std::lock_guard lock(mtx_log); logList.push_back(str); } template @@ -141,15 +155,19 @@ struct DetLog if (LogLevel <= addLogLevel) { + std::lock_guard lock(mtx_log); logList.push_back(str); } } void printLog(std::string str) { printf("===========================%s==============================\n", str.c_str()); - for (auto strl : logList) { - printf("%s\n", strl.c_str()); + std::lock_guard lock(mtx_log); + for (auto strl : logList) + { + printf("%s\n", strl.c_str()); + } } printf("==========================================================\n"); } diff --git a/AlgorithmModule/src/CameraCheckAnalysisy.cpp b/AlgorithmModule/src/CameraCheckAnalysisy.cpp index 2e6a7e6..bf9d470 100644 --- a/AlgorithmModule/src/CameraCheckAnalysisy.cpp +++ b/AlgorithmModule/src/CameraCheckAnalysisy.cpp @@ -789,7 +789,10 @@ int CameraCheckAnalysisy::CheckImgRun() if (m_pCheck_Result->getImgPushComplate()) { curcheckStep = Check_Step_Complete; // 进入到预图片检测阶段 - m_pCheck_Result->SetCheckStep(curcheckStep); + // 注意:这里先不发布 Check_Step_Complete。 + // 若提前发布,ALLImgCheckAnalysisy 线程会立刻把结果塞给 deal, + // 而本线程还在 InsertCameraLog() 里写 result->det_LogList,两边并发(读/写)竞争。 + // 因此把 SetCheckStep(Check_Step_Complete) 挪到 InsertCameraLog() 之后。 } else { @@ -806,6 +809,8 @@ int CameraCheckAnalysisy::CheckImgRun() m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "========came %s Check ALL end time %ld ms %s", m_pCheck_Result->cameraBaseResult->strCameraName.c_str(), tend - m_pCheck_Result->time_start, strTimg.c_str()); InsertCameraLog(); + // 日志拼接完成后再发布“检测完成”,避免 deal 提前读到正在写入的 det_LogList + m_pCheck_Result->SetCheckStep(Check_Step_Complete); std::lock_guard lock(mtx_WaiteImg); m_bHaveImgeDet = false; @@ -850,8 +855,12 @@ int CameraCheckAnalysisy::InsertCameraLog() } // 1、把图片的相关日志 写到 返回 日志中。 - m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), - pImageResult->detlog->logList.begin(), pImageResult->detlog->logList.end()); + // 注意:DetLog 可能仍被实例线程写入,使用 GetLogs() 做加锁快照,避免并发遍历。 + { + std::vector imgLogs = pImageResult->detlog->GetLogs(); + m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), + imgLogs.begin(), imgLogs.end()); + } std::string str = ""; char buffer[256]; // 2、把缺陷信息 写的 返回日志中。 @@ -882,8 +891,9 @@ int CameraCheckAnalysisy::InsertCameraLog() if (QX_info->result == QX_RESULT_TYPE_NG) { std::shared_ptr pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog; + std::vector qxLogs = pQxLog->GetLogs(); m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), - pQxLog->logList.begin(), pQxLog->logList.end()); + qxLogs.begin(), qxLogs.end()); } } @@ -899,8 +909,9 @@ int CameraCheckAnalysisy::InsertCameraLog() if (QX_info->result == QX_RESULT_TYPE_YS) { std::shared_ptr pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog; + std::vector qxLogs = pQxLog->GetLogs(); m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), - pQxLog->logList.begin(), pQxLog->logList.end()); + qxLogs.begin(), qxLogs.end()); } } @@ -916,8 +927,9 @@ int CameraCheckAnalysisy::InsertCameraLog() if (QX_info->result == QX_RESULT_TYPE_OK) { std::shared_ptr pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog; + std::vector qxLogs = pQxLog->GetLogs(); m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), - pQxLog->logList.begin(), pQxLog->logList.end()); + qxLogs.begin(), qxLogs.end()); } } @@ -933,8 +945,9 @@ int CameraCheckAnalysisy::InsertCameraLog() if (QX_info->result == QX_RESULT_TYPE_NoJduge) { std::shared_ptr pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog; + std::vector qxLogs = pQxLog->GetLogs(); m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), - pQxLog->logList.begin(), pQxLog->logList.end()); + qxLogs.begin(), qxLogs.end()); } } } @@ -946,8 +959,11 @@ int CameraCheckAnalysisy::InsertCameraLog() } // 3、把相机的日志 写到 返回日志中。 - m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), - m_pCheck_Result->detlog->logList.begin(), m_pCheck_Result->detlog->logList.end()); + { + std::vector camLogs = m_pCheck_Result->detlog->GetLogs(); + m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), + camLogs.begin(), camLogs.end()); + } { sprintf(buffer, " =====================Product Log ============================="); @@ -955,8 +971,11 @@ int CameraCheckAnalysisy::InsertCameraLog() m_CheckResult_shareP->det_LogList.push_back(str); } // 4、把产品相关日志 写到 返回日志中。 - m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), - m_pCheck_Result->productBaseResult->detlog->logList.begin(), m_pCheck_Result->productBaseResult->detlog->logList.end()); + { + std::vector productLogs = m_pCheck_Result->productBaseResult->detlog->GetLogs(); + m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(), + productLogs.begin(), productLogs.end()); + } } return 0; } diff --git a/AlgorithmModule/src/ImgCheckAnalysisy.cpp b/AlgorithmModule/src/ImgCheckAnalysisy.cpp index 4c95925..8cd319a 100644 --- a/AlgorithmModule/src/ImgCheckAnalysisy.cpp +++ b/AlgorithmModule/src/ImgCheckAnalysisy.cpp @@ -18,7 +18,7 @@ #define HANDLE_SIZE_MIN_RATIO 0.8f #define HANDLE_SIZE_MAX_RATIO 1.2f // "附近"的搜索范围:把手区域外接矩形在宽/高方向各外扩该比例 -#define HANDLE_NEAR_EXPAND_RATIO 0.5f +#define HANDLE_NEAR_EXPAND_RATIO 5 // 凸起填充率下限等参数的默认值在 Handle_Check_Param(CheckConfigDefine.h)里 // 用于排序轮廓的比较函数