#include "QX_Merge_Analysis.h" #include #include #include #include #include #include "CheckUtil.hpp" #include "CheckConfigDefine.h" QX_Merge_Analysis::QX_Merge_Analysis() { m_bExit = false; Clear(); StartThread(0); } QX_Merge_Analysis::~QX_Merge_Analysis() { StopThread(); } std::shared_ptr QX_Merge_Analysis::GetInstance() { std::shared_ptr instance = std::make_shared(); return instance; } int QX_Merge_Analysis::Clear() { m_pdetlogList.clear(); m_statusList.clear(); return 0; } int QX_Merge_Analysis::AddCamer(std::string cameraName) { setSendStatus(cameraName, RUN_STATUS_NULL); for (auto &it : m_statusList) { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "QX_Merge_Analysis", "AddCamer %s %d", it.first.c_str(), it.second); } m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "QX_Merge_Analysis", "AddCamer %s %s", cameraName.c_str(),CheckUtil::getCurTimeHMS().c_str()); return 0; } int QX_Merge_Analysis::InitData() { m_reultList.Init(); m_pMergedetlog = std::make_shared(); m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "QX_Merge_Analysis", "InitData %s",CheckUtil::getCurTimeHMS().c_str()); { std::lock_guard lock(mtx_QXList); for (int i = 0; i < QX_ANALYSIS_COUNT; i++) { m_QXList[i].Init(); } } return 0; } int QX_Merge_Analysis::GetReusult(QX_Analysis_Result_List *&presult) { presult = &m_reultList; return 0; } void QX_Merge_Analysis::SetConfig(std::string cameraName, int qxidx, QXAnalysis_Config config) { if (cameraName == "") { return; } // if (cameraName != QX_MEREGE_CONFIG_CAMERA_NAME) // { // return; // } ALL_QX_ParamList *pqxConfigList = nullptr; { std::lock_guard lock(mtx_ConfigList); // pqxConfigList = &m_ConfigList[qxidx]; pqxConfigList->configlsit.push_back(config); } m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "QX_Merge_Analysis", "SetConfig cameraName %s qxidx %d ", cameraName.c_str(), qxidx); } void QX_Merge_Analysis::InitConfig(std::string cameraName) { // if (cameraName != QX_MEREGE_CONFIG_CAMERA_NAME) // { // return; // } { std::lock_guard lock(mtx_ConfigList); for (int i = 0; i < QX_ANALYSIS_COUNT; i++) { m_ConfigList[i].Init(); } } m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "QX_Merge_Analysis", "InitConfig cameraName %s ", cameraName.c_str()); } void QX_Merge_Analysis::SetbaseCheckFunction(std::string cameraName, ALLChannelCheckFunction *pChannelFuntion, BaseCheckFunction *pbaseCheckFunction) { if (cameraName == "") { return; } // if (cameraName != QX_MEREGE_CONFIG_CAMERA_NAME) // { // return; // } m_pChannelFuntion = pChannelFuntion; m_pbaseCheckFunction = pbaseCheckFunction; } int QX_Merge_Analysis::ConfigTypeToQXAnalysis(int nconfigType) { int QXAnalysis_type = -1; switch (nconfigType) { case CONFIG_QX_NAME_POL_Cell: QXAnalysis_type = QX_ANALYSIS_POL_CELL; // 异物 break; case CONFIG_QX_NAME_AD: QXAnalysis_type = QX_ANALYSIS_AD; // 暗点 break; case CONFIG_QX_NAME_Scratch_L1: case CONFIG_QX_NAME_Scratch_L2: QXAnalysis_type = QX_ANALYSIS_Scratch; // 划伤 break; case CONFIG_QX_NAME_X_line: case CONFIG_QX_NAME_Y_line: case CONFIG_QX_NAME_line: case CONFIG_QX_NAME_Fangge: QXAnalysis_type = QX_ANALYSIS_LINE; // 线类 break; case CONFIG_QX_NAME_MTX: QXAnalysis_type = QX_ANALYSIS_MTX; // MTX break; // case CONFIG_QX_NAME_Broken_line: // QXAnalysis_type = QX_ANALYSIS_ALL, // MTX&异物 // break; default: QXAnalysis_type = -1; break; } return QXAnalysis_type; } bool QX_Merge_Analysis::Idx(int qxidx) { if (qxidx < 0 || qxidx >= QX_ANALYSIS_COUNT) { return false; } return true; } bool QX_Merge_Analysis::AddQxInfo(int qxidx, QX_Info qxinfo, std::shared_ptr plog, std::shared_ptr pchannelLog) { std::string channel_name = qxinfo.channel_name; std::string cam_name = qxinfo.camera_name; ALL_QX_ParamList *pconfigList = nullptr; { std::lock_guard lock(mtx_ConfigList); pconfigList = &m_ConfigList[qxidx]; } if (pconfigList == nullptr) { plog->AddCheckstr(PrintLevel_3, 3, "AddQxInfo", "cam_name = %s config error", cam_name.c_str()); return false; } if (!Idx(qxidx)) { plog->AddCheckstr(PrintLevel_3, 3, "AddQxInfo", "qxidx error"); return false; } // 初步筛选一次 bool badd = false; { std::lock_guard lock(mtx_ConfigList); for (int i = 0; i < (int)pconfigList->configlsit.size(); i++) { QXAnalysis_Config *pconfig = &pconfigList->configlsit.at(i); // 面积 灰阶满足要求 if (qxinfo.area >= pconfig->area && qxinfo.hj >= pconfig->hj && qxinfo.length >= pconfig->len && qxinfo.density >= pconfig->density) { badd = true; } plog->AddCheckstr(PrintLevel_3, 3, "preA", "add = %s congfig idx %d / %d ", BOOL_TO_STR(badd), i, (int)pconfigList->configlsit.size()); plog->AddCheckstr(PrintLevel_4, 3, "Area", "%s -> %f %s %f ", BOOL_TO_STR(qxinfo.area >= pconfig->area), qxinfo.area, BOOL_TO_ThanLess(qxinfo.area >= pconfig->area), pconfig->area); plog->AddCheckstr(PrintLevel_4, 3, "HJ", "%s -> %f %s %d ", BOOL_TO_STR(qxinfo.hj >= pconfig->hj), qxinfo.hj, BOOL_TO_ThanLess(qxinfo.hj >= pconfig->hj), pconfig->hj); plog->AddCheckstr(PrintLevel_4, 3, "Len", "%s -> %f %s %f ", BOOL_TO_STR(qxinfo.length >= pconfig->len), qxinfo.length, BOOL_TO_ThanLess(qxinfo.length >= pconfig->len), pconfig->len); plog->AddCheckstr(PrintLevel_4, 3, "md", "%s -> %f %s %f ", BOOL_TO_STR(qxinfo.density >= pconfig->density), qxinfo.density, BOOL_TO_ThanLess(qxinfo.density >= pconfig->density), pconfig->density); if (badd) { break; /* code */ } } } { std::lock_guard lock(mtx_QXList); if (badd) { QX_channel_List *pQXChannelList = nullptr; for (auto &config : m_QXList[qxidx].channelqxList) { if (config.channel_name == channel_name) { pQXChannelList = &config; break; } } if (pQXChannelList == nullptr) { plog->AddCheckstr(PrintLevel_3, 3, "AddQxInfo", "new channel_name %s ", channel_name.c_str()); QX_channel_List tempchannel; tempchannel.channel_name = channel_name; tempchannel.pChannelDetlog = pchannelLog; tempchannel.qxList.push_back(qxinfo); m_QXList[qxidx].channelqxList.push_back(tempchannel); } else { plog->AddCheckstr(PrintLevel_3, 3, "AddQxInfo", "have channel_name %s ", channel_name.c_str()); pQXChannelList->pChannelDetlog2 = pchannelLog; pQXChannelList->qxList.push_back(qxinfo); } m_pMergedetlog->AddCheckstr(PrintLevel_3, 3, "AddQxInfo", "m_QXList[%d].channelqxList.size() = %d cam %s channel %s %s", qxidx, (int)m_QXList[qxidx].channelqxList.size(), cam_name.c_str(), channel_name.c_str(), CheckUtil::getCurTimeHMS().c_str()); } } return badd; } bool QX_Merge_Analysis::setSendStatus(std::string cameraName, RUN_STATUS_ status) { { std::lock_guard lock(mtx_status); m_statusList[cameraName] = status; } cv_status.notify_all(); return false; } /** * @brief 等待所有任务完成 * @param timeoutMs 超时时间(毫秒) * @return bool 如果所有任务在超时前完成返回true,否则返回false */ bool QX_Merge_Analysis::waitComplete(int timeoutMs) { // 使用互斥锁保护共享资源m_statusList std::unique_lock lock(mtx_status); // 记录开始时间 auto startTime = std::chrono::steady_clock::now(); // 循环检查直到所有任务完成或超时或退出标志被设置 while (!m_bExit) { // 假设所有任务已完成 bool allComplete = !m_statusList.empty(); // 遍历状态列表检查每个任务的状态 for (auto &it : m_statusList) { // 如果发现未完成的任务,设置allComplete为false并跳出循环 if (it.second != RUN_STATUS_COMPLETE) { allComplete = false; break; } } // 如果所有任务都已完成,返回true if (allComplete) { return true; } auto elapsedMs = std::chrono::duration_cast( std::chrono::steady_clock::now() - startTime) .count(); if (elapsedMs >= timeoutMs) { return false; } cv_status.wait_for(lock, std::chrono::milliseconds(100)); } return false; } int QX_Merge_Analysis::Run(int nId) { std::unique_lock lock(mtx_status); while (!m_bExit) { cv_status.wait(lock, [this]() { if (m_bExit) return true; if (m_statusList.empty()) return false; for (auto &it : m_statusList) { if (it.second != RUN_STATUS_READY) return false; } return true; }); if (m_bExit) break; if (!m_statusList.empty()) { for (auto &it : m_statusList) { it.second = RUN_STATUS_BUSY; } lock.unlock(); StartAnalysis(); lock.lock(); for (auto &it : m_statusList) { it.second = RUN_STATUS_COMPLETE; } cv_status.notify_all(); } } return 0; } int QX_Merge_Analysis::StartThread(int nId) { // 开启检测线程 ptr_thread_Run = std::make_shared(std::bind(&QX_Merge_Analysis::Run, this, nId)); return 0; } int QX_Merge_Analysis::StopThread() { m_bExit = true; cv_status.notify_all(); if (ptr_thread_Run != nullptr) { if (ptr_thread_Run->joinable()) { ptr_thread_Run->join(); } } return 0; } int QX_Merge_Analysis::StartAnalysis() { m_pMergedetlog->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "==========Start========%s", CheckUtil::getCurTimeHMS().c_str()); // 分析每一个缺陷类型 for (int i = 0; i < QX_ANALYSIS_COUNT; i++) { if (QX_ANALYSIS_POL_CELL != i && QX_ANALYSIS_AD != i && QX_ANALYSIS_MTX != i && QX_ANALYSIS_Scratch != i && QX_ANALYSIS_LINE != i) { m_pMergedetlog->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "== %d 11", i); continue; } if (m_QXList[i].channelqxList.size() <= 0 || m_ConfigList[i].configlsit.size() <= 0) { m_pMergedetlog->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "== %d channelqxList %ld configlsit %ld", i, m_QXList[i].channelqxList.size(), m_ConfigList[i].configlsit.size()); continue; } m_pMergedetlog->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "%s start", QX_ANALYSIS_NAME_Names[i].c_str()); Analysis_QXtype(&m_QXList[i], i); m_pMergedetlog->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "%s end", QX_ANALYSIS_NAME_Names[i].c_str()); } // presult = &m_reultList; return 0; } int QX_Merge_Analysis::Analysis_single_Config(QXAnalysis_Config *pconfig, QX_channel_List *pqxList, int qx_type, std::shared_ptr pchannelLog) { pchannelLog->AddCheckstr(PrintLevel_2, 3, "param", " okparam = %d area %f max_area %f hj %d num %d dis %f len %f md %f", pconfig->bok, pconfig->area, pconfig->sum_area, pconfig->hj, pconfig->num, pconfig->dis, pconfig->len, pconfig->density); float sumarea = 0; float fmaxarea = 0; int num = 0; // 遍历每一个相机 Pre_Analysisy_Param param; param.fAreaMin = pconfig->area; param.fHJMin = pconfig->hj; param.fLenMin = pconfig->len; param.fMdMin = pconfig->density; pqxList->Initstatus(); for (int i = 0; i < (int)pqxList->qxList.size(); i++) { std::string str = ""; // 面积 灰阶满足要求 if (pqxList->preDet(i, param, str)) { num++; pqxList->qxList.at(i).nstatus = 1; sumarea += pqxList->qxList.at(i).area; if (pqxList->qxList.at(i).area > fmaxarea) { fmaxarea = pqxList->qxList.at(i).area; } } pchannelLog->AddCheckstr(PrintLevel_3, 3, "preA", "qx_idx %d : %s count = %d; %s ", i, Re_TO_STR_Pass_1(pqxList->qxList.at(i).nstatus), num, pqxList->qxList.at(i).GetInfo().c_str(), str.c_str()); } if (num <= 0 && pconfig->num > 0) { pchannelLog->AddCheckstr(PrintLevel_3, 3, "result", "fail num = 0"); return 0; } // 对距离有要求 if (pconfig->dis > 0) { pqxList->claDis(); } if (pconfig->bok == 1 && num > 0) { // 只要有一个条件大于阈值参数,就NG; std::string strresult = "param type=OK:"; bool bresult = true; // 数量不满足要求。 if (num >= pconfig->num) { bresult = false; strresult += "Num = false : " + std::to_string(num) + ">=" + std::to_string(pconfig->num) + ";"; int are = QX_ERROR_TYPE_NUM; for (int i = 0; i < (int)pqxList->qxList.size(); i++) { if (pqxList->qxList.at(i).nstatus == 1) { pqxList->qxList.at(i).nqx_type = QX_ERROR_TYPE_NUM; } } } else { strresult += "Num = true: " + std::to_string(num) + "<" + std::to_string(pconfig->num) + ";"; } float fmaxLen = 0; bool blenerror = false; float allmindis = 99999999999; bool bdiserror = false; for (int i = 0; i < (int)pqxList->qxList.size(); i++) { if (pqxList->qxList.at(i).nstatus == 1) { if (pqxList->qxList.at(i).length > fmaxLen) { fmaxLen = pqxList->qxList.at(i).length; } // 长度超过阈值 if (pqxList->qxList.at(i).length > pconfig->len) { blenerror = true; pqxList->qxList.at(i).nqx_type = QX_ERROR_TYPE_Len; } // 对距离有要求 if (pconfig->dis > 0) { if (pqxList->qxList.at(i).tem_dis_idx >= 0) { // 最小距离 大于 阈值 if (pqxList->qxList.at(i).tem_dis <= pconfig->dis) { bdiserror = true; pqxList->qxList.at(i).nqx_type = QX_ERROR_TYPE_DIS; pqxList->qxList.at(i).fmindis = pqxList->qxList.at(i).tem_dis; pqxList->qxList.at(i).nmindis_BlobIdx = pqxList->qxList.at(i).tem_dis_idx; } if (pqxList->qxList.at(i).tem_dis < allmindis) { allmindis = pqxList->qxList.at(i).tem_dis; } } } } } if (blenerror) { bresult = false; strresult += "Len = false : " + std::to_string(fmaxLen) + ">=" + std::to_string(pconfig->len) + ";"; } else { strresult += "Len = true: " + std::to_string(fmaxLen) + ">=" + std::to_string(pconfig->len) + ";"; } if (bdiserror) { bresult = false; strresult += "dis = false : " + std::to_string(allmindis) + ">=" + std::to_string(pconfig->dis) + ";"; } else { strresult += "dis = true: " + std::to_string(allmindis) + ">=" + std::to_string(pconfig->dis) + ";"; } for (int i = 0; i < (int)pqxList->qxList.size(); i++) { if (pqxList->qxList.at(i).nqx_type > QX_ERROR_TYPE_OK) { if (pqxList->qxList.at(i).result == 0) { pqxList->qxList.at(i).result = 1; QX_RESULT tem; tem.blobIdx = pqxList->qxList.at(i).blobIdx; tem.qx_Num = num; tem.mindis = pqxList->qxList.at(i).fmindis; tem.flen = pqxList->qxList.at(i).length; tem.error_Type = pqxList->qxList.at(i).nqx_type; tem.camera_name = pqxList->qxList.at(i).camera_name; tem.channel_name = pqxList->qxList.at(i).channel_name; pchannelLog->AddCheckstr(PrintLevel_4, 3, "result = NG", "Add New qx,Blob idx %d type %d num %d dis %f len %f ", tem.blobIdx, tem.error_Type, tem.qx_Num, tem.mindis, tem.flen); m_reultList.resultList.push_back(tem); } } } } else { std::string strresult = "param type=NG:"; bool bpass = true; if (num >= pconfig->num) { strresult += "Num = true : " + std::to_string(num) + ">=" + std::to_string(pconfig->num) + ";"; } else { bpass = false; strresult += "Num = false: " + std::to_string(num) + "<" + std::to_string(pconfig->num) + ";"; } if (fmaxarea >= pconfig->sum_area) { strresult += "maxarea = true : " + std::to_string(fmaxarea) + ">=" + std::to_string(pconfig->sum_area) + ";"; } else { bpass = false; strresult += "maxarea = false: " + std::to_string(fmaxarea) + "<" + std::to_string(pconfig->sum_area) + ";"; } // 数量满足要求 if (bpass) { float allmindis = 99999999999; for (int i = 0; i < (int)pqxList->qxList.size(); i++) { // pchannelLog->AddCheckstr(PrintLevel_4, 3, "ddddddd", "%d %f %f %s ", // i, pqxList->qxList.at(i).plocatin_mm.x, pqxList->qxList.at(i).plocatin_mm.y, // pqxList->qxList.at(i).GetInfo().c_str()); // 面积 灰阶满足要求 if (pqxList->qxList.at(i).nstatus == 1) { int minidx = -1; bool bdis = true; double remindis = 0; // 对距离有要求 if (pconfig->dis > 0) { // pchannelLog->AddCheckstr(PrintLevel_3, 3, "result", "%d %f",i,pqxList->qxList.at(i).tem_dis); if (pqxList->qxList.at(i).tem_dis_idx >= 0) { // 最小距离 大于 阈值 if (pqxList->qxList.at(i).tem_dis > pconfig->dis) { bdis = false; } if (pqxList->qxList.at(i).tem_dis < allmindis) { allmindis = pqxList->qxList.at(i).tem_dis; } } remindis = pqxList->qxList.at(i).tem_dis; } // 距离满足要求 if (bdis && pqxList->qxList.at(i).result == 0) { pqxList->qxList.at(i).result = 1; QX_RESULT tem; tem.blobIdx = pqxList->qxList.at(i).blobIdx; tem.qx_Num = num; tem.mindis = remindis; tem.camera_name = pqxList->qxList.at(i).camera_name; tem.channel_name = pqxList->qxList.at(i).channel_name; if (pconfig->num <= 0 && pconfig->dis <= 0) { tem.error_Type = QX_ERROR_TYPE_AREA; } else if (pconfig->dis <= 0) { tem.error_Type = QX_ERROR_TYPE_NUM; } else { tem.error_Type = QX_ERROR_TYPE_DIS; } pchannelLog->AddCheckstr(PrintLevel_4, 3, "Add New QX", "result = NG, Add New qx,Blob idx %d -> num %d >= %d is true; dis %f <= %f is true; max_area %f >= %f is true ", tem.blobIdx, num, pconfig->num, remindis, pconfig->dis, fmaxarea, pconfig->sum_area); m_reultList.resultList.push_back(tem); } } } if (pconfig->dis > 0) { if (allmindis <= pconfig->dis) { strresult += "dis = true : " + std::to_string(allmindis) + "<=" + std::to_string(pconfig->dis) + ";"; } else { bpass = false; strresult += "dis = false : " + std::to_string(allmindis) + ">" + std::to_string(pconfig->dis) + ";"; } } else { strresult += "dis = true : dis param is 0"; } } if (!bpass) { pchannelLog->AddCheckstr(PrintLevel_2, 3, "result", "OK==>%s", strresult.c_str()); } else { pchannelLog->AddCheckstr(PrintLevel_2, 3, "result", "NG==>%s", strresult.c_str()); } } return 0; } int QX_Merge_Analysis::Analysis_QXtype(ALL_Qx_DataList *pALLTypeqxList, int qx_idx) { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "Num And Dis Judge", "pALLTypeqxList->channelqxList.size() %ld", pALLTypeqxList->channelqxList.size()); for (int i = 0; i < pALLTypeqxList->channelqxList.size(); i++) { QX_channel_List *pQXChannelList = &pALLTypeqxList->channelqxList[i]; Analysis_Channel(pQXChannelList, qx_idx); } // AD 要进行额外的分析 if (qx_idx == QX_ANALYSIS_AD) { Analysis_AD(pALLTypeqxList, qx_idx); } return 0; } int QX_Merge_Analysis::Analysis_Channel(QX_channel_List *pChannelqxList, int qx_idx) { int param_num = 0; int param_dis = 0; ALL_QX_ParamList *pConfigList = &m_ConfigList[qx_idx]; // 用单面相机的参数去处理 所有相机的缺陷。 m_pMergedetlog->AddCheckstr(PrintLevel_3, 3, "Num And Dis Judge", "pConfigList->configlsit.size() %ld", pConfigList->configlsit.size()); for (int i = 0; i < (int)pConfigList->configlsit.size(); i++) { pChannelqxList->pChannelDetlog->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", "QX %s channel %s param %d / %d Analysis start ", QX_ANALYSIS_NAME_Names[qx_idx].c_str(), pChannelqxList->channel_name.c_str(), i, (int)pConfigList->configlsit.size()); Analysis_single_Config(&pConfigList->configlsit.at(i), pChannelqxList, qx_idx, pChannelqxList->pChannelDetlog); } if (pChannelqxList->pChannelDetlog2 && pChannelqxList->pChannelDetlog) { for (auto log : pChannelqxList->pChannelDetlog->logList) { pChannelqxList->pChannelDetlog2->logList.push_back(log); } } return 0; } int QX_Merge_Analysis::Judge_OK_Config() { return 0; } int QX_Merge_Analysis::Judge_NG_Config() { return 0; } int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx) { AD_list.clear(); if (!m_pbaseCheckFunction) { return 1; } Base_Function_AD_Check *pAd_checkParma = &m_pbaseCheckFunction->ad_check; int product_AD_num = 0; // 整个产品的 暗点数目。 int check_s_Num = 0; int s_param_value = -1; int s_param_num = 0; // 遍历每个通道,找到开启的 进行分析。 for (int i = 0; i < pALLTypeqxList->channelqxList.size(); i++) { QX_channel_List *pQXChannelList = &pALLTypeqxList->channelqxList[i]; if (!pAd_checkParma) { continue; } if (pAd_checkParma && !pAd_checkParma->bOpen) { pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_2, 3, "Analysis_AD ", "channel %s AD Check is close", pQXChannelList->channel_name.c_str()); continue; } bool bana_num = false; bool bana_dis = false; bool bana_S = false; if (pAd_checkParma->analysis_num.bOpen) { bana_num = true; } if (pAd_checkParma->analysis_dis.bOpen) { bana_dis = true; } if (pAd_checkParma->analysis_s.bOpen) { bana_S = true; } { pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_2, 3, "Analysis_AD ", "NUM --> %s Param num check %d dis check %d S check %d", pQXChannelList->channel_name.c_str(), bana_num, bana_dis, bana_S); } if (!bana_num && !bana_dis && !bana_S) { continue; } for (int j = 0; j < pQXChannelList->qxList.size(); j++) { if (pQXChannelList->qxList[j].area >= pAd_checkParma->S_standard_1s.area && pQXChannelList->qxList[j].length >= pAd_checkParma->S_standard_1s.len) { } else { continue; } tem_AD_QX_Info tem_AD_qx; // 暗点信息 tem_AD_qx.channelidx = i; tem_AD_qx.qxidx = j; int s_det_value = 0; // 当前通道 要参与s标准分析 if (pAd_checkParma->analysis_s.bOpen) { s_param_num = pAd_checkParma->analysis_s.Check_s_Num; s_param_value = pAd_checkParma->analysis_s.Check_s_Value; if (pQXChannelList->qxList[j].area >= pAd_checkParma->S_standard_3s.area && pQXChannelList->qxList[j].length >= pAd_checkParma->S_standard_3s.len) { s_det_value = 3; pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_3, 3, "add AD ", "%d %s 3S: cur[A %0.2f L %0.2f] parm[A %0.2f L %0.2f]", j, pQXChannelList->channel_name.c_str(), pQXChannelList->qxList[j].area, pQXChannelList->qxList[j].length, pAd_checkParma->S_standard_3s.area, pAd_checkParma->S_standard_3s.len); } else if (pQXChannelList->qxList[j].area >= pAd_checkParma->S_standard_2s.area && pQXChannelList->qxList[j].length >= pAd_checkParma->S_standard_2s.len) { s_det_value = 2; pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_3, 3, " add AD ", "%d %s 2S: cur[A %0.2f L %0.2f] parm[A %0.2f L %0.2f]", j, pQXChannelList->channel_name.c_str(), pQXChannelList->qxList[j].area, pQXChannelList->qxList[j].length, pAd_checkParma->S_standard_2s.area, pAd_checkParma->S_standard_1s.len); } else { pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_3, 3, "add AD ", "%d %s 1S: cur[A %0.2f L %0.2f] parm[A %0.2f L %0.2f]", j, pQXChannelList->channel_name.c_str(), pQXChannelList->qxList[j].area, pQXChannelList->qxList[j].length, pAd_checkParma->S_standard_2s.area, pAd_checkParma->S_standard_1s.len); s_det_value = 1; } if (s_det_value >= s_param_value) { check_s_Num++; } } cv::Rect roi = pQXChannelList->qxList[j].product_roi; int list_idx = -1; int channel_s = 0; bool bnew_add = true; for (int idx = 0; idx < AD_list.size(); idx++) { float fiou = CheckUtil::CalIoU(AD_list.at(idx).roi, roi); if (fiou > 0.15) { list_idx = idx; } } // 在list已存在。 if (list_idx >= 0) { AD_list.at(list_idx).num++; AD_list.at(list_idx).numIdxList.push_back(tem_AD_qx); channel_s = AD_list.at(list_idx).num; if (s_det_value == 1) { AD_list.at(list_idx).num_1s++; } else if (s_det_value == 2) { AD_list.at(list_idx).num_2s++; AD_list.at(list_idx).num_2sIdxList.push_back(tem_AD_qx); } else { AD_list.at(list_idx).num_3s++; AD_list.at(list_idx).num_3sIdxList.push_back(tem_AD_qx); } bnew_add = false; } else { // 在list不存在。 AD_Channel_Info_ tem; tem.roi = roi; tem.location_product_mm = pQXChannelList->qxList[j].pLocation_Product_mm; tem.num = 1; channel_s = 1; tem.fdis = 99999999999; tem.numIdxList.push_back(tem_AD_qx); if (s_det_value == 1) { tem.num_1s++; } else if (s_det_value == 2) { tem.num_2s++; tem.num_2sIdxList.push_back(tem_AD_qx); } else { tem.num_3s++; tem.num_3sIdxList.push_back(tem_AD_qx); } AD_list.push_back(tem); // 如果要参与数量统计 if (bana_num) { product_AD_num++; } } m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "AD list size %ld; channel %s blob idx %d,new_add %d ,A %f len %f p %d %d", AD_list.size(), pQXChannelList->channel_name.c_str(), j, bnew_add, pQXChannelList->qxList[j].area, pQXChannelList->qxList[j].length, roi.x, roi.y); pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_2, 3, "Analysis_AD ", "%d %s AD list size %ld product_AD_num Num %d; cur channel num = %d;cur S = %ds; param :%ds num %d;->S check_s_Num = %d", j, pQXChannelList->channel_name.c_str(), AD_list.size(), product_AD_num, channel_s, s_det_value, s_param_value, s_param_num, check_s_Num); } } float min_dis = 9999999999; // 求最小距离 if (true) { for (int ad_i = 0; ad_i < AD_list.size(); ad_i++) { for (int ad_j = 0; ad_j < AD_list.size(); ad_j++) { if (ad_i == ad_j) { continue; } // double dis = DistanceBetweenRectCenters(AD_list.at(ad_i).roi, AD_list.at(ad_j).roi, // 1, // 1); float dis = CheckUtil::calDis(AD_list.at(ad_i).location_product_mm, AD_list.at(ad_j).location_product_mm); if (dis < AD_list.at(ad_i).fdis) { AD_list.at(ad_i).fdis = dis; AD_list.at(ad_i).dist_idx = ad_j; if (dis < min_dis) { min_dis = dis; } } } } } int A_2S_num = 0; int A_3S_num = 0; // 统计 2s 总数 if (s_param_value > 0) { int channels = 0; int oneimgs = check_s_Num; for (int ad_i = 0; ad_i < AD_list.size(); ad_i++) { if (AD_list.at(ad_i).num > 1) { AD_list.at(ad_i).num_2s++; for (int i = 0; i < AD_list.at(ad_i).numIdxList.size(); i++) { AD_list.at(ad_i).num_2sIdxList.push_back(AD_list.at(ad_i).numIdxList.at(i)); } } A_2S_num += AD_list.at(ad_i).num_2s; A_3S_num += AD_list.at(ad_i).num_3s; if(AD_list.at(ad_i).num_1s >= 3) A_3S_num++; m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "AD_list %d %s", ad_i, AD_list.at(ad_i).GetInfo().c_str()); } m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "product_AD_num %d 2S_num = %d 3S_num s = %d min_dis %0.2f", product_AD_num, A_2S_num, A_3S_num, min_dis); } for (int i = 0; i < pALLTypeqxList->channelqxList.size(); i++) { QX_channel_List *pQXChannelList = &pALLTypeqxList->channelqxList[i]; if (!pAd_checkParma->bOpen) { continue; } bool bNG = false; bool NG_num = false; bool NG_3S = false; bool NG_2S = false; bool NG_dis = false; if (pAd_checkParma->analysis_num.bOpen) { // 数量分析 if (product_AD_num >= pAd_checkParma->analysis_num.numT) { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "Num Analysis --> %s result NG ,product_AD_num %d >= parm num %d", pQXChannelList->channel_name.c_str(), product_AD_num, pAd_checkParma->analysis_num.numT); bNG = true; NG_num = true; } else { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "Num Analysis--> %s result OK ,product_AD_num %d < parm num %d", pQXChannelList->channel_name.c_str(), product_AD_num, pAd_checkParma->analysis_num.numT); } } // 不NG if (!bNG) { // 3S直接 NG if (pAd_checkParma->analysis_s.NG_3s) { // 数量分析 if (A_3S_num >= 1) { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "3S Analysis --> %s result NG 3S %d >= 1", pQXChannelList->channel_name.c_str(), A_3S_num); bNG = true; NG_3S = true; } else { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "3S Analysis --> %s result OK 3S %d < 1", pQXChannelList->channel_name.c_str(), A_3S_num); } } } // 不NG if (!bNG) { // 距离判断 if (pAd_checkParma->analysis_dis.bOpen) { // 数量分析 if (min_dis <= pAd_checkParma->analysis_dis.disT) { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "Dis Analysis--> %s Dis result NG ,min dis %f <= parm dis %f", pQXChannelList->channel_name.c_str(), min_dis, pAd_checkParma->analysis_dis.disT); bNG = true; NG_2S = true; } else { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "Dis Analysis--> %s Dis result OK ,min dis %f > parm dis %f", pQXChannelList->channel_name.c_str(), min_dis, pAd_checkParma->analysis_dis.disT); } } } // 不NG if (!bNG) { // S标准判断 if (pAd_checkParma->analysis_s.bOpen) { // 数量分析 if (A_2S_num >= pAd_checkParma->analysis_s.Check_s_Num) { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "S Analysis--> %s result NG , Check %ds Num %d >= parm S Num %d", pQXChannelList->channel_name.c_str(), pAd_checkParma->analysis_s.Check_s_Value, A_2S_num, pAd_checkParma->analysis_s.Check_s_Num); bNG = true; NG_2S = true; } else { m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "S Analysis--> %s result OK , Check %ds Num %d < parm S Num %d", pQXChannelList->channel_name.c_str(), pAd_checkParma->analysis_s.Check_s_Value, A_2S_num, pAd_checkParma->analysis_s.Check_s_Num); } } } // 已经NG if (bNG) { QX_channel_List *pqxList = pQXChannelList; for (int i = 0; i < (int)pqxList->qxList.size(); i++) { if (pqxList->qxList.at(i).result == 0) { pqxList->qxList.at(i).result = 1; QX_RESULT tem; tem.blobIdx = pqxList->qxList.at(i).blobIdx; tem.mindis = pqxList->qxList.at(i).fmindis; tem.flen = pqxList->qxList.at(i).length; tem.error_Type = pqxList->qxList.at(i).nqx_type; tem.camera_name = pqxList->qxList.at(i).camera_name; tem.channel_name = pqxList->qxList.at(i).channel_name; pqxList->pChannelDetlog->AddCheckstr(PrintLevel_4, 3, "result = NG", "Add New qx,Blob idx %d type %d num %d dis %f len %f ", tem.blobIdx, tem.error_Type, tem.qx_Num, tem.mindis, tem.flen); m_pMergedetlog->AddCheckstr(PrintLevel_4, 3, "result = NG", "%s Add New qx,Blob idx %d type %d num %d dis %f len %f ", tem.channel_name.c_str(), tem.blobIdx, tem.error_Type, tem.qx_Num, tem.mindis, tem.flen); m_reultList.resultList.push_back(tem); } } } } return 0; } ChannelCheckFunction *QX_Merge_Analysis::GetChannelFuntion(std::string strChannelName) { ChannelCheckFunction *p = NULL; for (int i = 0; i < m_pChannelFuntion->channelFunctionArr.size(); i++) { if (CheckUtil::compareIgnoreCase(m_pChannelFuntion->channelFunctionArr[i].strChannelName, strChannelName)) { p = &m_pChannelFuntion->channelFunctionArr[i]; } } return p; } double QX_Merge_Analysis::DistanceBetweenRectCenters(const cv::Rect &rect1, const cv::Rect &rect2, float fx, float fy) { // 计算矩形1的中心点 cv::Point center1(rect1.x + rect1.width / 2, rect1.y + rect1.height / 2); // 计算矩形2的中心点 cv::Point center2(rect2.x + rect2.width / 2, rect2.y + rect2.height / 2); center1.x *= fx; center1.y *= fy; center2.x *= fx; center2.y *= fy; // 计算中心点之间的欧几里得距离 double distance = cv::norm(center1 - center2); return distance; }