You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
BOE_FOG_DETECT/AlgorithmModule/src/QX_Merge_Analysis.cpp

1142 lines
32 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "QX_Merge_Analysis.h"
#include <memory>
#include <string>
#include <mutex>
#include <thread>
#include <chrono>
#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> QX_Merge_Analysis::GetInstance()
{
std::shared_ptr<QX_Merge_Analysis> instance = std::make_shared<QX_Merge_Analysis>();
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<DetLog>();
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "QX_Merge_Analysis", "InitData %s",CheckUtil::getCurTimeHMS().c_str());
{
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<DetLog> plog, std::shared_ptr<DetLog> pchannelLog)
{
std::string channel_name = qxinfo.channel_name;
std::string cam_name = qxinfo.camera_name;
ALL_QX_ParamList *pconfigList = nullptr;
{
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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::milliseconds>(
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<std::mutex> 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::thread>(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<DetLog> 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;
}