#ifndef _deal_HPP_ #define _deal_HPP_ #include #include #include #include #include #include #include #include #include #include "SystemCommonDefine.h" #include "ImgCheckBase.h" #include "ImgCheckConfig.h" #include "ConfigBase.h" #include #include #include #include "Image_ReadAndChange.h" #include #include "Read_Image.h" #include "LoadImage.hpp" namespace fs = std::filesystem; // ============ 产品检测线程配置 ============ #define READ_PRODUCT_THREAD_NUM 8 // 读图线程数 #define PRODUCT_QUEUE_MAX_SIZE 30 // 任务队列最大长度 enum Thread_Status_ { Thread_Status_IDE, Thread_Status_READY, Thread_Status_BUSY, Thread_Status_COMMPLET, }; enum Thread_ReadImg_Status_ { ReadImg_Status_IDE, ReadImg_Status_Read, ReadImg_Status_COMMPLET, }; // 各种线程处理状态信息 enum DET_Status_Type_ { Status_Type_ReadAndDet, // 读取图和处理 Status_Type_PullPath, // 读取图片路径 Status_Type_Count, }; enum Mutex_Type_ { Mutex_Type_ReadImgThread, // 读图线程 Mutex_Type_DetStatus, Mutex_Type_DetResult, Mutex_Type_Count, }; // 读线程,处理类型。 enum READ_THREAD_TYPE_ { READ_THREAD_TYPE_NULL, READ_THREAD_TYPE_READIMG, // 读图 READ_THREAD_Detect, // 检测模式 READ_THREAD_TYPE_COUNT, }; // 线程运行模式 enum THREAD_RUN_TYPE { THREAD_RUN_Only_ReadImg, // 仅读图 THREAD_RUN_ALL, // 所有 }; #define READ_IMG_THREAD_NUM 4 #define Save_IMG_THREAD_NUM 4 // ============ 产品检测任务结构体 ============ struct ReadImgTask { std::string productId; std::string channelName; std::string imageName; // 图片名称(不含路径) std::string left_path; // 左图路径 std::string right_path; // 右图路径 int camera_Num; int taskIndex; std::string cameraSide; // 相机方位:"left" | "right" | "merge" ReadImgTask() : taskIndex(0), camera_Num(0), cameraSide("") {} }; struct FailedImgRecord { std::string left_path; std::string right_path; std::string productId; std::string channelName; std::string errorReason; FailedImgRecord() {} }; // 图片检测通知信息 struct CheckImgNotifyInfo { int taskIndex; std::string productId; std::string channelName; std::string imageName; std::string left_path; std::string right_path; int width; int height; long readTimeMs; bool success; std::string errorReason; // 失败原因 cv::Mat left_img; // 左图数据 cv::Mat right_img; // 右图数据 int camera_Num; // 新增字段 std::string cameraSide; // 相机方位:"left" | "right" | "merge" CheckImgNotifyInfo() : taskIndex(0), width(0), height(0), readTimeMs(0), success(false), camera_Num(0), cameraSide("") {} }; using namespace std; enum RUNTYPE_ { RUNTYPE_RUN_Pre, RUNTYPE_RUN_File, RUNTYPE_RUN_File_AI_TEST, RUNTYPE_RUN_File_Edge_Test_Save_Qx, RUNTYPE_RUN_File_Edge_Test_Save_ALL, }; // 程序运行模式 enum Process_Run_Type { Process_Run_Detect, // 正常检测模式 Process_Run_ReJson, // 复测模式 Process_Run_SaveImg, // 解密图片并存图 }; struct JC_IMAGE_INFO_ { enum Status_ { STATUS_Image_IDE, STATUS_Image_READ, STATUS_Image_COMMPLET, STATUS_Det_Start, }; std::string strProductID; // 产品ID std::string strCamID; // 相机名称 std::string strchannelName; // 通道名称 std::string strPath; // 完整路径 std::string strName; // 图片名称 cv::Mat img; // 图像数据 Status_ status; // 状态 long readImg_start; // 读取开始时间 long readImg_end; // 读取结束时间 // 构造函数,调用 Init 初始化 JC_IMAGE_INFO_() { Init(); } // 初始化函数,重置所有成员变量 void Init() { strProductID = ""; strCamID = ""; strchannelName = ""; strPath = ""; strName = ""; img.release(); // 释放图像内存 status = STATUS_Image_IDE; readImg_start = 0; readImg_end = 0; } // 拷贝函数,将传入的结构体内容复制到当前对象 void copy(JC_IMAGE_INFO_ tem) { this->strProductID = tem.strProductID; this->strCamID = tem.strCamID; this->strchannelName = tem.strchannelName; this->strPath = tem.strPath; this->strName = tem.strName; if (!tem.img.empty()) { this->img = tem.img.clone(); // 深拷贝图像数据 } this->status = tem.status; this->readImg_start = tem.readImg_start; this->readImg_end = tem.readImg_end; } // 打印信息函数(可选) void print() { std::cout << "Product ID: " << strProductID << std::endl; std::cout << "Camera ID: " << strCamID << std::endl; std::cout << "Channel Name: " << strchannelName << std::endl; std::cout << "Image Path: " << strPath << std::endl; std::cout << "Image Name: " << strName << std::endl; std::cout << "Status: " << status << std::endl; std::cout << "Read Start Time: " << readImg_start << std::endl; std::cout << "Read End Time: " << readImg_end << std::endl; } }; struct Det_single_img_Result_Info { int result; std::string name; std::string qx_name; Det_single_img_Result_Info() { Init(); } void Init() { name = ""; result = 0; qx_name = "NO"; } }; struct Det_One_Result_Info { int result; long time_s; long time_e; std::string Product_ID; std::vector img_result_list; Det_One_Result_Info() { Init(); } void Init() { Product_ID = ""; time_s = 0; time_e = 0; result = 0; img_result_list.erase(img_result_list.begin(), img_result_list.end()); img_result_list.clear(); } std::string print() { std::string str = ""; // printf("%s:result %d | ", Product_ID.c_str(), result); char buffer[64]; sprintf(buffer, "%s:result %d time %ld | ", Product_ID.c_str(), result, time_e - time_s); std::string st1 = buffer; str += st1; for (size_t i = 0; i < img_result_list.size(); i++) { str += img_result_list.at(i).name + " " + img_result_list.at(i).qx_name + " | "; } // str += str; return str; // printf("%s\n", str.c_str()); } }; struct Det_File_qx_Info { std::string qx_name; int num; Det_File_qx_Info() { Init(); } void Init() { qx_name = ""; num = 0; } }; // 套图检测 统计结果信息 struct Det_File_Result_Info { int det_num_all; int det_num_ok; int det_num_ng; int det_num_error; float sumtime_S; long startTime_S; float mean_time; std::vector one_result_list; std::vector strlist; std::vector qx_result_list; Det_File_Result_Info() { Init(); } void Init() { det_num_all = 0; det_num_ok = 0; det_num_ng = 0; det_num_error = 0; sumtime_S = 0; startTime_S = 0; mean_time = 0; one_result_list.erase(one_result_list.begin(), one_result_list.end()); one_result_list.clear(); strlist.erase(strlist.begin(), strlist.end()); strlist.clear(); qx_result_list.erase(qx_result_list.begin(), qx_result_list.end()); qx_result_list.clear(); } void updata(std::string productid, std::string imgname, int nresult, long t) { sumtime_S = t - startTime_S; sumtime_S /= 1000; if (det_num_all > 0) { mean_time = sumtime_S / det_num_all; } for (int i = 0; i < one_result_list.size(); i++) { if (one_result_list.at(i).Product_ID == productid) { // if (one_result_list.at(i).result < 0) // { // one_result_list.at(i).result = 0; // } one_result_list.at(i).time_e = t; for (size_t j = 0; j < one_result_list.at(i).img_result_list.size(); j++) { if (one_result_list.at(i).img_result_list.at(j).name == imgname) { one_result_list.at(i).img_result_list.at(j).result = nresult; if (nresult == 0) { one_result_list.at(i).img_result_list.at(j).qx_name = "OK"; } else if (nresult > 0) { one_result_list.at(i).img_result_list.at(j).qx_name = "NG"; if (one_result_list.at(i).result == 0) { one_result_list.at(i).result = 1; } } else { one_result_list.at(i).img_result_list.at(j).qx_name = "ER"; one_result_list.at(i).result = -1; } } } } } } void update_qx(std::string qx_name, int num) { for (int i = 0; i < qx_result_list.size(); i++) { if (qx_result_list.at(i).qx_name == qx_name) { qx_result_list.at(i).num += num; return; } } Det_File_qx_Info tem; tem.qx_name = qx_name; tem.num = num; qx_result_list.push_back(tem); } void print(bool show = true) { strlist.erase(strlist.begin(), strlist.end()); strlist.clear(); det_num_ok = 0; det_num_ng = 0; det_num_error = 0; std::string str = ""; str = "*****************************************************************************"; strlist.push_back(str); str = "*****************************detect result***********************************"; strlist.push_back(str); float fok = 0; float fng = 0; float ferror = 0; // printf("one_result_list.size() %d \n", one_result_list.size()); for (int i = 0; i < one_result_list.size(); i++) { if (one_result_list.at(i).result == 0) { det_num_ok++; } else if (one_result_list.at(i).result > 0) { det_num_ng++; } else { det_num_error++; } } if (det_num_all > 0) { fok = det_num_ok * 1.0f / det_num_all * 100; fng = det_num_ng * 1.0f / det_num_all * 100; ferror = det_num_error * 1.0f / det_num_all * 100; } char buffer[64]; sprintf(buffer, "ALL:%d OK:%d %.1f%% NG:%d %.1f%% Error:%d %.1f%%", det_num_all, det_num_ok, fok, det_num_ng, fng, det_num_error, ferror); std::string st1 = buffer; strlist.push_back(st1); sprintf(buffer, "Use time %f s mean time %f s", sumtime_S, mean_time); std::string st2 = buffer; strlist.push_back(st2); // printf("%s\n", st1.c_str()); // printf("------------------------------------------------------------------------------\n"); str = "------------------------------------------------------------------------------"; strlist.push_back(str); { int qx_all_num = 0; for (size_t i = 0; i < qx_result_list.size(); i++) { qx_all_num += qx_result_list.at(i).num; } for (size_t i = 0; i < qx_result_list.size(); i++) { float fr = qx_result_list.at(i).num * 1.0 / qx_all_num * 100; std::string str_qx = ""; // printf("len %d \n", qx_result_list.at(i).qx_name.length()); for (int k = 0; k < (20 - qx_result_list.at(i).qx_name.length()); k++) { str_qx += " "; } str_qx += qx_result_list.at(i).qx_name; char buffer123[64]; sprintf(buffer123, ":%d %.1f%% ", qx_result_list.at(i).num, fr); std::string st1 = buffer123; str_qx += st1; int nlen = fr; for (int j = 0; j < nlen; j++) { str_qx += "|"; } strlist.push_back(str_qx); } } str = "------------------------------------------------------------------------------"; strlist.push_back(str); for (int i = 0; i < one_result_list.size(); i++) { st1 = one_result_list.at(i).print(); strlist.push_back(st1); } str = "*****************************************************************************"; strlist.push_back(str); // printf("*****************************************************************************\n"); if (show) { for (size_t i = 0; i < strlist.size(); i++) { printf("%s\n", strlist.at(i).c_str()); } } } }; struct IMG_BASE_INFO_ { std::string strPath; std::string strChannel; std::string strImgSN; IMG_BASE_INFO_() { strPath = ""; strImgSN = ""; strChannel = ""; } }; struct ReadImgInfo { std::string strPath; std::string strChannel; int stype; int status; std::string strImgSN; int idx; int sumNUm; cv::Rect cutRoi; std::vector imglist; ReadImgInfo() { strPath = ""; strImgSN = ""; stype = 0; status = 0; idx = 0; imglist.clear(); cutRoi = cv::Rect(0, 0, 0, 0); sumNUm = 0; } }; struct AI_Det_Path { std::string strPath_CutImg; std::string strPath_AIMask; /* data */ }; struct AI_Det_Channel_ { std::string strChannel; AI_Det_Path path; /* data */ }; struct Json_Det_Path { std::string strPath_CutImg; std::string strPath_Json; /* data */ }; struct READ_IMG_INFO { std::string strpath = ""; std::string strproduct = ""; }; struct DealRunConfig { Process_Run_Type run_Type = Process_Run_Detect; // 运行模式 RUNTYPE_ det_Type = RUNTYPE_RUN_Pre; // 处理 std::string filePath = ""; // 处理文件路径 如果为空 处理当前的单张图片 bool bDebugSaveImg = false; // 是否中间图片图片 int m_nTestNum = 999999; void print(std::string str) { printf(">>>>>>>>>>>>>>> %s <<<<<<<<<<<<\n", str.c_str()); printf("run_Type %d det_Type %d file %s bsave %d \n", run_Type, det_Type, filePath.c_str(), bDebugSaveImg); } }; class deal { public: // 构造函数 deal(); ~deal(); int start(); private: // 初始化 int Init(); // 检测参数 int LoadCheckImgConfig(); // 初始化检测分析线程类 int InitCheckAnalysisy(); int InitConfig(); // 初始化 检查存图路径 int InitSaveImgPath(); int LoadCheckConfig(); // 分析参数 int LoadAnalysisConfig(); // 开启线程 int StartThread(THREAD_RUN_TYPE type); // 停止线程 int StopThread(); int preCheck(); std::string readTestImg(); int readTestImg(READ_IMG_INFO &read); // 重复检测 int repeatCheck(); int saveImg(std::string strpath, std::shared_ptr result); int writeLog(std::string strSavePath, std::vector logList); int WriteJsonString(std::string strSavePath, std::string strjson); // 获取图片路径 int GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector &jcImageInfoList); // 解析图片的信息 -- cell et int GetImgInfo_POL_ET(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo); int GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo); // 随机绘制错误 int RandDrawImg(cv::Mat srcimg, cv::Mat &randErrorImg); int LoadOfflineCheckImg(std::string strImgPath); int LoadImgPath_JCSN(std::string strImgPath); bool isValidString(const std::string &str); int LoadProductID(std::string strImgPath); int set_cpu_id(const std::vector &cpu_set_vec); void GetDealResultToQueu(); // 加载系统配置文件 bool ReadSystemConfig(const std::string &strPath); int GetJcImageInfo(std::string strpath, std::vector &jcImageInfoList); int ReadTestImgaData(); // 处理前,初始化部分数据 int InitDetData(); // 检测结果 插入结果队列 int InsertDetResult(ReadImgInfo tem); int GetUpMaskImg(cv::Mat inImg, cv::Rect roi, cv::Mat &maskimg); int ReJson(); int ReJson_ALL(); int DetImg(); // 套图复测 int ReJson_product(std::vector &jsonList, std::string strProductName); // 套图复测 int CheckFileImg(); ///< 检查文件图片(新增) int CheckProduct(const LoadProductImages &product); ///< 检查单个产品(新增) int SendCheckImg(const CheckImgNotifyInfo &info, IN_IMG_Status_ status, bool bComplete = false); // 处理图片 // ============ 产品检测线程池相关 ============ void ProductReadImgThreadFunc(int threadId); std::shared_ptr GetProductTask(); void DistributeProductTasks(const LoadProductImages &product); void RecordFailedImg(const FailedImgRecord &record); void PrintProductStatistics(const LoadProductImages &product); // ============ 线程池生命周期管理 ============ void InitProductReadThreadPool(); ///< 初始化线程池(构造时调用) void DestroyProductReadThreadPool(); ///< 销毁线程池(析构时调用) private: // 处理调度线程 std::shared_ptr ptr_DealImgthread; void DealImg(); std::vector extractAllDirectories(const std::string &path); // 结果处理线程 // std::shared_ptr ptr_Resultthread; std::vector> ptr_ResultthreadList; void ResultThread(int id); // 结果拷贝线程 std::shared_ptr ptr_GetResultthread; void GetResultThread(); std::vector> threadArray; void ReadImgThread(int id); void testimg(cv::Mat img); int updataResltInfo(std::shared_ptr result); void slidingWindowAutoThreshold(const cv::Mat &src, cv::Mat &dst, int windowSize, int step, double C); int SetStatus(int type, int status); int GetStatus(int type); bool IsStatus(int type, int status); int SetStatus_List(int idx, Thread_Status_ status); int GetStatus_List(int idx); bool IsStatus_List(int idx, Thread_Status_ status); int setReadThreadStart(); int GetReadImgCompleteThreadIdx(); // 获取读取完成后的idx bool IsALLComplete(); int InitCPUIDX(); // 线程读图 void Thread_ReadImg(int id); int InsertReadImgInfo(std::shared_ptr pImageInfo); int GetReadImgInfo(std::shared_ptr &pImageInfo); public: std::vector m_OffLineCheckImgList; // 离线检测图片列表 std::vector m_OffLineCheckImgNameList; // 离线检测图片列表 std::vector m_OffImageSNPathList; // 离线检测图片列表 std::vector m_product_ID_List; // 离线检测图片列表 ALLImgCheckBase *m_pALLImgCheckAnalysisy; std::vector m_TestJC_ImageDate; // 离线检测图片列表 std::string m_strCurDate; int m_nSystemCheckType; bool m_bExit; int nLastCheckAnalysisyThreadIdx; RunInfoST m_RunConfig; // 检测基本参数 std::mutex mutex_Result_list; std::queue> m_Result_list; // 检测区域list std::vector m_DetRoiMaskPointList; // 检测区域list std::vector m_CoreMaskPointList; DealRunConfig runConfig; int m_nTestNum; std::string m_strSaveImgPath; ConfigManagerBase *m_pConfigManager = NULL; SystemConfigParam m_system_param; int m_nCurUseCPUIDX; int m_nCamIdx; ImageInfo m_ImgInfo_src; ImageInfo m_ImgInfo_result; cv::Rect m_CutRoi; int nn; int nddd; int kkd; int maxidx; Det_File_Result_Info m_DetResult; std::vector m_ImageInfoList; std::queue> m_ReadImg_queue; // 读图队列 std::mutex mutex_ReadImgList; std::condition_variable cv_ReadImgList; int m_nReadStausList[READ_IMG_THREAD_NUM]; // 读图线程状态 std::shared_ptr m_ReadImgThread_Result[READ_IMG_THREAD_NUM]; READ_THREAD_TYPE_ m_nReadThread_type; bool m_nreadImg_Stop; std::mutex mutex_DetResult_; std::queue m_DetImgQueue; // 存储生产者生产的数据 std::mutex mtx_DetImgQueue; // 互斥量,保护共享资源 std::mutex mtx_DetImgQueue_edge; // 互斥量,保护共享资源 std::condition_variable cv; // 条件变量,用于线程间通信 std::mutex mtx_DetImgQueue_com; // int m_read_ImgNum; long m_readImgStarttime; int m_DetStatusList[Status_Type_Count]; // 各种需要线程同步的状态信息 std::mutex mtx_List[Mutex_Type_Count]; // 互斥量 std::vector m_DetResultList; CPU_ID_INFO_ m_CPUInfo[THREAD_CPU_Count]; Image_ReadChannel m_image_ReadChannel; Process_Run_Type m_processRunType = Process_Run_Detect; // 程序运行模式 // ============ 产品检测线程池相关成员 ============ std::vector> m_productReadThreads; // 读图线程池 std::queue> m_productTaskQueue; // 任务队列 std::mutex m_productTaskMutex; std::condition_variable m_productTaskCV; std::atomic m_bProductReadExit{false}; // 退出标志 std::atomic m_nProductPendingTasks{0}; // 待处理任务数 std::atomic m_nProductSuccessCount{0}; // 成功数量 std::atomic m_nProductFailCount{0}; // 失败数量 std::vector m_ProductFailedList; std::mutex m_productFailedMutex; int m_nProductReadThreadNum; // 读图线程数 int m_nProductQueueMaxSize; // 队列最大长度 // ============ 图片检测通知相关 ============ std::queue m_checkNotifyQueue; // 通知队列 std::mutex m_checkNotifyMutex; // 通知队列锁 std::condition_variable m_checkNotifyCV; // 通知条件变量 std::atomic m_nCheckNotifiedCount{0}; // 已通知数量 }; #endif //_CORELOGICFACTORY_HPP_