feat 主通道为空,使用次通道走老逻辑v2

dev_lsy
liusiyang 1 week ago
parent badc3fa4c6
commit 7ef04b6234

@ -214,9 +214,17 @@ private:
int Judge_OK_Config();
int Judge_NG_Config();
int Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx);
// pAllowChannels 非空时仅列表内通道参与分析(主通道未配置时的回退: 仅次通道);
// nullptr=不过滤;非空但为空列表=不做任何通道分析(直接返回)
int Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx, const std::vector<std::string> *pAllowChannels = nullptr);
int Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_idx);
// 绑定分析的主通道是否未配置(2s 或 3s 的主通道列表为空);
// 只按配置判断,与本次产品是否检出缺陷无关(良品主通道本来就没暗点,按缺陷判断会频繁误回退)
bool IsADBindMainChannelConfigEmpty();
// 绑定分析的次通道列表(second_channel_2s + second_channel_3s, 去重并过滤空名)
std::vector<std::string> GetADBindSecondChannels();
// 关联过滤源过滤:移除与关联通道过滤源缺陷重叠的缺陷,使其不参与后续数量/距离/S分析
int FilterCorrelatedDirtyQx(ALL_Qx_DataList *pALLTypeqxList);

@ -303,6 +303,29 @@ static bool IsValidCorrelatedName(const std::string &strName)
return true;
}
/**
* @brief 判断通道名是否在通道列表中(忽略大小写)
* 通道配置由人工填写(如 "Blue" 与实际通道名 "BLUE"),大小写敏感匹配会漏掉应参与的通道
* @param channels 通道列表
* @param channelName 待判断的通道名
* @return bool 在列表中返回true
*/
static bool IsChannelInList(const std::vector<std::string> &channels, const std::string &channelName)
{
if (channelName.empty())
{
return false;
}
for (int i = 0; i < (int)channels.size(); i++)
{
if (CheckUtil::compareIgnoreCase(channels.at(i), channelName))
{
return true;
}
}
return false;
}
/**
* @brief 判断缺陷类型是否为配置的关联过滤源类型(analysis_bind.correlated_types,
* 如 "Dirty_L0"/"Dirty_L1"/"Dirty_L2"/"AD"), 登记与过滤两处共用此判定
@ -712,7 +735,7 @@ int QX_Merge_Analysis::Analysis_single_Config(QXAnalysis_Config *pconfig, QX_cha
if (qx_type == QX_ANALYSIS_AD && m_pbaseCheckFunction)
{
std::vector<std::string> merge_analysy_region_sf = m_pbaseCheckFunction->ad_check.analysis_sf.region_sf;
if (std::find(merge_analysy_region_sf.begin(), merge_analysy_region_sf.end(), pqxList->channel_name) == merge_analysy_region_sf.end())
if (!IsChannelInList(merge_analysy_region_sf, pqxList->channel_name))
{
pchannelLog->AddCheckstr(PrintLevel_1, 3, "Analysis_single_Config", "merge_analysy_region_sf not found %s --> skip", pqxList->channel_name.c_str());
return 0;
@ -999,6 +1022,57 @@ int QX_Merge_Analysis::Analysis_single_Config(QXAnalysis_Config *pconfig, QX_cha
return 0;
}
/**
* @brief 绑定分析的主通道是否未配置(2s 或 3s 的主通道列表为空)
* 只按配置判断,与本次产品是否检出缺陷无关:良品主通道本来就没暗点,
* 若按“本次无匹配通道”判定回退,则每个良品都会回退,把次通道噪声直接判成 NG
* @return bool 需要回退用次通道走 Analysis_AD 老逻辑返回true
*/
bool QX_Merge_Analysis::IsADBindMainChannelConfigEmpty()
{
if (m_pbaseCheckFunction == nullptr)
{
return false;
}
const AD_Analysisy_Bind &bind = m_pbaseCheckFunction->ad_check.analysis_bind;
// 2s/3s 任一主通道未配置,就无法完成对应的绑定判定,整体回退
return bind.main_channel_2s.empty() || bind.main_channel_3s.empty();
}
/**
* @brief 取绑定分析的次通道列表(second_channel_2s + second_channel_3s)
* 去重忽略大小写,并过滤空名
* @return std::vector<std::string> 次通道名列表
*/
std::vector<std::string> QX_Merge_Analysis::GetADBindSecondChannels()
{
std::vector<std::string> channels;
if (m_pbaseCheckFunction == nullptr)
{
return channels;
}
const AD_Analysisy_Bind &bind = m_pbaseCheckFunction->ad_check.analysis_bind;
const std::vector<std::string> *pListArr[2] = {&bind.second_channel_2s, &bind.second_channel_3s};
for (int i = 0; i < 2; i++)
{
const std::vector<std::string> &channelList = *pListArr[i];
for (int j = 0; j < (int)channelList.size(); j++)
{
const std::string &channelName = channelList.at(j);
if (channelName.empty())
{
continue;
}
// 2s/3s 重复配同一通道时只保留一份
if (!IsChannelInList(channels, channelName))
{
channels.push_back(channelName);
}
}
}
return channels;
}
int QX_Merge_Analysis::Analysis_QXtype(ALL_Qx_DataList *pALLTypeqxList, int qx_idx)
{
@ -1021,17 +1095,41 @@ int QX_Merge_Analysis::Analysis_QXtype(ALL_Qx_DataList *pALLTypeqxList, int qx_i
Analysis_Channel(pQXChannelList, qx_idx);
}
// AD 要进行额外的分析
if (qx_idx == QX_ANALYSIS_AD)
if (qx_idx == QX_ANALYSIS_AD && m_pbaseCheckFunction != nullptr)
{
if (m_pbaseCheckFunction->ad_check.analysis_bind.bUse)
{
if (IsADBindMainChannelConfigEmpty())
{
if(m_pbaseCheckFunction->ad_check.analysis_bind.bUse)
// 主通道未配置(2s 或 3s 的主通道列表为空):无法做绑定判定,
// 回退用次通道列表走 Analysis_AD 老逻辑(产品级数量/距离/S 分析)。
// 关联通道过滤(FilterCorrelatedDirtyQx)已在上面执行,回退路径同样受其保护。
std::vector<std::string> fallback_channels = GetADBindSecondChannels();
std::string strFallbackChannels;
for (int k = 0; k < (int)fallback_channels.size(); k++)
{
if (k > 0)
{
strFallbackChannels += ",";
}
strFallbackChannels += fallback_channels.at(k);
}
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "Analysis_AD_Bind",
"main channel config empty(main_2s %d main_3s %d) --> fallback Analysis_AD (only second channels: %s)",
(int)m_pbaseCheckFunction->ad_check.analysis_bind.main_channel_2s.size(),
(int)m_pbaseCheckFunction->ad_check.analysis_bind.main_channel_3s.size(),
fallback_channels.empty() ? "<empty>" : strFallbackChannels.c_str());
Analysis_AD(pALLTypeqxList, qx_idx, &fallback_channels);
}
else
{
Analysis_AD_Bind(pALLTypeqxList, qx_idx);
}
}
else
{
Analysis_AD(pALLTypeqxList, qx_idx);
}
}
return 0;
@ -1073,7 +1171,7 @@ int QX_Merge_Analysis::Judge_NG_Config()
return 0;
}
int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx)
int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx, const std::vector<std::string> *pAllowChannels)
{
AD_list.clear();
if (!m_pbaseCheckFunction)
@ -1081,6 +1179,15 @@ int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx)
return 1;
}
// 回退模式(主通道未配置)且次通道也没配置:没有任何通道可参与,直接返回,
// 避免“空允许列表导致所有通道被 skip”的隐晦行为
if (pAllowChannels != nullptr && pAllowChannels->empty())
{
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "Analysis_AD",
"fallback allow list(second channels) is empty --> skip AD analysis");
return 0;
}
Base_Function_AD_Check *pAd_checkParma = &m_pbaseCheckFunction->ad_check;
int product_AD_num = 0; // 整个产品的 暗点数目。
@ -1092,6 +1199,17 @@ int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx)
{
QX_channel_List *pQXChannelList = &pALLTypeqxList->channelqxList[i];
// 回退模式:只允许次通道列表内的通道参与分析(忽略大小写)
if (pAllowChannels != nullptr && !IsChannelInList(*pAllowChannels, pQXChannelList->channel_name))
{
if (pQXChannelList->pChannelDetlog)
{
pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_1, 3, "Analysis_AD",
"channel %s not in fallback allow list(second channels) --> skip",
pQXChannelList->channel_name.c_str());
}
continue;
}
if (!pAd_checkParma)
{
continue;
@ -1336,6 +1454,17 @@ int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx)
{
QX_channel_List *pQXChannelList = &pALLTypeqxList->channelqxList[i];
// 回退模式:只允许次通道列表内的通道被判定NG(忽略大小写)
if (pAllowChannels != nullptr && !IsChannelInList(*pAllowChannels, pQXChannelList->channel_name))
{
if (pQXChannelList->pChannelDetlog)
{
pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_1, 3, "Analysis_AD",
"channel %s not in fallback allow list(second channels) --> skip NG mark",
pQXChannelList->channel_name.c_str());
}
continue;
}
if (!pAd_checkParma->bOpen)
{
@ -1531,13 +1660,15 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
string cur_channel_name = pQXChannelList->channel_name;
if (std::find(main_channel_2s.begin(), main_channel_2s.end(), cur_channel_name) != main_channel_2s.end() ||
std::find(main_channel_3s.begin(), main_channel_3s.end(), cur_channel_name) != main_channel_3s.end())
// 通道名忽略大小写匹配:配置由人工填写(如 "Blue" 而实际通道是 "BLUE"),
// 大小写敏感匹配会让应参与的通道被静默排除
if (IsChannelInList(main_channel_2s, cur_channel_name) ||
IsChannelInList(main_channel_3s, cur_channel_name))
{
main_channel_s_qxList.push_back(pALLTypeqxList->channelqxList[i]);
}
if (std::find(second_channel_2s.begin(), second_channel_2s.end(), cur_channel_name) != second_channel_2s.end() ||
std::find(second_channel_3s.begin(), second_channel_3s.end(), cur_channel_name) != second_channel_3s.end())
if (IsChannelInList(second_channel_2s, cur_channel_name) ||
IsChannelInList(second_channel_3s, cur_channel_name))
{
second_channel_s_qxList.push_back(pALLTypeqxList->channelqxList[i]);
}
@ -1640,13 +1771,13 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
// roi_expand, fiou);
if (fiou > pAd_checkParma->analysis_iou.AD_IOU)
{
if (std::find(second_channel_2s.begin(), second_channel_2s.end(), second_channel_name) != second_channel_2s.end())
if (IsChannelInList(second_channel_2s, second_channel_name))
{
tmp_main_qxInfo.s_name_2.push_back(second_channel_name);
m_pMergedetlog->AddCheckstr(PrintLevel_3, 3, "Add 2s", "%s roi1 %s roi2 %s expand %d iou %f",
second_channel_name.c_str(), CheckUtil::GetRectString(roi_main).c_str(),CheckUtil::GetRectString(roi_second).c_str(),roi_expand, fiou);
}
if(std::find(second_channel_3s.begin(), second_channel_3s.end(), second_channel_name) != second_channel_3s.end())
if(IsChannelInList(second_channel_3s, second_channel_name))
{
tmp_main_qxInfo.s_name_3.push_back(second_channel_name);
m_pMergedetlog->AddCheckstr(PrintLevel_3, 3, "Add 3s", "%s roi1 %s roi2 %s expand %d iou %f",
@ -1724,7 +1855,7 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
{
continue;
}
if(std::find(merge_analysy_s_sf.begin(), merge_analysy_s_sf.end(), pQXChannelList->channel_name) != merge_analysy_s_sf.end())
if (IsChannelInList(merge_analysy_s_sf, pQXChannelList->channel_name))
{
}
else

Loading…
Cancel
Save