#include "deal.h" #include "json/json.h" #include #include #include #include #include #include "CheckUtil.hpp" #include "LoadImage.hpp" // #include "LoadImage.h" std::string ExtractFileNameWithoutExtension(const std::string &strImgPath) { // 查找最后一个斜杠 '/' 或 '\' 的位置 size_t lastSlashPos = strImgPath.find_last_of("/\\"); // 如果没有找到斜杠,默认整个字符串是文件名 std::string fileName = (lastSlashPos == std::string::npos) ? strImgPath : strImgPath.substr(lastSlashPos + 1); // 查找最后一个点 '.' 的位置 size_t lastDotPos = fileName.find_last_of('.'); // 如果没有找到点号,或者点号在第一个字符的位置,则返回完整文件名 if (lastDotPos == std::string::npos || lastDotPos == 0) { return fileName; } // 返回去掉扩展名的部分 return fileName.substr(0, lastDotPos); } std::string GetFileName(const std::string &strImgPath) { // 查找最后一个斜杠 '/' 或 '\' 的位置 size_t lastSlashPos = strImgPath.find_last_of("/\\"); // 如果没有找到斜杠,默认整个字符串是文件名 std::string fileName = (lastSlashPos == std::string::npos) ? strImgPath : strImgPath.substr(lastSlashPos + 1); // 查找最后一个点 '.' 的位置 return fileName; } bool customSort(const AI_Det_Channel_ &a, const AI_Det_Channel_ &b) { // 特定规则排序: "a" 排第一, "b" 排第二, "L" 排最后 if (a.strChannel == "Up-Particle" && b.strChannel != "Up-Particle") { return true; // "a" 排在前面 } if (a.strChannel != "Up-Particle" && b.strChannel == "Up-Particle") { return false; } if (a.strChannel == "Down-Particle" && b.strChannel != "Down-Particle" && b.strChannel != "Up-Particle") { return true; // "b" 排第二 } if (a.strChannel != "Down-Particle" && b.strChannel == "Down-Particle") { return false; } if (a.strChannel == "L0" && b.strChannel != "L0" && b.strChannel != "Up-Particle" && b.strChannel != "Down-Particle") { return false; // "L" 排最后 } if (a.strChannel != "L0" && b.strChannel == "L0") { return true; } // 对其他情况使用字典顺序排序 return a.strChannel < b.strChannel; } // 定义图片读取函数 void readImage(const std::string &filename) { cv::Mat image = cv::imread(filename); if (image.empty()) { std::cerr << "Error: Unable to read image " << filename << std::endl; return; } // // 在这里可以添加对图像的处理操作 // // 例如:显示图像、保存图像、进行其他处理等 // // 示例:显示图像 // cv::imshow(filename, image); // cv::waitKey(0); // cv::destroyWindow(filename); } int _sysmkdir_1(const std::string &dir) { int ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (ret && errno == EEXIST) { // printf("dir[%s] already exist.\n", dir.c_str()); } else if (ret) { printf("create dir[%s] error: %d %s\n", dir.c_str(), ret, strerror(errno)); return -1; } else { printf("create dir[%s] success.\n", dir.c_str()); } return 0; } std::string __getParentDir_1(const std::string &dir) { std::string pdir = dir; if (pdir.length() < 1 || (pdir[0] != '/')) { return ""; } while (pdir.length() > 1 && (pdir[pdir.length() - 1] == '/')) pdir = pdir.substr(0, pdir.length() - 1); pdir = pdir.substr(0, pdir.find_last_of('/')); return pdir; } int _sysmkdirs_1(const std::string &dir) { int ret = 0; if (dir.empty()) return -1; std::string pdir; if ((ret = _sysmkdir_1(dir)) == -1) { pdir = __getParentDir_1(dir); if ((ret = _sysmkdirs_1(pdir)) == 0) { ret = _sysmkdirs_1(dir); } } return ret; } long getcurTime() { struct timeval tv; gettimeofday(&tv, NULL); return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000; } deal::deal() { nLastCheckAnalysisyThreadIdx = 0; m_nCamIdx = 0; m_nCurUseCPUIDX = 0; m_DetResult.Init(); for (int i = 0; i < READ_IMG_THREAD_NUM; i++) { m_nReadStausList[i] = ReadImg_Status_IDE; } m_nreadImg_Stop = false; m_strCurDate = ""; m_nReadThread_type = READ_THREAD_TYPE_NULL; for (int i = 0; i < Status_Type_Count; i++) { m_DetStatusList[i] = Thread_Status_IDE; } m_nTestNum = 9999999; m_pALLImgCheckAnalysisy = NULL; // ✅ 新增:初始化产品检测线程池 m_bProductReadExit = false; m_nProductReadThreadNum = READ_PRODUCT_THREAD_NUM; m_nProductQueueMaxSize = PRODUCT_QUEUE_MAX_SIZE; m_nCheckNotifiedCount = 0; } deal::~deal() { // ✅ 新增:销毁产品检测线程池 DestroyProductReadThreadPool(); } int deal::start() { std::string strdate = CheckUtil::getCurrentDate(); printf("===== %s\n", strdate.c_str()); int re = Init(); // getchar(); // 配置系统运行的cup核数。 if (re != 0) { return 1; } // 解析图片,并保存 if (Process_Run_SaveImg == runConfig.run_Type) { return 1; } else if (runConfig.run_Type == Process_Run_ReJson) { ReJson_ALL(); return 0; } else { DetImg(); } return 0; } int deal::Init() { InitCPUIDX(); // 读取系统配置文件 int re = ReadSystemConfig(FILE_SYSTEM_RUN_CONFIG); if (re == false) { printf("ReadSystemConfig error\n"); return 1; } // 加载 检测 的通道 图片名称 std::string strchannlePath = m_system_param.config_Root_Path + "surface_list.json"; m_image_ReadChannel.ReadJsonConfig(strchannlePath); // getchar(); if (Process_Run_SaveImg == runConfig.run_Type) { return 0; } // getchar(); // 初始化参数模块 InitConfig(); printf("\n\n\n\n\n\n\n\n\n\n\n**********************************************************LoadCheckImgConfig\n"); // 载入参数 re = LoadCheckImgConfig(); if (re != 0) { printf("read config error\n"); return 2; } printf("\n\n**********************************************************InitCheckAnalysisy\n"); // 初始化检测库 InitCheckAnalysisy(); printf("\n\n\n\n\n\n\n\n\n\n\n**********************************************************Check\n"); return 0; } int deal::LoadCheckImgConfig() { int re = LoadAnalysisConfig(); if (re != 0) { return re; } return 0; } int deal::InitCheckAnalysisy() { int re = 0; int m_nMAX_GPU_NUM = MAX_GPU_NUM; if (m_nMAX_GPU_NUM <= 0) { printf(">>>>error GPU error %d \n", m_nMAX_GPU_NUM); return 2; } int startidx = m_CPUInfo[THREAD_CPU_CheckSo].startIdx; int cpunum = m_CPUInfo[THREAD_CPU_CheckSo].num; m_RunConfig.nCpu_start_Idx = startidx; m_RunConfig.nCpu_num = cpunum; m_RunConfig.nWorkIdx = m_system_param.nWorkIdx; for (int i = 0; i < MAX_GPU_NUM; i++) { m_RunConfig.UseGPUList[i] = m_system_param.GPU_Device_ID_List[i]; printf("gpu %d %d\n", i, m_RunConfig.UseGPUList[i]); } m_pALLImgCheckAnalysisy = ALLImgCheckBase::GetInstance(); re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)&m_RunConfig, CHECK_CONFIG_Run); re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)m_pConfigManager, CHECK_CONFIG_Module); VERSION_INFO tm; tm.InterfaceVersion = ALL_INTERFACE_VERSION; tm.ConfigVersion = CONFIGBASE_VERSION; tm.ResultVersion = RESULT_VERSION; re = m_pALLImgCheckAnalysisy->RunStart(&tm); if (re != 0) { printf("RunStart Fail %d\n", re); return re; } printf(">>>> ImgCheckThread Start Succ \n"); return 0; } int deal::InitConfig() { m_pConfigManager = ConfigManagerBase::GetInstance(); return 0; } int deal::InitSaveImgPath() { return 0; } int deal::LoadCheckConfig() { return 0; } int deal::LoadAnalysisConfig() { if (!m_pConfigManager) { return 1; } std::string folder = m_system_param.config_Root_Path; int re = m_pConfigManager->LoadAnalysisConfig(folder); for (const auto &pair : m_pConfigManager->Config_instances_) { std::cout << "cam: " << pair.first << std::endl; } // getchar(); return re; } int deal::StartThread(THREAD_RUN_TYPE type) { m_bExit = false; // 只读图线程 if (type == THREAD_RUN_ALL) { // 开启检测线程 ptr_DealImgthread = std::make_shared(&deal::DealImg, this); // 结果处理线程 // ptr_Resultthread = std::make_shared(&deal::ResultThread, this); for (int i = 0; i < Save_IMG_THREAD_NUM; ++i) { // 创建线程,并使用 std::make_shared 创建 shared_ptr std::shared_ptr threadPtr = std::make_shared(&deal::ResultThread, this, i); // 将 shared_ptr 添加到 vector 中 ptr_ResultthreadList.push_back(threadPtr); } // 结果拷贝线程 ptr_GetResultthread = std::make_shared(&deal::GetResultThread, this); } InitProductReadThreadPool(); // for (int i = 0; i < READ_IMG_THREAD_NUM; ++i) // { // // 创建线程,并使用 std::make_shared 创建 shared_ptr // std::shared_ptr threadPtr = std::make_shared(&deal::ReadImgThread, this, i); // // 将 shared_ptr 添加到 vector 中 // threadArray.push_back(threadPtr); // } return 0; } int deal::StopThread() { return 0; } int deal::preCheck() { printf(">>> preCheck start \n"); std::string strRoot = "../data/img/t1"; std::string strProductID = ""; { READ_IMG_INFO read; readTestImg(read); strRoot = read.strpath; strProductID = read.strproduct; printf("strSearchImg strRoot %s\n", strRoot.c_str()); std::ifstream file123(strRoot); bool bhave = file123.good(); if (!bhave) { printf("read img path error %d %s\n", bhave, strRoot.c_str()); return 1; } } // 获取图片路径 std::string strSearchImg = strRoot; LoadImage loader; LoadConfig config; config.Init(); printf("开始加载图片...\n\n"); std::vector products = loader.LoadALLImg(strSearchImg, config, &m_image_ReadChannel, strProductID); if (products.empty()) { printf("未找到任何图片!\n"); printf("错误信息:%s\n", loader.getLastError().c_str()); return 1; } printf("加载完成!\n"); printf("产品数量:%zu\n", products.size()); printf("图片总数:%zu\n\n", loader.getTotalLoaded()); for (size_t i = 0; i < products.size(); i++) { products[i].print("产品" + std::to_string(i + 1)); } long t1 = getcurTime(); for (size_t i = 0; i < products.size(); i++) { CheckProduct(products[i]); // 处理单个产品 int getresultNum = 0; // getchar(); while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟消费过程 // 处理结果 std::shared_ptr checkResult; int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult); saveImg("/home/aidlux/BOE/FOG/testresult/", checkResult); getresultNum++; if (getresultNum == m_nProductSuccessCount) { break; } } } // } printf(">>> ALL preCheck complete \n"); return 0; } std::string deal::readTestImg() { std::string strRoot = "../data/img/TestImg.json"; printf("Reading Img config %s\n", strRoot.c_str()); Json::CharReaderBuilder builder; builder["collectComments"] = true; Json::Value root; std::string err; std::ifstream ifs(strRoot); if (!ifs.is_open()) { printf("error:file is open\n"); return ""; } if (!Json::parseFromStream(builder, ifs, &root, &err)) { printf("error:parseFromStream\n"); return ""; } std::string imgpath = ""; imgpath = root["TestImg_Path"].asString(); return imgpath; } int deal::readTestImg(READ_IMG_INFO &read) { std::string strRoot = "../data/img/TestImg.json"; printf("Reading Img config %s\n", strRoot.c_str()); Json::CharReaderBuilder builder; builder["collectComments"] = true; Json::Value root; std::string err; std::ifstream ifs(strRoot); if (!ifs.is_open()) { printf("error:file is open\n"); return 1; } if (!Json::parseFromStream(builder, ifs, &root, &err)) { printf("error:parseFromStream\n"); return 1; } std::string imgpath = ""; read.strpath = root["TestImg_Path"].asString(); read.strproduct = root["ProductID"].asString(); return 0; } int deal::repeatCheck() { return 0; } int deal::saveImg(std::string strpath, std::shared_ptr result) { std::string strroot = strpath; std::string strroot_qx = strpath; if (result->in_shareImage->imgstr != "") { strroot += result->in_shareImage->imgstr; strroot += "/"; strroot_qx += result->in_shareImage->imgstr; strroot_qx += "/"; } if (strpath != "") { strroot_qx += "qx/"; if (result->nProductResult != 0) { strroot += "NG/"; } else { strroot += "OK/"; } if (result->in_shareImage->strImgProductID != "") { strroot += result->in_shareImage->strImgProductID + "/"; } if (result->nresult != 0) { strroot += "NG/"; } else { if (result->nYS_result != 0) { strroot += "OK/YS/"; } else { strroot += "OK/OK/"; } } } printf("result->nresult %d %d \n", result->nresult, result->nYS_result); printf("%s\n", strroot.c_str()); _sysmkdirs_1(strroot); std::string str_saveName = ""; // getchar(); if (result->in_shareImage->strImgProductID != "") { strroot += result->in_shareImage->strImgProductID; str_saveName += result->in_shareImage->strImgProductID; } if (result->in_shareImage->strImgName != "") { strroot += "_" + result->in_shareImage->strImgName; str_saveName += "_" + result->in_shareImage->strImgName; } { strroot += "_" + result->in_shareImage->strCameraName; str_saveName += "_" + result->in_shareImage->strCameraName; strroot += "_" + result->in_shareImage->strChannel; str_saveName += "_" + result->in_shareImage->strChannel; } writeLog(strroot, result->det_LogList); WriteJsonString(strroot, result->strResultJson); // printf("%s \n", strroot.c_str()); std::string str = strroot + "_RE_Resultimg.png"; if (!result->resultimg.empty()) { cv::imwrite(str, result->resultimg); } std::string str123 = strroot + "_RE_CutImg.png"; if (!result->cutSrcimg.empty()) { cv::imwrite(str123, result->cutSrcimg); } std::string str123r = strroot + "_RE_CutDrawImg.png"; if (!result->SrcResultImg.empty()) { cv::imwrite(str123r, result->SrcResultImg); } std::string strMask = strroot + "_RE_AIMask.png"; if (!result->resultMaskImg.empty()) { cv::imwrite(strMask, result->resultMaskImg); } std::string str_qx; printf("result->qxImageResult.size() %ld \n", result->qxImageResult.size()); for (int i = 0; i < result->qxImageResult.size(); i++) { std::string str = strroot + "_RE_" + std::to_string(i) + "_Src.png"; if (!result->qxImageResult.at(i).srcImg.empty()) { cv::imwrite(str, result->qxImageResult.at(i).srcImg); } str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; printf("-1-- %s\n", str_qx.c_str()); _sysmkdirs_1(str_qx); str_qx += str_saveName + "_RE_" + std::to_string(i) + "_Src.png"; // printf("-2-- %s\n", str_qx.c_str()); if (!result->qxImageResult.at(i).srcImg.empty()) { cv::imwrite(str_qx, result->qxImageResult.at(i).srcImg); } str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; str_qx += str_saveName + "_RE_" + std::to_string(i) + "_Small.png"; if (!result->qxImageResult.at(i).resizeImg.empty()) { cv::imwrite(str_qx, result->qxImageResult.at(i).resizeImg); } { str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; str_qx += str_saveName + "_RE_" + std::to_string(i) + "_AI_In.png"; if (!result->qxImageResult.at(i).AI_in_Img.empty()) { cv::imwrite(str_qx, result->qxImageResult.at(i).AI_in_Img); } str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; str_qx += str_saveName + "_RE_" + std::to_string(i) + "_AI_In_mask.png"; if (!result->qxImageResult.at(i).AI_out_img.empty()) { cv::imwrite(str_qx, result->qxImageResult.at(i).AI_out_img); } } // printf("-1111-- %s\n", str_qx.c_str()); std::string str1 = strroot + "_RE_" + std::to_string(i) + "_Small.png"; if (!result->qxImageResult.at(i).resizeImg.empty()) { cv::imwrite(str1, result->qxImageResult.at(i).resizeImg); } } printf("result->YS_ImageResult.size() %ld\n", result->YS_ImageResult.size()); for (int i = 0; i < result->YS_ImageResult.size(); i++) { std::string str = strroot + "_RE_" + std::to_string(i) + "_YS_Src.png"; if (result->YS_ImageResult.at(i).srcImg.empty()) { printf("resqwwwwwwwwwwwwwwwult->YS_ImageResult.size() %ld \n", result->YS_ImageResult.size()); } if (!result->YS_ImageResult.at(i).srcImg.empty()) { cv::imwrite(str, result->YS_ImageResult.at(i).srcImg); } str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; // printf("-3-- %s\n", str_qx.c_str()); _sysmkdirs_1(str_qx); str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_Src.png"; // printf("-4-- %s\n", str_qx.c_str()); if (!result->YS_ImageResult.at(i).srcImg.empty()) { cv::imwrite(str_qx, result->YS_ImageResult.at(i).srcImg); } str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_Small.png"; if (!result->YS_ImageResult.at(i).resizeImg.empty()) { cv::imwrite(str_qx, result->YS_ImageResult.at(i).resizeImg); } { str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_AI_In.png"; if (!result->YS_ImageResult.at(i).AI_in_Img.empty()) { cv::imwrite(str_qx, result->YS_ImageResult.at(i).AI_in_Img); } str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_AI_In_mask.png"; if (!result->YS_ImageResult.at(i).AI_out_img.empty()) { cv::imwrite(str_qx, result->YS_ImageResult.at(i).AI_out_img); } } // printf("-1111-- %s\n", str_qx.c_str()); std::string str1 = strroot + "_RE_" + std::to_string(i) + "_YS_Small.png"; if (!result->YS_ImageResult.at(i).resizeImg.empty()) { cv::imwrite(str1, result->YS_ImageResult.at(i).resizeImg); } } return 0; } int deal::writeLog(std::string strSavePath, std::vector logList) { std::string str = strSavePath + ".txt"; // 打开文件 std::ofstream outFile(str); // 检查文件是否成功打开 if (!outFile) { std::cerr << "Failed to open file." << std::endl; return 1; } // 将vector中的内容写入文件 for (const auto &str : logList) { // printf("%s \n",str.c_str()); outFile << str << std::endl; } // 关闭文件 outFile.close(); return 0; } int deal::WriteJsonString(std::string strSavePath, std::string strjson) { std::string str = strSavePath + ".json"; // 打开文件 std::ofstream outFile(str); // 检查文件是否成功打开 if (!outFile) { std::cerr << "Failed to open file." << std::endl; return 1; } // 将vector中的内容写入文件 outFile << strjson << std::endl; // 关闭文件 outFile.close(); return 0; } void deal::ResultThread(int id) { std::vector vi; int startidx = m_CPUInfo[THREAD_CPU_Main_saveImg].startIdx; int cpunum = m_CPUInfo[THREAD_CPU_Main_saveImg].num; // for (int i = 0; i < cpunum; i++) // { // vi.push_back(startidx + i); // } vi.push_back(startidx + id); auto nRet = set_cpu_id(vi); printf("THREAD_CPU_Main_saveImg %d bind cpu ret %d startidx %d num %d\n", id, nRet, startidx + id, 1); int re = 0; cv::Mat detImg; int kkkkk = 0; static int saveidx = 0; while (!m_bExit) { std::shared_ptr dealResult; mutex_Result_list.lock(); if (m_Result_list.size() > 0) { dealResult = m_Result_list.front(); m_Result_list.pop(); if (m_Result_list.size() > 10) { printf("Result_list size %ld \n", m_Result_list.size()); } mutex_Result_list.unlock(); } else { mutex_Result_list.unlock(); usleep(10000); continue; } { updataResltInfo(dealResult); } { if (true) { // 存图 std::string savepath = "/home/aidlux/BOE/FOG/Detsave/"; saveImg(savepath, dealResult); // saveImg("/home/aidlux/BOE/ResultImg/", dealResult); } { // 存 检测统计 日志 mutex_DetResult_.lock(); m_DetResult.print(false); std::string strlog = "/home/aidlux/BOE/FOG/ResultImg/"; if (m_strCurDate != "") { strlog += m_strCurDate; strlog += "/result"; } else { strlog += "/result"; } writeLog(strlog, m_DetResult.strlist); mutex_DetResult_.unlock(); } } usleep(5 * 1000); } } int deal::set_cpu_id(const std::vector &cpu_set_vec) { // for cpu affinity int nRet = 0; #ifdef __linux cpu_set_t _cur_cpu_set; CPU_ZERO(&_cur_cpu_set); for (auto _id : cpu_set_vec) { CPU_SET(_id, &_cur_cpu_set); } if (0 > pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cur_cpu_set)) { perror("set cpu affinity failed: "); printf("Warning: set cpu affinity failed ... ...\n"); nRet = -1; } #endif //__linux return nRet; } void deal::GetDealResultToQueu() { // 处理结果 std::shared_ptr checkResult; if (!m_pALLImgCheckAnalysisy) { return; } int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult); if (re == 0) { mutex_Result_list.lock(); m_Result_list.push(checkResult); mutex_Result_list.unlock(); } else { printf("Check error >>>>>>>>>>>>>>>>> \n"); } return; } bool deal::ReadSystemConfig(const std::string &strPath) { printf("Reading system config %s\n", strPath.c_str()); Json::CharReaderBuilder builder; builder["collectComments"] = true; Json::Value root; std::string err; std::ifstream ifs(strPath); if (!ifs.is_open()) { printf("error:file is open\n"); return false; } if (!Json::parseFromStream(builder, ifs, &root, &err)) { printf("error:parseFromStream\n"); return false; } m_system_param.Use_CPU_StartIdx = root["Use_CPU_StartIdx"].asInt(); m_system_param.nWorkIdx = root["Detect_Work_Idx"].asInt(); m_system_param.config_Root_Path = root["Config_Root_Path"].asString(); for (int i = 0; i < 4; i++) m_system_param.GPU_Device_ID_List[i] = -1; if (root.isMember("GPU_Device_ID_List")) { auto &arr = root["GPU_Device_ID_List"]; for (int i = 0; i < arr.size() && i < 4; i++) { m_system_param.GPU_Device_ID_List[i] = arr[i].asInt(); } } m_nCurUseCPUIDX = m_system_param.Use_CPU_StartIdx; return m_system_param.valid(); } int deal::GetJcImageInfo(std::string strpath, std::vector &jcImageInfoList) { LoadOfflineCheckImg(strpath); jcImageInfoList.erase(jcImageInfoList.begin(), jcImageInfoList.end()); // 遍历每一套图片 for (int idx = 0; idx < m_OffLineCheckImgNameList.size(); idx++) { std::string path = m_OffLineCheckImgNameList.at(idx); JC_IMAGE_INFO_ tem; int re = GetImgInfo_POL_ET(path, &tem); } // getchar(); return 0; } int deal::GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector &jcImageInfoList) { // 1、获取图片路径 std::vector img_paths; std::string strs1 = strSearchImg + "/*.ytimage"; cv::glob(strs1, img_paths, true); printf("%ld \n", img_paths.size()); jcImageInfoList.erase(jcImageInfoList.begin(), jcImageInfoList.end()); // 遍历每一套图片 for (int idx = 0; idx < img_paths.size(); idx++) { // printf("---- %d / %d %s----\n", idx, m_OffLineCheckImgNameList.size(), m_OffLineCheckImgNameList.at(idx).c_str()); std::string path = img_paths.at(idx); JC_IMAGE_INFO_ tem; int re = 0; { re = GetImgInfo_POL_ET(path, &tem); if (re != 0) { continue; } } tem.strProductID = strProductID; jcImageInfoList.push_back(tem); } return 0; } int deal::GetImgInfo_POL_ET(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo) { if (pImageInfo == NULL) { return 1; } string strName = ExtractFileNameWithoutExtension(strImgPath); printf("strName %s \n", strName.c_str()); size_t lastUnderscore = strName.rfind('_'); if (lastUnderscore == std::string::npos) return 1; // 没有找到最后一个 '_' std::string strImageChannel = strName.substr(0, lastUnderscore); printf("strImageChannel %s\n", strImageChannel.c_str()); if (strImageChannel == "CA" || strImageChannel == "TA") { } else { return 1; } pImageInfo->strchannelName = strImageChannel; pImageInfo->strName = strName; pImageInfo->strPath = strImgPath; pImageInfo->strCamID = "0"; printf("strImgPath %s strName %s strChannel %s\n", strImgPath.c_str(), strName.c_str(), strImageChannel.c_str()); // 使用 find 函数检查是否包含 "_左" return 0; } int deal::GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo) { if (pImageInfo == NULL) { return 1; } string strImageChannel = ExtractFileNameWithoutExtension(strImgPath); printf("strImageChannel %s\n", strImageChannel.c_str()); std::string strChannle = m_image_ReadChannel.strDetName(strImageChannel); if (strChannle == "") { return 1; } pImageInfo->strchannelName = strChannle; pImageInfo->strName = strChannle; pImageInfo->strPath = strImgPath; pImageInfo->strCamID = "0"; // printf("strImgPath %s strChannel %s\n", strImgPath.c_str(), strChannle.c_str()); // 使用 find 函数检查是否包含 "_左" if (strImgPath.find("_工位右") != std::string::npos) { pImageInfo->strCamID = "1"; ; } return 0; } int deal::ReadTestImgaData() { std::string strPath = "../data/testImg.json"; printf("ReadTestImgaData config %s\n", strPath.c_str()); Json::CharReaderBuilder builder; builder["collectComments"] = true; Json::Value root; std::string err; std::ifstream ifs(strPath); if (!ifs.is_open()) { printf("error:file is open\n"); return false; } if (!Json::parseFromStream(builder, ifs, &root, &err)) { printf("error:parseFromStream\n"); return false; } m_TestJC_ImageDate.erase(m_TestJC_ImageDate.begin(), m_TestJC_ImageDate.end()); { auto value = root["img_date"]; if (value.isObject()) { auto arr = value["date"]; std::cout << arr << std::endl; if (arr.isArray()) { // 遍历数组中的每个元素 for (int i = 0; i < arr.size(); i++) { // 读取对象中的属性值 std::string strdata = arr[i].asString(); m_TestJC_ImageDate.push_back(strdata); // 输出属性值 std::cout << "date: " << strdata << std::endl; } } } } // getchar(); return 0; } int deal::InitDetData() { m_read_ImgNum = 0; return 0; } int deal::InsertDetResult(ReadImgInfo tem) { std::lock_guard lock(mtx_List[Mutex_Type_DetResult]); m_DetResultList.push_back(tem); return 0; } int deal::GetUpMaskImg(cv::Mat inImg, cv::Rect roi, cv::Mat &maskimg) { // 定义滑动窗口的大小和步长 int windowWidth = 128; int windowHeight = 128; int stepX = 110; // 横向步长 int stepY = 110; // 纵向步长 maskimg = cv::Mat(roi.height, roi.width, CV_8U, cv::Scalar(0)); int sx = roi.x; int ex = roi.x + roi.width; int sy = roi.y; int ey = roi.y + roi.height; cv::Rect detroi; detroi.width = windowWidth; detroi.height = windowHeight; cv::Rect maskroi; maskroi.width = windowWidth; maskroi.height = windowHeight; cv::Mat temmask; // 遍历图像,使用滑动窗口 for (int y = sy; y <= ey; y += stepY) { detroi.y = y; if (detroi.y + windowHeight > ey) { detroi.y = ey - windowHeight; } maskroi.y = detroi.y - sy; for (int x = sx; x <= ex; x += stepX) { detroi.x = x; if (detroi.x + windowWidth > ex) { detroi.x = ex - windowWidth; } maskroi.x = detroi.x - sx; int thresholdValue = 30; // 初始阈值,OTSU将自动计算 int maxVal = 255; // 最大值 double otsuThreshold; cv::Scalar mean, stddev; cv::meanStdDev(inImg(detroi), mean, stddev); int varianceImg; varianceImg = mean[0] + 1 * mean[0]; if (mean[0] > 100) { continue; } // 使用 OTSU 阈值处理 otsuThreshold = cv::threshold(inImg(detroi), temmask, thresholdValue, maxVal, cv::THRESH_BINARY | cv::THRESH_OTSU); thresholdValue = otsuThreshold; if (thresholdValue < 30) { thresholdValue = 30; } if (thresholdValue < varianceImg) { thresholdValue = varianceImg; } if (thresholdValue > 100) { continue; } // std::cout << "varianceImg value is: " << varianceImg << std::endl; // std::cout << "OTSU threshold value is: " << otsuThreshold << std::endl; // std::cout << "stddev[0] value is: " << stddev[0] << std::endl; otsuThreshold = cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY); // cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY + cv::THRESH_OTSU); // 提取当前窗口 // cv::rectangle(inImg, detroi, cv::Scalar(255, 0, 0)); } } // cv::imwrite("inImg1123.png", inImg); // cv::imwrite("maskimg.png", maskimg); // getchar(); return 0; } int deal::ReJson() { return 0; } int deal::ReJson_ALL() { printf(">>> ReJson ALL start \n"); // 1、获取所有的json std::vector img_paths; cv::glob(runConfig.filePath + "/*.json", img_paths, true); if (img_paths.size() <= 0) { printf("json file is NULL \n"); return 1; /* code */ } // 用map存储每个id对应的vector std::unordered_map> ProductJsonList; // 遍历路径并按照ID分组 for (const auto &path : img_paths) { // 获取路径中的 ID 部分(即文件夹名部分) size_t start_pos = path.find_last_of("/") + 1; size_t end_pos = path.find("_", start_pos); std::string id = path.substr(start_pos, end_pos - start_pos); // printf("id %s\n",id.c_str()); // 将文件路径加入对应 ID 的vector中 ProductJsonList[id].push_back(path); } for (const auto &product : ProductJsonList) { std::cout << product.first << " => " << product.second.size() << std::endl; std::vector jsonList; std::string strProductName = product.first; for (const auto &str : product.second) { { // 2、获取第一个 名称 std::string strPath = str; size_t lastSlashPos = strPath.find_last_of('/'); // 提取文件名(从最后一个斜杠之后的部分) std::string filename = strPath.substr(lastSlashPos + 1); // 查找文件名中的第一个下划线位置 size_t firstUnderscorePos = filename.find('_'); // 提取文件名中的名称部分(下划线之前的字符串) std::string strProduct = filename.substr(0, firstUnderscorePos); // printf("strProduct %s \n", strProduct.c_str()); if (strProduct == strProductName) { Json_Det_Path tem; tem.strPath_Json = str; tem.strPath_CutImg = str; size_t pos = tem.strPath_CutImg.rfind(".json"); if (pos != std::string::npos) { // 替换 ".json" 为 "_RE_CutImg.png" tem.strPath_CutImg.replace(pos, 5, "_RE_CutImg.png"); } std::cout << " Path: " << tem.strPath_Json << std::endl; std::cout << " Path: " << tem.strPath_CutImg << std::endl; jsonList.push_back(tem); } } } ReJson_product(jsonList, strProductName); } // 获取要检测的 json 图片 list printf(">>>>>>>>>>>>>>>>>>>> rejson ALL is Complete \n"); return 0; } int deal::DetImg() { // 单张检测 if (runConfig.det_Type == RUNTYPE_RUN_Pre) { m_nReadThread_type = READ_THREAD_TYPE_READIMG; StartThread(THREAD_RUN_Only_ReadImg); preCheck(); return 0; } m_nReadThread_type = READ_THREAD_TYPE_READIMG; m_nSystemCheckType = CHECK_TYPE_OFFLING; StartThread(THREAD_RUN_ALL); // 文件夹套图处理 if (RUNTYPE_RUN_File == runConfig.det_Type || runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST || runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_Qx || runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_ALL) { CheckFileImg(); // 检查文件图片 } // getchar(); return 0; } /// @brief 检查文件图片 /// @detail 后续实现具体功能 /// @return 0 表示成功 int deal::CheckFileImg() { std::string root_dir = runConfig.filePath; printf("测试目录:%s\n\n", root_dir.c_str()); LoadImage loader; LoadConfig config; config.Init(); config.max_products = runConfig.m_nTestNum; if (config.max_products <= 0) { config.max_products = 9999999; } printf("开始加载图片...\n\n"); std::vector products = loader.LoadALLImg(root_dir, config, &m_image_ReadChannel); if (products.empty()) { printf("未找到任何图片!\n"); printf("错误信息:%s\n", loader.getLastError().c_str()); return 1; } printf("加载完成!\n"); printf("产品数量:%zu\n", products.size()); printf("图片总数:%zu\n\n", loader.getTotalLoaded()); for (size_t i = 0; i < products.size(); i++) { products[i].print("产品" + std::to_string(i + 1)); } // getchar(); for (size_t i = 0; i < products.size(); i++) { CheckProduct(products[i]); // 处理单个产品 } printf("\n"); // TODO: 后续实现具体功能 // getchar(); return 0; } /// @brief 检查单个产品 /// @param product 产品信息(包含图片对列表) /// @return 0 表示成功 int deal::CheckProduct(const LoadProductImages &product) { // 1. 统计图片对总数 size_t totalImgNum = product.images.size(); if (runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST) { totalImgNum = 0; for (const auto &image : product.images) { if (image.channel_name == "L255") { totalImgNum++; } } } if (totalImgNum == 0) { printf("[产品] %s 没有图片对\n", product.product_id.c_str()); return 0; } // 2. 重置计数器(重要!每个产品独立计数) m_nProductPendingTasks = 0; m_nProductSuccessCount = 0; m_nProductFailCount = 0; m_ProductFailedList.clear(); m_nCheckNotifiedCount = 0; // 3. 打印产品信息 printf("\n"); printf("╔══════════════════════════════════════════════════════════\n"); printf("║ 产品:%s\n", product.product_id.c_str()); printf("║ 图片对数:%zu\n", totalImgNum); printf("╚══════════════════════════════════════════════════════════\n\n"); // 4. 分发读图任务 printf("[任务分发] 开始向读图线程分发 %zu 个任务...\n", totalImgNum); DistributeProductTasks(product); printf("[任务分发] 完成\n\n"); // 5. 使用条件变量等待并处理通知队列 int processed = 0; { IN_IMG_Status_ temstatus = IN_IMG_Status_Start; std::unique_lock lock(m_checkNotifyMutex); while (processed < (int)totalImgNum) { // 等待通知:队列非空 或 所有任务已完成 m_checkNotifyCV.wait_for(lock, std::chrono::milliseconds(100), [this, &processed, totalImgNum]() { return !m_checkNotifyQueue.empty() || m_nCheckNotifiedCount.load() >= (int)totalImgNum; }); // 消费队列中的所有通知 while (!m_checkNotifyQueue.empty()) { auto info = m_checkNotifyQueue.front(); m_checkNotifyQueue.pop(); // 处理图片对 SendCheckImg(info, temstatus, false); processed++; if (IN_IMG_Status_Start == temstatus) { temstatus = IN_IMG_Status_Other; } } } // 注:不需要第二个 while 清理,因为第一个 while 退出时 processed == totalImgNum // 队列中不可能还有未处理的项目(内层 while 已经消费完) } CheckImgNotifyInfo info; info.productId = product.product_id; SendCheckImg(info, IN_IMG_Status_End, true); printf("\n"); // 6. 打印统计(不清理线程,继续下一个产品) PrintProductStatistics(product); // getchar(); return 0; } int deal::SendCheckImg(const CheckImgNotifyInfo &info, IN_IMG_Status_ status, bool bComplete) { // 发送结束标志 if (bComplete) { std::shared_ptr tem = std::make_shared(); tem->strImgProductID = info.productId; tem->Status = -1; if (m_pALLImgCheckAnalysisy) { m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem); } return 0; } // 图片读取有异常,处理失败的图片对 if (!info.success) { // 记录失败 FailedImgRecord record; record.left_path = info.left_path; record.right_path = info.right_path; record.productId = info.productId; record.channelName = info.channelName; record.errorReason = info.errorReason; RecordFailedImg(record); m_nProductFailCount.fetch_add(1); printf("[失败-%3d] %s | %s | %s\n", info.taskIndex, info.productId.c_str(), info.channelName.c_str(), info.errorReason.c_str()); return -1; } // printf("[%3d] %s | %d | %s | %s | %s | 左:%dx%d 右:%dx%d | 耗时:%ldms\n", // info.taskIndex, // info.productId.c_str(), // info.camera_Num, // info.cameraSide.c_str(), // info.channelName.c_str(), // info.imageName.c_str(), // info.left_img.cols, info.left_img.rows, // info.right_img.cols, info.right_img.rows, // info.readTimeMs); m_nProductSuccessCount.fetch_add(1); std::shared_ptr tem = std::make_shared(); tem->strChannel = info.channelName; // cv::imwrite(tem->strChannel + "_new_debug.png", info.left_img); // return 0; // cv::imwrite(tem->strChannel+".png",pDetImageInfo->img); tem->nImgBigIdx = 0; tem->strImgName = info.imageName; tem->strImgProductID = info.productId; tem->imgstr = m_strCurDate; if (runConfig.bDebugSaveImg == 1) { tem->otherValue = 9; } tem->getImgTimeMs = getcurTime(); tem->Status = status; tem->Det_Mode = DET_MODE_Det; if (runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST) { tem->Det_Mode = DET_MODE_EDGE; } if (runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_Qx || runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_ALL) { tem->ninstruct = 767; if (runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_ALL) { tem->ninstruct = 768; } } { if (!info.left_img.empty()) { tem->img = info.left_img; } else if (!info.right_img.empty()) { tem->img = info.right_img; } } tem->strCameraName = info.cameraSide; tem->camera_ID = 0; if (runConfig.bDebugSaveImg == 1) { tem->bDebugsaveImg = true; } int re = 0; if (m_pALLImgCheckAnalysisy) { bool bcontinue = false; do { re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem); if (re == 8) { bcontinue = true; std::this_thread::sleep_for(std::chrono::milliseconds(500)); } else { bcontinue = false; } } while (bcontinue); } return re; } // ============ 产品检测线程池相关函数 ============ void deal::InitProductReadThreadPool() { printf("[线程池] 初始化产品检测线程池...\n"); // 创建 8 个读图线程 for (int i = 0; i < m_nProductReadThreadNum; i++) { auto thread = std::make_shared( &deal::ProductReadImgThreadFunc, this, i); m_productReadThreads.push_back(thread); } printf("[线程池] 创建完成 (%d 读图线程)\n", m_nProductReadThreadNum); } void deal::DestroyProductReadThreadPool() { printf("[线程池] 销毁产品检测线程池...\n"); // 通知所有线程退出 m_bProductReadExit = true; m_productTaskCV.notify_all(); m_checkNotifyCV.notify_all(); // 等待读图线程结束 for (auto &thread : m_productReadThreads) { if (thread && thread->joinable()) { thread->join(); } } m_productReadThreads.clear(); printf("[线程池] 销毁完成\n"); } void deal::DistributeProductTasks(const LoadProductImages &product) { int taskIndex = 0; for (const auto &image : product.images) { if (runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST) { if (image.channel_name != "L255") { continue; } } auto task = std::make_shared(); task->productId = product.product_id; task->channelName = image.channel_name; task->imageName = image.image_name; // 图片名称 task->left_path = image.left_path; task->right_path = image.right_path; task->camera_Num = product.camera_Num; task->cameraSide = image.camera_side; task->taskIndex = taskIndex++; // 如果队列满了,等待 { std::unique_lock lock(m_productTaskMutex); m_productTaskCV.wait(lock, [this]() { return m_productTaskQueue.size() < (size_t)m_nProductQueueMaxSize || m_bProductReadExit; }); if (m_bProductReadExit) { break; } m_productTaskQueue.push(task); m_nProductPendingTasks.fetch_add(1); } m_productTaskCV.notify_one(); } } std::shared_ptr deal::GetProductTask() { std::shared_ptr task; std::unique_lock lock(m_productTaskMutex); if (m_productTaskCV.wait_for(lock, std::chrono::milliseconds(10), [this]() { return !m_productTaskQueue.empty() || m_bProductReadExit; })) { if (m_productTaskQueue.empty()) { return nullptr; } task = m_productTaskQueue.front(); m_productTaskQueue.pop(); } return task; } void deal::ProductReadImgThreadFunc(int threadId) { while (!m_bProductReadExit) { auto task = GetProductTask(); if (task == nullptr) { continue; } CheckImgNotifyInfo info; info.taskIndex = task->taskIndex; info.productId = task->productId; info.channelName = task->channelName; info.imageName = task->imageName; info.left_path = task->left_path; info.right_path = task->right_path; info.cameraSide = task->cameraSide; // 复制相机方位 info.camera_Num = task->camera_Num; try { // 读取左图 long startTime = getcurTime(); cv::Mat left_img; cv::Mat img16 = cv::imread(task->left_path, cv::IMREAD_UNCHANGED); if (!img16.empty()) { if (img16.type() != CV_8U) { // printf("=========== 1 %s\n", info.channelName.c_str()); cv::Mat img8; cv::normalize(img16, img8, 0, 255, cv::NORM_MINMAX); img8.convertTo(img8, CV_8U); left_img = img8; } else if (img16.type() == CV_8U) { // printf("=========== 2%s\n", info.channelName.c_str()); left_img = img16; } } // cv::imwrite(info.channelName+"_ddddd.png", left_img); // getchar(); // 读取右图 cv::Mat right_img; img16 = cv::imread(task->right_path, cv::IMREAD_UNCHANGED); if (!img16.empty()) { if (img16.type() != CV_8U) { // printf("=========== 1 %s\n", info.channelName.c_str()); cv::Mat img8; cv::normalize(img16, img8, 0, 255, cv::NORM_MINMAX); img8.convertTo(img8, CV_8U); right_img = img8; } else if (img16.type() == CV_8U) { // printf("=========== 2%s\n", info.channelName.c_str()); right_img = img16; } } long endTime = getcurTime(); info.width = left_img.cols; info.height = left_img.rows; info.readTimeMs = endTime - startTime; info.left_img = left_img; info.right_img = right_img; // 检查是否成功读取 info.success = !left_img.empty() || !right_img.empty(); if (!info.success) { // 记录失败原因 if (left_img.empty() && right_img.empty()) { info.errorReason = "左右图都读取失败"; } else if (left_img.empty()) { info.errorReason = "左图读取失败:" + task->left_path; } else { info.errorReason = "右图读取失败:" + task->right_path; } printf("[读图错误-%3d] %s\n", task->taskIndex, info.errorReason.c_str()); } } catch (const cv::Exception &e) { // OpenCV 异常处理 info.success = false; info.errorReason = std::string("OpenCV 异常:") + e.what(); info.width = 0; info.height = 0; info.readTimeMs = 0; printf("[读图异常-%3d] %s\n", task->taskIndex, e.what()); } catch (const std::exception &e) { // 标准异常处理 info.success = false; info.errorReason = std::string("异常:") + e.what(); info.width = 0; info.height = 0; info.readTimeMs = 0; printf("[读图异常-%3d] %s\n", task->taskIndex, e.what()); } catch (...) { // 未知异常处理 info.success = false; info.errorReason = "未知异常"; info.width = 0; info.height = 0; info.readTimeMs = 0; printf("[读图未知异常-%3d]\n", task->taskIndex); } // 推送到通知队列并通知主线程 { std::lock_guard lock(m_checkNotifyMutex); m_checkNotifyQueue.push(info); } m_checkNotifyCV.notify_one(); // 立即唤醒主线程 // 更新计数器 m_nCheckNotifiedCount.fetch_add(1); } } void deal::RecordFailedImg(const FailedImgRecord &record) { std::lock_guard lock(m_productFailedMutex); m_ProductFailedList.push_back(record); } void deal::PrintProductStatistics(const LoadProductImages &product) { printf("\n"); printf("╔══════════════════════════════════════════════════════════\n"); printf("║ 产品:%s - 处理完成\n", product.product_id.c_str()); printf("║ ─────────────────────────────────────────────────────── \n"); printf("║ 总计:%zu 对图片\n", product.images.size()); printf("║ 成功:%d 对\n", m_nProductSuccessCount.load()); printf("║ 失败:%d 对\n", m_nProductFailCount.load()); int totalProcessed = m_nProductSuccessCount.load() + m_nProductFailCount.load(); float successRate = (totalProcessed > 0) ? (m_nProductSuccessCount.load() * 100.0f / totalProcessed) : 0; printf("║ 成功率:%.1f%%\n", successRate); if (!m_ProductFailedList.empty()) { printf("║ ─────────────────────────────────────────────────────── \n"); printf("║ 失败列表:\n"); for (size_t i = 0; i < m_ProductFailedList.size() && i < 10; i++) { const auto &record = m_ProductFailedList[i]; printf("║ [%zu] 左:%s\n", i, record.left_path.c_str()); printf("║ 右:%s\n", record.right_path.c_str()); printf("║ 错误:%s\n", record.errorReason.c_str()); } if (m_ProductFailedList.size() > 10) { printf("║ ... 还有 %zu 条失败记录\n", m_ProductFailedList.size() - 10); } } printf("╚══════════════════════════════════════════════════════════\n"); printf("\n"); } int deal::ReJson_product(std::vector &jsonList, std::string strProductName) { // 获取要检测的 json 图片 list int temstatus = IN_IMG_Status_Start; int PushNum = 0; // 开始逐一复测 for (int i = 0; i < jsonList.size(); i++) { std::string strJson = jsonList.at(i).strPath_Json; std::string strimg = jsonList.at(i).strPath_CutImg; std::ifstream file(strJson); if (!file.is_open()) { std::cerr << "Unable to open file!" << std::endl; return -1; } // 读取文件内容到 std::string std::stringstream buffer; buffer << file.rdbuf(); std::string json_str = buffer.str(); // 获取 JSON 文件的内容作为字符串 // 显示读取到的 JSON 字符串 // std::cout << "JSON content: " << json_str << std::endl; cv::Mat cutimg = cv::imread(strimg, 0); int f0 = strJson.rfind('_'); int f1 = strJson.rfind('.'); int f2 = strJson.rfind('/'); std::string str1 = strJson.substr(f2 + 1, f1 - f2 - 1); std::string str2 = strJson.substr(f0 + 1, f1 - f0 - 1); // std::string str3 = strJson.substr(f2 + 1, strJson.size() - f2); std::cout << str1 << std::endl; std::cout << str2 << std::endl; if (str1.find("CA") != std::string::npos) { str2 = "CA"; } else if (str1.find("TA") != std::string::npos) { str2 = "TA"; } else { continue; } std::cout << "start " << strJson << std::endl; std::shared_ptr result; // 多线程 互斥 作用域 { std::shared_ptr temdet = std::make_shared(); temdet->strCameraName = str2; temdet->strImgProductID = strProductName; temdet->strChannel = str2; temdet->strImgName = str1; std::cout << "strChannel " << temdet->strChannel << std::endl; temdet->Det_Mode = DET_MODE_ReJson; temdet->img = cutimg; temdet->resultJson = json_str; { if (i == 0) { temdet->Status = IN_IMG_Status_Start; } else if (i == jsonList.size() - 1) { temdet->Status = IN_IMG_Status_End; } else { temdet->Status = IN_IMG_Status_Other; } } int re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(temdet); if (re != 0) { printf("reJson Error %d \n", re); continue; } PushNum++; // 结果异常 } } int getresultNum = 0; while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟消费过程 // 处理结果 std::shared_ptr checkResult; int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult); printf("********************** Get result %d -- %s \n", getresultNum, checkResult->in_shareImage->strChannel.c_str()); saveImg("/home/aidlux/BOE/ReJsonresult/", checkResult); getresultNum++; if (getresultNum == PushNum) { break; } } return 0; } void deal::GetResultThread() { std::vector vi; vi.push_back(18); auto nRet = set_cpu_id(vi); printf("bind cpu ret %d, %d\n", nRet, 18); int re = 0; int nsleep1 = 2 * 1000; while (!m_bExit) { // 1、拷贝检测结果到队列 GetDealResultToQueu(); usleep(nsleep1); } } void deal::ReadImgThread(int id) { int nsleep1 = 200 * 1000; int readThreadIdx = id; while (!m_bExit) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费过程 // 读图模式 if (READ_THREAD_TYPE_READIMG == m_nReadThread_type) { Thread_ReadImg(readThreadIdx); } else if (READ_THREAD_Detect == m_nReadThread_type) { } } } void deal::testimg(cv::Mat img) { } int deal::updataResltInfo(std::shared_ptr result) { mutex_DetResult_.lock(); std::string productID = result->in_shareImage->strImgProductID; std::string imgName = result->in_shareImage->strChannel; // printf("add productID %s imgName %s %d\n", productID.c_str(), imgName.c_str(), result->nresult); long t1 = getcurTime(); m_DetResult.updata(productID, imgName, result->nresult, t1); for (int i = 0; i < ERROR_TYPE_COUNT; i++) { if (result->defectResultList[i].nresult == 1) { m_DetResult.update_qx(result->defectResultList[i].keyName, result->defectResultList[i].num); } } mutex_DetResult_.unlock(); return 0; } // 滑动窗口二值化函数 void deal::slidingWindowAutoThreshold(const cv::Mat &src, cv::Mat &dst, int windowSize, int step, double C) { // 确保窗口大小为奇数 // if (windowSize % 2 == 0) // { // windowSize++; // } // 创建目标图像 dst = cv::Mat::zeros(src.size(), CV_8UC1); // 获取源图像的尺寸 int rows = src.rows; int cols = src.cols; int xs = 0; int xe = windowSize; int ys = 0; int ye = windowSize; for (int y = ye; y < rows;) { int xs = 0; int xe = windowSize; for (int x = xe; x < cols;) { cv::Rect roi; roi.x = xs; roi.width = windowSize; roi.y = ys; roi.height = windowSize; cv::Mat window = src(roi); // 计算窗口中的平均值和标准差 cv::Scalar mean, stdDev; cv::meanStdDev(window, mean, stdDev); // printf(" x %d %d y %d %d %f %f \n", xs, xe, ys, ye, mean[0], stdDev[0]); int T = mean[0] + 20 * stdDev[0]; cv::threshold(window, dst(roi), T, 255, cv::THRESH_BINARY); // cv::rectangle(src, roi, cv::Scalar(255, 0, 255)); if (xe == cols) { break; } xs = xs + step; xe = xs + windowSize; if (xs < cols && xe > cols) { xe = cols; xs = xe - windowSize; } } if (ye == rows) { break; } ys = ys + step; ye = ys + windowSize; if (ys < rows && ye > rows) { ye = rows; ys = ye - windowSize; } } } int deal::SetStatus(int type, int status) { std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); m_DetStatusList[type] = status; return 0; } int deal::GetStatus(int type) { std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); return m_DetStatusList[type]; } bool deal::IsStatus(int type, int status) { std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); if (m_DetStatusList[type] == status) { return true; } return false; } int deal::SetStatus_List(int idx, Thread_Status_ status) { std::lock_guard lock(mtx_List[Mutex_Type_ReadImgThread]); m_nReadStausList[idx] = status; return 0; } int deal::GetStatus_List(int idx) { std::lock_guard lock(mtx_List[Mutex_Type_ReadImgThread]); return m_nReadStausList[idx]; } bool deal::IsStatus_List(int idx, Thread_Status_ status) { std::lock_guard lock(mtx_List[Mutex_Type_ReadImgThread]); if (idx < 0 || idx >= READ_IMG_THREAD_NUM) { } else { if (m_nReadStausList[idx] == status) { return true; } } return false; } int deal::setReadThreadStart() { for (int i = 0; i < READ_IMG_THREAD_NUM; i++) { SetStatus_List(i, Thread_Status_READY); } return 0; } int deal::GetReadImgCompleteThreadIdx() { for (int i = 0; i < READ_IMG_THREAD_NUM; i++) { if (IsStatus_List(i, Thread_Status_COMMPLET)) { return i; } } return -1; } bool deal::IsALLComplete() { std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); for (size_t i = 0; i < READ_IMG_THREAD_NUM; i++) { if (m_nReadStausList[i] == ReadImg_Status_COMMPLET) { return false; } } return true; } int deal::InitCPUIDX() { int start = 3; m_CPUInfo[THREAD_CPU_Main_Det].set(start, 4); start += 4; m_CPUInfo[THREAD_CPU_Main_readImg].set(start, READ_IMG_THREAD_NUM); start += READ_IMG_THREAD_NUM; m_CPUInfo[THREAD_CPU_Main_saveImg].set(start, Save_IMG_THREAD_NUM); start += Save_IMG_THREAD_NUM; m_CPUInfo[THREAD_CPU_CheckSo].set(start, 15); return 0; } void deal::Thread_ReadImg(int id) { if (!IsStatus_List(id, Thread_Status_READY)) { return; } int re = 0; std::shared_ptr pImageInfo = nullptr; re = GetReadImgInfo(pImageInfo); if (pImageInfo == nullptr) { printf("pImageInfo == nullptr=================id %d=============\n", id); return; } pImageInfo->img = cv::imread(pImageInfo->strPath, 0); m_ReadImgThread_Result[id] = pImageInfo; // 线程完成读图,设置现场状态为 完成 SetStatus_List(id, Thread_Status_COMMPLET); // printf("Thread_ReadImg=================id %d %s=============\n", id, pImageInfo->strPath.c_str()); } int deal::InsertReadImgInfo(std::shared_ptr pImageInfo) { std::lock_guard lock(mutex_ReadImgList); m_ReadImg_queue.push(pImageInfo); cv_ReadImgList.notify_one(); // 唤醒等待的线程 return 0; } int deal::GetReadImgInfo(std::shared_ptr &pImageInfo) { // printf("===============waite img info ===============\n"); std::unique_lock lock(mutex_ReadImgList); cv_ReadImgList.wait(lock, [this]() { return !m_ReadImg_queue.empty(); }); pImageInfo = m_ReadImg_queue.front(); // 获取队首数据 if (pImageInfo == NULL) { return 1; } m_ReadImg_queue.pop(); // 弹出队首数据 return 0; } int deal::LoadOfflineCheckImg(std::string strImgPath) { std::vector img_paths; cv::glob(strImgPath, img_paths, true); m_OffLineCheckImgList.erase(m_OffLineCheckImgList.begin(), m_OffLineCheckImgList.end()); m_OffLineCheckImgNameList.erase(m_OffLineCheckImgNameList.begin(), m_OffLineCheckImgNameList.end()); for (int i = 0; i < img_paths.size(); i++) { size_t found = img_paths[i].find_last_of("/\\"); // std::cout << img_paths[i] << std::endl; std::string str = img_paths[i]; m_OffLineCheckImgNameList.push_back(str); } return 0; } int deal::LoadImgPath_JCSN(std::string strImgPath) { std::cout << strImgPath << std::endl; std::vector img_paths; cv::glob(strImgPath, img_paths, true); m_OffImageSNPathList.erase(m_OffImageSNPathList.begin(), m_OffImageSNPathList.end()); for (int i = 0; i < img_paths.size(); i++) { std::string path = img_paths[i]; // std::cout << img_paths[i] << std::endl; // 提取所有文件夹名称 std::vector allDirectories = extractAllDirectories(path); std::string strSN = ""; // 输出所有文件夹名称 std::string strAllPath = "/"; for (const auto &dir : allDirectories) { strAllPath += dir; if (isValidString(dir)) { strSN = dir; // std::cout << strSN << std::endl; break; } strAllPath += "/"; } bool bh = false; for (int j = 0; j < m_OffImageSNPathList.size(); j++) { if (m_OffImageSNPathList.at(j) == strAllPath) { bh = true; break; } } if (!bh) { if (m_OffImageSNPathList.size() < m_nTestNum) { m_OffImageSNPathList.push_back(strAllPath); std::cout << strAllPath << std::endl; } // std::cout << strSN << std::endl; } } return 0; } bool deal::isValidString(const std::string &str) { // 检查字符串长度是否为10 if (str.length() < 14 || str.length() > 19) { return false; } // 检查字符串中的每个字符是否都是字母或数字 for (char c : str) { if (!std::isalnum(c)) { // 如果字符不是字母或数字 return false; } } // 字符串满足条件 return true; } int deal::LoadProductID(std::string strImgPath) { m_product_ID_List.erase(m_product_ID_List.begin(), m_product_ID_List.end()); std::vector img_paths; // tif 格式 { std::string str_bmp = strImgPath + "/*.ytimage"; std::cout << str_bmp << std::endl; cv::glob(str_bmp, img_paths, true); for (int i = 0; i < img_paths.size(); i++) { std::string path = img_paths[i]; // 提取所有文件夹名称 std::vector allDirectories = extractAllDirectories(path); std::string strSN = ""; // 输出所有文件夹名称 std::string strAllPath = "/"; for (const auto &dir : allDirectories) { // std::cout << dir << std::endl; strAllPath += dir; if (isValidString(dir)) { strSN = dir; break; } strAllPath += "/"; } bool bh = false; for (int j = 0; j < m_product_ID_List.size(); j++) { if (m_product_ID_List.at(j) == strAllPath) { bh = true; break; } } if (!bh) { if (m_product_ID_List.size() < m_nTestNum) { m_product_ID_List.push_back(strAllPath); std::cout << strAllPath << std::endl; } } } } return 0; } int deal::RandDrawImg(cv::Mat srcimg, cv::Mat &randErrorImg) { randErrorImg = srcimg.clone(); cv::Rect roi; roi.x = (rand() % (srcimg.cols - 20 - 20)) + 20; roi.y = (rand() % (srcimg.rows - 20 - 20)) + 20; roi.width = (rand() % (100 - 5)) + 5; roi.height = roi.width; if (roi.x + roi.width >= srcimg.cols) { roi.x = srcimg.cols - roi.width - 1; /* code */ } if (roi.y + roi.height >= srcimg.rows) { roi.y = srcimg.rows - roi.height - 1; /* code */ } randErrorImg(roi).setTo(30); return 0; } void deal::DealImg() { } // 提取所有文件夹名称函数 std::vector deal::extractAllDirectories(const std::string &path) { std::vector directories; std::string directory; // 遍历路径中的每个字符 for (char c : path) { // 如果遇到路径分隔符,则将当前文件夹名称存储起来 if (c == '/' || c == '\\') { if (!directory.empty()) { // 确保文件夹名称不为空 directories.push_back(directory); directory.clear(); // 清空当前文件夹名称 } } else { directory += c; // 将字符添加到当前文件夹名称中 } } // 将最后一个文件夹名称添加到列表中 if (!directory.empty()) { directories.push_back(directory); } return directories; }