update 修改脏污过滤流程

dev_lsy
liusiyang 1 month ago
parent ab3abb8fa8
commit cd8aa0f492

@ -132,6 +132,9 @@ private:
int AnalysisResult_Pre(QX_ERROR_INFO_ *QX_info); // 弱化处理
// 关联通道脏污过滤:撤销与关联通道脏污重叠的暗点NG结果(含单图判定的单点NG)
int FilterCorrelatedDirtyNG(std::shared_ptr<ImageAllResult> pImageResult);
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能
int ConfigTypeToQXAnalysis(int nconfigType);

@ -177,6 +177,12 @@ public:
// 登记关联通道(非主/次通道)的缺陷信息,如脏污(dirty),供 AD 绑定分析判断重叠缺陷
bool AddCorrelatedQxInfo(Correlated_Qx_Info_ qxinfo, std::shared_ptr<DetLog> plog);
// 关联通道脏污重叠判断(供外部调用):当前缺陷ROI是否与关联通道脏污缺陷重叠
bool IsDirtyOverlapInCorrelatedChannel(const std::string &cur_channel_name,
const std::string &cur_camera_name,
const cv::Rect &qx_product_roi,
std::shared_ptr<DetLog> plog);
bool setSendStatus(std::string cameraName, RUN_STATUS_ status);
bool waitComplete(int timeoutMs = 15000);
@ -207,6 +213,9 @@ private:
int Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx);
int Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_idx);
// 关联通道脏污过滤:移除与关联通道脏污重叠的缺陷,使其不参与后续数量/距离/S分析
int FilterCorrelatedDirtyQx(ALL_Qx_DataList *pALLTypeqxList);
// 判断当前缺陷是否与关联通道(correlated_channels)中的脏污缺陷重叠
bool IsOverlapDirtyInCorrelatedChannel(const std::vector<std::string> &correlated_channels,
const std::string &cur_channel_name,

@ -1,5 +1,6 @@
#include "ImageResultJudge.h"
#include <cmath>
ImageResultJudge::ImageResultJudge(/* args */)
{
@ -807,6 +808,117 @@ int ImageResultJudge::UpdateMergedet(std::shared_ptr<CameraResult> pCheck_Result
return 0;
}
/**
* @brief 关联通道脏污过滤:撤销与关联通道脏污缺陷重叠的暗点NG结果(含单图判定的单点NG)
* 被过滤的暗点不再计入NG
* @param pImageResult 当前检测图片结果
* @return int 被过滤的缺陷个数
*/
int ImageResultJudge::FilterCorrelatedDirtyNG(std::shared_ptr<ImageAllResult> pImageResult)
{
if (pImageResult == nullptr || pImageResult->cameraBaseResult == nullptr ||
m_pbaseCheckFunction == nullptr || m_pQX_Merge_Analysis == nullptr || m_pAnalysisyConfig == nullptr)
{
return 0;
}
// 未配置关联通道(NONE/空)时不需要判断
std::vector<std::string> correlated_channels = m_pbaseCheckFunction->ad_check.analysis_bind.correlated_channels;
if (correlated_channels.empty())
{
return 0;
}
std::shared_ptr<One_Image_CheckResult_> pDetResult = pImageResult->pDetResult; // 检测结果
std::shared_ptr<CheckResult> m_CheckResult_shareP = pImageResult->result; // 返回结果
if (pDetResult == nullptr || pDetResult->pQx_ErrorList == nullptr || m_CheckResult_shareP == nullptr)
{
return 0;
}
std::shared_ptr<DetLog> pImageLog = pImageResult->detlog;
float fproduct_offx_mm = m_pAnalysisyConfig->commonCheckConfig.baseConfig.fProduct_Off_X_mm;
int fproduct_offx_piexl = int(fproduct_offx_mm / m_fImgage_Scale_X);
int nFilterNum = 0;
for (int qxidx = 0; qxidx < (int)pDetResult->pQx_ErrorList->size(); qxidx++)
{
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
// 只处理 暗点(AD) 的 NG 结果
if (QX_info->nconfig_qx_type != CONFIG_QX_NAME_AD || QX_info->result != QX_RESULT_TYPE_NG)
{
continue;
}
// 关联通道存在与当前缺陷重叠的脏污缺陷时,过滤该暗点NG
cv::Rect product_roi = QX_info->roi;
product_roi.x += fproduct_offx_piexl;
if (!m_pQX_Merge_Analysis->IsDirtyOverlapInCorrelatedChannel(pImageResult->strChannel,
pImageResult->cameraBaseResult->strCameraName,
product_roi,
pImageLog))
{
continue;
}
// 撤销NG结果
QX_info->result = QX_RESULT_TYPE_OK;
QX_info->result_name = QX_RESULT_TYPE_Names[QX_info->result];
int nqx_type = ConfigTypeToResultType(QX_info->nconfig_qx_type);
// 移除该缺陷的NG小图
int nEraseNum = 0;
for (auto it = m_CheckResult_shareP->qxImageResult.begin(); it != m_CheckResult_shareP->qxImageResult.end();)
{
if (it->idx == qxidx)
{
it = m_CheckResult_shareP->qxImageResult.erase(it);
nEraseNum++;
}
else
{
++it;
}
}
// 计数回退
if (nqx_type >= 0 && nqx_type < ERROR_TYPE_COUNT)
{
m_CheckResult_shareP->defectResultList[nqx_type].num -= nEraseNum;
if (m_CheckResult_shareP->defectResultList[nqx_type].num < 0)
{
m_CheckResult_shareP->defectResultList[nqx_type].num = 0;
}
}
if (pImageResult->NG_num > 0)
{
pImageResult->NG_num--;
}
pImageResult->Ok_num++;
// 过滤后已无NG,则恢复图片结果
if (m_CheckResult_shareP->qxImageResult.empty())
{
m_CheckResult_shareP->nresult = ERROR_TYPE_OK;
}
nFilterNum++;
if (pImageLog)
{
pImageLog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "DirtyCorrelatedFilter",
"img %s cam %s blob %d qx %s roi %s : 关联通道存在重叠脏污, 过滤该暗点NG",
pImageResult->strChannel.c_str(), pImageResult->cameraBaseResult->strCameraName.c_str(),
qxidx, QX_info->qx_name.c_str(), CheckUtil::GetRectString(product_roi).c_str());
}
if (m_pQX_Merge_Analysis->m_pMergedetlog)
{
m_pQX_Merge_Analysis->m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter",
"img %s cam %s blob %d qx %s roi %s : 关联通道存在重叠脏污, 过滤该暗点NG",
pImageResult->strChannel.c_str(), pImageResult->cameraBaseResult->strCameraName.c_str(),
qxidx, QX_info->qx_name.c_str(), CheckUtil::GetRectString(product_roi).c_str());
}
}
return nFilterNum;
}
int ImageResultJudge::MergeResult(std::shared_ptr<ImageAllResult> pImageResult, QX_Analysis_Result_List *ptemre)
{
@ -829,6 +941,9 @@ int ImageResultJudge::MergeResult(std::shared_ptr<ImageAllResult> pImageResult,
}
int qxNum = pDetResult->pQx_ErrorList->size();
// 关联通道脏污过滤:撤销与关联通道脏污重叠的暗点NG(含单图判定的单点NG)
FilterCorrelatedDirtyNG(pImageResult);
for (int iqx = 0; iqx < (int)ptemre->resultList.size(); iqx++)
{
if (ptemre->resultList.at(iqx).channel_name != pImageResult->strChannel ||

@ -424,6 +424,98 @@ bool QX_Merge_Analysis::IsOverlapDirtyInCorrelatedChannel(const std::vector<std:
return false;
}
/**
* @brief 关联通道脏污重叠判断(供外部调用):使用内置关联通道/IOU配置判断缺陷是否与关联通道脏污重叠
* @param cur_channel_name 当前缺陷所属通道
* @param cur_camera_name 当前缺陷所属相机
* @param qx_product_roi 当前缺陷的产品坐标系ROI
* @param plog 日志
* @return bool 重叠返回true
*/
bool QX_Merge_Analysis::IsDirtyOverlapInCorrelatedChannel(const std::string &cur_channel_name,
const std::string &cur_camera_name,
const cv::Rect &qx_product_roi,
std::shared_ptr<DetLog> plog)
{
if (m_pbaseCheckFunction == nullptr)
{
return false;
}
Base_Function_AD_Check *pAd_checkParma = &m_pbaseCheckFunction->ad_check;
const std::vector<std::string> &correlated_channels = pAd_checkParma->analysis_bind.correlated_channels;
const int roi_expand = (int)(round)(pAd_checkParma->analysis_iou.AD_Expand);
const float iou_threshold = pAd_checkParma->analysis_iou.AD_IOU;
return IsOverlapDirtyInCorrelatedChannel(correlated_channels, cur_channel_name, cur_camera_name,
qx_product_roi, roi_expand, iou_threshold, plog);
}
/**
* @brief 关联通道脏污过滤:将与该通道内关联通道脏污缺陷重叠的缺陷从列表中移除,
* 使其不参与后续数量/距离/S分析,也不会被判为NG
* @param pALLTypeqxList 当前缺陷类型的缺陷列表
* @return int 被过滤的缺陷个数
*/
int QX_Merge_Analysis::FilterCorrelatedDirtyQx(ALL_Qx_DataList *pALLTypeqxList)
{
if (m_pbaseCheckFunction == nullptr || pALLTypeqxList == nullptr)
{
return 0;
}
Base_Function_AD_Check *pAd_checkParma = &m_pbaseCheckFunction->ad_check;
const std::vector<std::string> correlated_channels = pAd_checkParma->analysis_bind.correlated_channels;
// 未配置关联通道(NONE/空)时不需要过滤
if (correlated_channels.empty())
{
return 0;
}
const int roi_expand = (int)(round)(pAd_checkParma->analysis_iou.AD_Expand);
const float iou_threshold = pAd_checkParma->analysis_iou.AD_IOU;
int nFilterNum = 0;
for (int i = 0; i < (int)pALLTypeqxList->channelqxList.size(); i++)
{
QX_channel_List *pQXChannelList = &pALLTypeqxList->channelqxList[i];
std::vector<QX_Info> temQxList;
temQxList.reserve(pQXChannelList->qxList.size());
for (int j = 0; j < (int)pQXChannelList->qxList.size(); j++)
{
if (IsOverlapDirtyInCorrelatedChannel(correlated_channels,
pQXChannelList->qxList.at(j).channel_name,
pQXChannelList->qxList.at(j).camera_name,
pQXChannelList->qxList.at(j).product_roi,
roi_expand, iou_threshold,
pQXChannelList->pChannelDetlog))
{
nFilterNum++;
if (pQXChannelList->pChannelDetlog)
{
pQXChannelList->pChannelDetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter",
"channel %s cam %s blob %d roi %s : 关联通道存在重叠脏污, 过滤该暗点(不参与数量/距离分析)",
pQXChannelList->qxList.at(j).channel_name.c_str(),
pQXChannelList->qxList.at(j).camera_name.c_str(),
pQXChannelList->qxList.at(j).blobIdx,
CheckUtil::GetRectString(pQXChannelList->qxList.at(j).product_roi).c_str());
}
if (m_pMergedetlog)
{
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter",
"channel %s cam %s blob %d roi %s : 关联通道存在重叠脏污, 过滤该暗点(不参与数量/距离分析)",
pQXChannelList->qxList.at(j).channel_name.c_str(),
pQXChannelList->qxList.at(j).camera_name.c_str(),
pQXChannelList->qxList.at(j).blobIdx,
CheckUtil::GetRectString(pQXChannelList->qxList.at(j).product_roi).c_str());
}
continue;
}
temQxList.push_back(pQXChannelList->qxList.at(j));
}
pQXChannelList->qxList.swap(temQxList);
}
return nFilterNum;
}
/**
* @brief 等待所有任务完成
* @param timeoutMs 超时时间(毫秒)
@ -863,6 +955,16 @@ 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",
pALLTypeqxList->channelqxList.size());
// 关联通道脏污过滤:AD 分析前先过滤与关联通道脏污重叠的缺陷,使其不参与数量/距离/S分析,也不会被判NG
if (qx_idx == QX_ANALYSIS_AD)
{
int nFilterNum = FilterCorrelatedDirtyQx(pALLTypeqxList);
if (nFilterNum > 0)
{
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "DirtyCorrelatedFilter", "%s 关联通道脏污过滤 %d 个缺陷",
QX_ANALYSIS_NAME_Names[qx_idx].c_str(), nFilterNum);
}
}
for (int i = 0; i < pALLTypeqxList->channelqxList.size(); i++)
{
QX_channel_List *pQXChannelList = &pALLTypeqxList->channelqxList[i];
@ -1349,11 +1451,11 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
vector<string> second_channel_2s = pAd_checkParma->analysis_bind.second_channel_2s;
vector<string> main_channel_3s = pAd_checkParma->analysis_bind.main_channel_3s;
vector<string> second_channel_3s = pAd_checkParma->analysis_bind.second_channel_3s;
/* 获取关联通道 */
/* 获取关联通道(已在 Analysis_QXtype 的过滤阶段使用, 此处仅打印) */
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",
(int)main_channel_2s.size(), (int)second_channel_2s.size(), (int)main_channel_3s.size(), (int)second_channel_3s.size());
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "Analysis_AD_Bind", "bind main_2s %d second_2s %d main_3s %d second_3s %d correlated %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());
/* 获取主次通道的缺陷列表 */
vector<QX_channel_List> main_channel_s_qxList;
@ -1674,9 +1776,7 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
// 已经NG
if (bNG)
{
// 注意:按缺陷(blob)粒度逐条判断,避免把同一通道内与脏污无关的缺陷也一并放过
const int roi_expand = (int)(round)(pAd_checkParma->analysis_iou.AD_Expand);
const float iou_threshold = pAd_checkParma->analysis_iou.AD_IOU;
// 注:与关联通道脏污重叠的缺陷已在 FilterCorrelatedDirtyQx(AD分析前) 中过滤,此处不会再被记录NG
QX_channel_List *pqxList = pQXChannelList;
for (int idx = 0; idx < (int)pqxList->qxList.size(); idx++)
@ -1686,29 +1786,6 @@ int QX_Merge_Analysis::Analysis_AD_Bind(ALL_Qx_DataList *pALLTypeqxList, int qx_
continue;
}
// 关联通道存在与当前缺陷重叠的脏污缺陷时,该缺陷不记录NG结果
if (IsOverlapDirtyInCorrelatedChannel(correlated_channels,
pqxList->qxList.at(idx).channel_name,
pqxList->qxList.at(idx).camera_name,
pqxList->qxList.at(idx).product_roi,
roi_expand, iou_threshold,
pqxList->pChannelDetlog))
{
pqxList->pChannelDetlog->AddCheckstr(PrintLevel_1, 3, "result = NG skip",
"channel %s cam %s blob %d roi %s : 关联通道存在重叠, 不记录NG结果",
pqxList->qxList.at(idx).channel_name.c_str(),
pqxList->qxList.at(idx).camera_name.c_str(),
pqxList->qxList.at(idx).blobIdx,
CheckUtil::GetRectString(pqxList->qxList.at(idx).product_roi).c_str());
m_pMergedetlog->AddCheckstr(PrintLevel_1, 3, "result = NG skip",
"channel %s cam %s blob %d roi %s : 关联通道存在重叠, 不记录NG结果",
pqxList->qxList.at(idx).channel_name.c_str(),
pqxList->qxList.at(idx).camera_name.c_str(),
pqxList->qxList.at(idx).blobIdx,
CheckUtil::GetRectString(pqxList->qxList.at(idx).product_roi).c_str());
continue;
}
pqxList->qxList.at(idx).result = 1;
QX_RESULT tem;

Loading…
Cancel
Save