|
|
|
@ -4,6 +4,7 @@
|
|
|
|
#include <mutex>
|
|
|
|
#include <mutex>
|
|
|
|
#include <thread>
|
|
|
|
#include <thread>
|
|
|
|
#include <chrono>
|
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include "CheckUtil.hpp"
|
|
|
|
#include "CheckUtil.hpp"
|
|
|
|
#include "CheckConfigDefine.h"
|
|
|
|
#include "CheckConfigDefine.h"
|
|
|
|
|
|
|
|
|
|
|
|
@ -268,35 +269,83 @@ bool QX_Merge_Analysis::setSendStatus(std::string cameraName, RUN_STATUS_ status
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @brief 判断缺陷配置类型是否为脏污(dirty)
|
|
|
|
* @brief 关联过滤源类型名称转配置类型(如 "Dirty_L0" -> CONFIG_QX_NAME_Dirty_L0), 大小写不敏感
|
|
|
|
* @param nconfigType 缺陷配置类型 CONFIG_QX_NAME_
|
|
|
|
* @param strTypeName 缺陷类型名称(CONFIG_QX_NAME_Names 中的名称)
|
|
|
|
* @return bool 是脏污返回true
|
|
|
|
* @return int 匹配的配置类型, 未匹配返回 -1
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static bool IsDirtyConfigType(int nconfigType)
|
|
|
|
static int CorrelatedTypeNameToConfigType(const std::string &strTypeName)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)CONFIG_QX_NAME_Names.size(); i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return nconfigType == CONFIG_QX_NAME_Dirty_L0 ||
|
|
|
|
if (CheckUtil::compareIgnoreCase(strTypeName, CONFIG_QX_NAME_Names.at(i)))
|
|
|
|
nconfigType == CONFIG_QX_NAME_Dirty_L1 ||
|
|
|
|
{
|
|
|
|
nconfigType == CONFIG_QX_NAME_Dirty_L2;
|
|
|
|
return i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @brief 判断关联通道名称是否需要参与判断(为空或NONE则不参与)
|
|
|
|
* @brief 判断关联配置名称是否需要参与判断(为空或NONE则不参与)
|
|
|
|
* @param strChannelName 关联通道名称
|
|
|
|
* @param strName 关联通道/缺陷类型名称
|
|
|
|
* @return bool 需要判断返回true
|
|
|
|
* @return bool 需要判断返回true
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static bool IsValidCorrelatedChannel(const std::string &strChannelName)
|
|
|
|
static bool IsValidCorrelatedName(const std::string &strName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (strChannelName == "")
|
|
|
|
if (strName == "")
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (CheckUtil::compareIgnoreCase(strChannelName, "NONE"))
|
|
|
|
if (CheckUtil::compareIgnoreCase(strName, "NONE"))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief 判断缺陷类型是否为配置的关联过滤源类型(analysis_bind.correlated_types,
|
|
|
|
|
|
|
|
* 如 "Dirty_L0"/"Dirty_L1"/"Dirty_L2"/"AD"), 登记与过滤两处共用此判定
|
|
|
|
|
|
|
|
* 配置为空时兼容旧行为, 默认三种脏污
|
|
|
|
|
|
|
|
* @param nconfigType 缺陷配置类型 CONFIG_QX_NAME_
|
|
|
|
|
|
|
|
* @return bool 是过滤源返回true
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool QX_Merge_Analysis::IsCorrelatedSourceConfigType(int nconfigType)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 防御:非法类型直接返回
|
|
|
|
|
|
|
|
if (nconfigType < 0 || nconfigType >= CONFIG_QX_NAME_count)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 从配置读取过滤源类型名称并转换
|
|
|
|
|
|
|
|
std::vector<int> configTypes;
|
|
|
|
|
|
|
|
if (m_pbaseCheckFunction != nullptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const std::vector<std::string> &typeNames = m_pbaseCheckFunction->ad_check.analysis_bind.correlated_types;
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)typeNames.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!IsValidCorrelatedName(typeNames.at(i)))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int type = CorrelatedTypeNameToConfigType(typeNames.at(i));
|
|
|
|
|
|
|
|
if (type >= 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
configTypes.push_back(type);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!configTypes.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return std::find(configTypes.begin(), configTypes.end(), nconfigType) != configTypes.end();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 缺省过滤源(兼容旧配置):三种脏污
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool QX_Merge_Analysis::AddCorrelatedQxInfo(Correlated_Qx_Info_ qxinfo, std::shared_ptr<DetLog> plog)
|
|
|
|
bool QX_Merge_Analysis::AddCorrelatedQxInfo(Correlated_Qx_Info_ qxinfo, std::shared_ptr<DetLog> plog)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 防御:通道为空或ROI非法时不登记,避免无效数据参与后续判断
|
|
|
|
// 防御:通道为空或ROI非法时不登记,避免无效数据参与后续判断
|
|
|
|
@ -351,14 +400,14 @@ bool QX_Merge_Analysis::IsOverlapDirtyInCorrelatedChannel(const std::vector<std:
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 拷贝出需要比较的脏污缺陷列表,避免在锁内做IoU计算
|
|
|
|
// 拷贝出需要比较的过滤源缺陷列表,避免在锁内做IoU计算
|
|
|
|
std::vector<Correlated_Qx_Info_> dirtyList;
|
|
|
|
std::vector<Correlated_Qx_Info_> sourceList;
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(mtx_correlatedQx);
|
|
|
|
std::lock_guard<std::mutex> lock(mtx_correlatedQx);
|
|
|
|
for (int i = 0; i < (int)correlated_channels.size(); i++)
|
|
|
|
for (int i = 0; i < (int)correlated_channels.size(); i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const std::string &channel_name = correlated_channels.at(i);
|
|
|
|
const std::string &channel_name = correlated_channels.at(i);
|
|
|
|
if (!IsValidCorrelatedChannel(channel_name))
|
|
|
|
if (!IsValidCorrelatedName(channel_name))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -369,15 +418,15 @@ bool QX_Merge_Analysis::IsOverlapDirtyInCorrelatedChannel(const std::vector<std:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int j = 0; j < (int)it->second.size(); j++)
|
|
|
|
for (int j = 0; j < (int)it->second.size(); j++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (IsDirtyConfigType(it->second.at(j).config_qx_type))
|
|
|
|
if (IsCorrelatedSourceConfigType(it->second.at(j).config_qx_type))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
dirtyList.push_back(it->second.at(j));
|
|
|
|
sourceList.push_back(it->second.at(j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (dirtyList.empty())
|
|
|
|
if (sourceList.empty())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -386,22 +435,22 @@ bool QX_Merge_Analysis::IsOverlapDirtyInCorrelatedChannel(const std::vector<std:
|
|
|
|
cv::Rect roi_expanded(qx_product_roi.x - roi_expand, qx_product_roi.y - roi_expand,
|
|
|
|
cv::Rect roi_expanded(qx_product_roi.x - roi_expand, qx_product_roi.y - roi_expand,
|
|
|
|
qx_product_roi.width + roi_expand * 2, qx_product_roi.height + roi_expand * 2);
|
|
|
|
qx_product_roi.width + roi_expand * 2, qx_product_roi.height + roi_expand * 2);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)dirtyList.size(); i++)
|
|
|
|
for (int i = 0; i < (int)sourceList.size(); i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
cv::Rect dirty_roi = dirtyList.at(i).product_roi;
|
|
|
|
cv::Rect source_roi = sourceList.at(i).product_roi;
|
|
|
|
cv::Rect dirty_expanded(dirty_roi.x - roi_expand, dirty_roi.y - roi_expand,
|
|
|
|
cv::Rect source_expanded(source_roi.x - roi_expand, source_roi.y - roi_expand,
|
|
|
|
dirty_roi.width + roi_expand * 2, dirty_roi.height + roi_expand * 2);
|
|
|
|
source_roi.width + roi_expand * 2, source_roi.height + roi_expand * 2);
|
|
|
|
|
|
|
|
|
|
|
|
float fiou = CheckUtil::CalIoU(roi_expanded, dirty_expanded);
|
|
|
|
float fiou = CheckUtil::CalIoU(roi_expanded, source_expanded);
|
|
|
|
|
|
|
|
|
|
|
|
if (plog)
|
|
|
|
if (plog)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
plog->AddCheckstr(PrintLevel_3, 3, "CorrelatedDirty",
|
|
|
|
plog->AddCheckstr(PrintLevel_3, 3, "CorrelatedDirty",
|
|
|
|
"cur %s cam %s roi %s <-> dirty %s roi %s expand %d iou %f",
|
|
|
|
"cur %s cam %s roi %s <-> source %s roi %s expand %d iou %f",
|
|
|
|
cur_channel_name.c_str(), cur_camera_name.c_str(),
|
|
|
|
cur_channel_name.c_str(), cur_camera_name.c_str(),
|
|
|
|
CheckUtil::GetRectString(qx_product_roi).c_str(),
|
|
|
|
CheckUtil::GetRectString(qx_product_roi).c_str(),
|
|
|
|
dirtyList.at(i).channel_name.c_str(),
|
|
|
|
sourceList.at(i).channel_name.c_str(),
|
|
|
|
CheckUtil::GetRectString(dirty_roi).c_str(),
|
|
|
|
CheckUtil::GetRectString(source_roi).c_str(),
|
|
|
|
roi_expand, fiou);
|
|
|
|
roi_expand, fiou);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// IOU 为 NaN(ROI 非法导致的除零)时比较结果为 false,不会误抑制 NG
|
|
|
|
// IOU 为 NaN(ROI 非法导致的除零)时比较结果为 false,不会误抑制 NG
|
|
|
|
@ -410,11 +459,11 @@ bool QX_Merge_Analysis::IsOverlapDirtyInCorrelatedChannel(const std::vector<std:
|
|
|
|
if (plog)
|
|
|
|
if (plog)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
plog->AddCheckstr(PrintLevel_1, 3, "CorrelatedDirty",
|
|
|
|
plog->AddCheckstr(PrintLevel_1, 3, "CorrelatedDirty",
|
|
|
|
"cur %s cam %s roi %s overlap dirty %s cam %s roi %s expand %d iou %f > %f",
|
|
|
|
"cur %s cam %s roi %s overlap source %s cam %s roi %s expand %d iou %f > %f",
|
|
|
|
cur_channel_name.c_str(), cur_camera_name.c_str(),
|
|
|
|
cur_channel_name.c_str(), cur_camera_name.c_str(),
|
|
|
|
CheckUtil::GetRectString(qx_product_roi).c_str(),
|
|
|
|
CheckUtil::GetRectString(qx_product_roi).c_str(),
|
|
|
|
dirtyList.at(i).channel_name.c_str(), dirtyList.at(i).camera_name.c_str(),
|
|
|
|
sourceList.at(i).channel_name.c_str(), sourceList.at(i).camera_name.c_str(),
|
|
|
|
CheckUtil::GetRectString(dirty_roi).c_str(),
|
|
|
|
CheckUtil::GetRectString(source_roi).c_str(),
|
|
|
|
roi_expand, fiou, iou_threshold);
|
|
|
|
roi_expand, fiou, iou_threshold);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
@ -425,7 +474,7 @@ bool QX_Merge_Analysis::IsOverlapDirtyInCorrelatedChannel(const std::vector<std:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @brief 关联通道脏污重叠判断(供外部调用):使用内置关联通道/IOU配置判断缺陷是否与关联通道脏污重叠
|
|
|
|
* @brief 关联通道过滤源重叠判断(供外部调用):使用内置关联通道/IOU配置判断缺陷是否与关联通道过滤源缺陷重叠
|
|
|
|
* @param cur_channel_name 当前缺陷所属通道
|
|
|
|
* @param cur_channel_name 当前缺陷所属通道
|
|
|
|
* @param cur_camera_name 当前缺陷所属相机
|
|
|
|
* @param cur_camera_name 当前缺陷所属相机
|
|
|
|
* @param qx_product_roi 当前缺陷的产品坐标系ROI
|
|
|
|
* @param qx_product_roi 当前缺陷的产品坐标系ROI
|
|
|
|
@ -451,7 +500,7 @@ bool QX_Merge_Analysis::IsDirtyOverlapInCorrelatedChannel(const std::string &cur
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @brief 关联通道脏污过滤:将与该通道内关联通道脏污缺陷重叠的缺陷从列表中移除,
|
|
|
|
* @brief 关联过滤源过滤:将与该通道内关联通道过滤源缺陷(脏污/暗点等)重叠的缺陷从列表中移除,
|
|
|
|
* 使其不参与后续数量/距离/S分析,也不会被判为NG
|
|
|
|
* 使其不参与后续数量/距离/S分析,也不会被判为NG
|
|
|
|
* @param pALLTypeqxList 当前缺陷类型的缺陷列表
|
|
|
|
* @param pALLTypeqxList 当前缺陷类型的缺陷列表
|
|
|
|
* @return int 被过滤的缺陷个数
|
|
|
|
* @return int 被过滤的缺陷个数
|
|
|
|
@ -491,7 +540,7 @@ int QX_Merge_Analysis::FilterCorrelatedDirtyQx(ALL_Qx_DataList *pALLTypeqxList)
|
|
|
|
if (pQXChannelList->pChannelDetlog)
|
|
|
|
if (pQXChannelList->pChannelDetlog)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter",
|
|
|
|
pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter",
|
|
|
|
"channel %s cam %s blob %d roi %s : 关联通道存在重叠脏污, 过滤该暗点(不参与数量/距离分析)",
|
|
|
|
"channel %s cam %s blob %d roi %s : 关联通道存在重叠的过滤源缺陷, 过滤该暗点(不参与数量/距离分析)",
|
|
|
|
pQXChannelList->qxList.at(j).channel_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).channel_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).camera_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).camera_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).blobIdx,
|
|
|
|
pQXChannelList->qxList.at(j).blobIdx,
|
|
|
|
@ -500,7 +549,7 @@ int QX_Merge_Analysis::FilterCorrelatedDirtyQx(ALL_Qx_DataList *pALLTypeqxList)
|
|
|
|
if (m_pMergedetlog)
|
|
|
|
if (m_pMergedetlog)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter",
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter",
|
|
|
|
"channel %s cam %s blob %d roi %s : 关联通道存在重叠脏污, 过滤该暗点(不参与数量/距离分析)",
|
|
|
|
"channel %s cam %s blob %d roi %s : 关联通道存在重叠的过滤源缺陷, 过滤该暗点(不参与数量/距离分析)",
|
|
|
|
pQXChannelList->qxList.at(j).channel_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).channel_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).camera_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).camera_name.c_str(),
|
|
|
|
pQXChannelList->qxList.at(j).blobIdx,
|
|
|
|
pQXChannelList->qxList.at(j).blobIdx,
|
|
|
|
@ -955,13 +1004,13 @@ int QX_Merge_Analysis::Analysis_QXtype(ALL_Qx_DataList *pALLTypeqxList, int qx_i
|
|
|
|
|
|
|
|
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "Num And Dis Judge", "pALLTypeqxList->channelqxList.size() %ld",
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "Num And Dis Judge", "pALLTypeqxList->channelqxList.size() %ld",
|
|
|
|
pALLTypeqxList->channelqxList.size());
|
|
|
|
pALLTypeqxList->channelqxList.size());
|
|
|
|
// 关联通道脏污过滤:AD 分析前先过滤与关联通道脏污重叠的缺陷,使其不参与数量/距离/S分析,也不会被判NG
|
|
|
|
// 关联过滤源过滤:AD 分析前先过滤与关联通道过滤源缺陷重叠的缺陷,使其不参与数量/距离/S分析,也不会被判NG
|
|
|
|
if (qx_idx == QX_ANALYSIS_AD)
|
|
|
|
if (qx_idx == QX_ANALYSIS_AD)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int nFilterNum = FilterCorrelatedDirtyQx(pALLTypeqxList);
|
|
|
|
int nFilterNum = FilterCorrelatedDirtyQx(pALLTypeqxList);
|
|
|
|
if (nFilterNum > 0)
|
|
|
|
if (nFilterNum > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter", "%s 关联通道脏污过滤 %d 个缺陷",
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter", "%s 关联通道过滤源过滤 %d 个缺陷",
|
|
|
|
QX_ANALYSIS_NAME_Names[qx_idx].c_str(), nFilterNum);
|
|
|
|
QX_ANALYSIS_NAME_Names[qx_idx].c_str(), nFilterNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -1454,8 +1503,9 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
|
|
|
|
/* 获取关联通道(已在 Analysis_QXtype 的过滤阶段使用, 此处仅打印) */
|
|
|
|
/* 获取关联通道(已在 Analysis_QXtype 的过滤阶段使用, 此处仅打印) */
|
|
|
|
vector<string> correlated_channels = pAd_checkParma->analysis_bind.correlated_channels;
|
|
|
|
vector<string> correlated_channels = pAd_checkParma->analysis_bind.correlated_channels;
|
|
|
|
|
|
|
|
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "Analysis_AD_Bind", "bind main_2s %d second_2s %d main_3s %d second_3s %d correlated %d",
|
|
|
|
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "Analysis_AD_Bind", "bind main_2s %d second_2s %d main_3s %d second_3s %d correlated_channels %d correlated_types %d",
|
|
|
|
(int)main_channel_2s.size(), (int)second_channel_2s.size(), (int)main_channel_3s.size(), (int)second_channel_3s.size(), (int)correlated_channels.size());
|
|
|
|
(int)main_channel_2s.size(), (int)second_channel_2s.size(), (int)main_channel_3s.size(), (int)second_channel_3s.size(),
|
|
|
|
|
|
|
|
(int)correlated_channels.size(), (int)pAd_checkParma->analysis_bind.correlated_types.size());
|
|
|
|
|
|
|
|
|
|
|
|
/* 获取主次通道的缺陷列表 */
|
|
|
|
/* 获取主次通道的缺陷列表 */
|
|
|
|
vector<QX_channel_List> main_channel_s_qxList;
|
|
|
|
vector<QX_channel_List> main_channel_s_qxList;
|
|
|
|
@ -1776,7 +1826,7 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
|
|
|
|
// 已经NG
|
|
|
|
// 已经NG
|
|
|
|
if (bNG)
|
|
|
|
if (bNG)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 注:与关联通道脏污重叠的缺陷已在 FilterCorrelatedDirtyQx(AD分析前) 中过滤,此处不会再被记录NG
|
|
|
|
// 注:与关联通道过滤源缺陷重叠的缺陷已在 FilterCorrelatedDirtyQx(AD分析前) 中过滤,此处不会再被记录NG
|
|
|
|
|
|
|
|
|
|
|
|
QX_channel_List *pqxList = pQXChannelList;
|
|
|
|
QX_channel_List *pqxList = pQXChannelList;
|
|
|
|
for (int idx = 0; idx < (int)pqxList->qxList.size(); idx++)
|
|
|
|
for (int idx = 0; idx < (int)pqxList->qxList.size(); idx++)
|
|
|
|
|