|
|
/*
|
|
|
//实现对部分缺陷 需要进行 数量 和距离上分析的
|
|
|
*/
|
|
|
#ifndef QX_Merge_Analysis_H_
|
|
|
#define QX_Merge_Analysis_H_
|
|
|
#include <opencv2/opencv.hpp>
|
|
|
#include "CheckUtil.hpp"
|
|
|
#include <mutex>
|
|
|
#include <thread>
|
|
|
#include <condition_variable>
|
|
|
#include <unordered_map>
|
|
|
#include <vector>
|
|
|
#include "CheckErrorCodeDefine.hpp"
|
|
|
#include "CheckConfigDefine.h"
|
|
|
#include "QX_Analysis.h"
|
|
|
|
|
|
using namespace std;
|
|
|
#define QX_MEREGE_CONFIG_CAMERA_NAME "left"
|
|
|
|
|
|
class QX_Merge_Analysis
|
|
|
{
|
|
|
public:
|
|
|
enum RUN_STATUS_
|
|
|
{
|
|
|
RUN_STATUS_NULL,
|
|
|
RUN_STATUS_IDLE,
|
|
|
RUN_STATUS_READY,
|
|
|
RUN_STATUS_BUSY,
|
|
|
RUN_STATUS_COMPLETE,
|
|
|
};
|
|
|
struct tem_AD_QX_Info
|
|
|
{
|
|
|
int qxidx = 0;
|
|
|
int channelidx = 0;
|
|
|
};
|
|
|
struct AD_Channel_Info_
|
|
|
{
|
|
|
cv::Rect roi;
|
|
|
cv::Point2f location_product_mm;
|
|
|
int num;
|
|
|
float fdis;
|
|
|
int dist_idx;
|
|
|
int num_2s;
|
|
|
int num_3s;
|
|
|
int num_1s;
|
|
|
vector<tem_AD_QX_Info> numIdxList;
|
|
|
vector<tem_AD_QX_Info> num_2sIdxList;
|
|
|
vector<tem_AD_QX_Info> num_3sIdxList;
|
|
|
AD_Channel_Info_()
|
|
|
{
|
|
|
roi = cv::Rect(0, 0, 0, 0);
|
|
|
location_product_mm = cv::Point2f(0, 0);
|
|
|
num = 0;
|
|
|
fdis = 999999999999;
|
|
|
dist_idx = 0;
|
|
|
num_1s = 0;
|
|
|
num_2s = 0;
|
|
|
num_3s = 0;
|
|
|
numIdxList.clear();
|
|
|
num_2sIdxList.clear();
|
|
|
num_3sIdxList.clear();
|
|
|
}
|
|
|
std::string GetInfo()
|
|
|
{
|
|
|
char buffer[256];
|
|
|
sprintf(buffer, "roi:[%d,%d,%d,%d] location [%f %f]num:%d fdis:%.2f dist_idx:%d num_1s:%d num_2s:%d num_3s:%d",
|
|
|
roi.x, roi.y, roi.width, roi.height, location_product_mm.x, location_product_mm.y,
|
|
|
num, fdis, dist_idx, num_1s, num_2s, num_3s);
|
|
|
return std::string(buffer);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
struct AD_Channel_BD_Info_
|
|
|
{
|
|
|
cv::Rect roi;
|
|
|
cv::Point2f location_product_mm;
|
|
|
vector<string> s_name_2;
|
|
|
vector<string> s_name_3;
|
|
|
int s_type;
|
|
|
AD_Channel_BD_Info_()
|
|
|
{
|
|
|
roi = cv::Rect(0, 0, 0, 0);
|
|
|
location_product_mm = cv::Point2f(0, 0);
|
|
|
s_name_2.clear();
|
|
|
s_name_3.clear();
|
|
|
s_type = 0;
|
|
|
}
|
|
|
std::string GetInfo()
|
|
|
{
|
|
|
char buffer[256];
|
|
|
snprintf(buffer, sizeof(buffer), "roi:[%d,%d,%d,%d] location [%f %f] s_type:%d",
|
|
|
roi.x, roi.y, roi.width, roi.height, location_product_mm.x, location_product_mm.y, s_type);
|
|
|
std::string str = buffer;
|
|
|
for(int i = 0; i < s_name_2.size(); i++)
|
|
|
{
|
|
|
str += " s_name_2[" + s_name_2[i] + "]";
|
|
|
}
|
|
|
for(int i = 0; i < s_name_3.size(); i++)
|
|
|
{
|
|
|
str += " s_name_3[" + s_name_3[i] + "]";
|
|
|
}
|
|
|
return str;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
struct AD_Channel_Stat_
|
|
|
{
|
|
|
int num_1s;
|
|
|
int num_2s;
|
|
|
int num_3s;
|
|
|
int num_2s_s;
|
|
|
int num_2s_m;
|
|
|
int num_3s_s;
|
|
|
int num_3s_m;
|
|
|
int product_AD_num;
|
|
|
float min_dis;
|
|
|
AD_Channel_Stat_()
|
|
|
{
|
|
|
num_1s = 0;
|
|
|
num_2s = 0;
|
|
|
num_3s = 0;
|
|
|
num_2s_s = 0;
|
|
|
num_2s_m = 0;
|
|
|
num_3s_s = 0;
|
|
|
num_3s_m = 0;
|
|
|
product_AD_num = 0;
|
|
|
min_dis = 9999999999;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 关联通道缺陷信息(用于判断关联通道是否存在脏污(dirty)重叠缺陷)
|
|
|
struct Correlated_Qx_Info_
|
|
|
{
|
|
|
std::string channel_name; // 缺陷所属通道
|
|
|
std::string camera_name; // 缺陷所属相机
|
|
|
int config_qx_type; // 缺陷配置类型 CONFIG_QX_NAME_
|
|
|
int result_type; // 缺陷结果类型(仅用于日志/追溯)
|
|
|
cv::Rect product_roi; // 产品坐标系下的缺陷ROI
|
|
|
Correlated_Qx_Info_()
|
|
|
{
|
|
|
channel_name = "";
|
|
|
camera_name = "";
|
|
|
config_qx_type = -1;
|
|
|
result_type = -1;
|
|
|
product_roi = cv::Rect(0, 0, 0, 0);
|
|
|
}
|
|
|
std::string GetInfo()
|
|
|
{
|
|
|
char buffer[256];
|
|
|
snprintf(buffer, sizeof(buffer), "cam:%s channel:%s cfgType:%d resType:%d roi:[%d,%d,%d,%d]",
|
|
|
camera_name.c_str(), channel_name.c_str(), config_qx_type, result_type,
|
|
|
product_roi.x, product_roi.y, product_roi.width, product_roi.height);
|
|
|
return std::string(buffer);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
public:
|
|
|
QX_Merge_Analysis();
|
|
|
~QX_Merge_Analysis();
|
|
|
static std::shared_ptr<QX_Merge_Analysis> GetInstance();
|
|
|
|
|
|
int Clear();
|
|
|
int AddCamer(std::string cameraName);
|
|
|
|
|
|
int InitData();
|
|
|
|
|
|
int GetReusult(QX_Analysis_Result_List *&presult);
|
|
|
|
|
|
void SetConfig(std::string cameraName, int qxidx, QXAnalysis_Config config);
|
|
|
void InitConfig(std::string cameraName);
|
|
|
void SetbaseCheckFunction(std::string cameraName, ALLChannelCheckFunction *pChannelFuntion, BaseCheckFunction *pbaseCheckFunction);
|
|
|
|
|
|
int ConfigTypeToQXAnalysis(int nconfigType);
|
|
|
bool Idx(int qxidx);
|
|
|
bool AddQxInfo(int qxidx, QX_Info qxinfo, std::shared_ptr<DetLog> plog, std::shared_ptr<DetLog> pchannelLog);
|
|
|
|
|
|
// 登记关联通道(非主/次通道)的过滤源缺陷信息(类型由 correlated_types 配置, 如脏污/暗点),供 AD 分析判断重叠缺陷
|
|
|
bool AddCorrelatedQxInfo(Correlated_Qx_Info_ qxinfo, std::shared_ptr<DetLog> plog);
|
|
|
|
|
|
// 判断缺陷类型是否为配置的关联过滤源类型(analysis_bind.correlated_types, 如 "Dirty_L0"/"Dirty_L1"/"Dirty_L2"/"AD")
|
|
|
// 配置为空时默认三种脏污; 登记与过滤两处共用此判定
|
|
|
bool IsCorrelatedSourceConfigType(int nconfigType);
|
|
|
|
|
|
// 关联通道过滤源重叠判断(供外部调用):当前缺陷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);
|
|
|
std::shared_ptr<DetLog> m_pMergedetlog;
|
|
|
|
|
|
ALLChannelCheckFunction *m_pChannelFuntion;
|
|
|
BaseCheckFunction *m_pbaseCheckFunction;
|
|
|
|
|
|
private:
|
|
|
std::shared_ptr<std::thread>
|
|
|
ptr_thread_Run;
|
|
|
int Run(int nId); // 运行;
|
|
|
|
|
|
// 开启线程
|
|
|
int StartThread(int nId);
|
|
|
// 停止线程
|
|
|
int StopThread();
|
|
|
|
|
|
int StartAnalysis();
|
|
|
|
|
|
int Analysis_single_Config(QXAnalysis_Config *pconfig, QX_channel_List *pqxList, int qx_type, std::shared_ptr<DetLog> pchannelLog);
|
|
|
|
|
|
int Analysis_QXtype(ALL_Qx_DataList *pALLTypeqxList, int qx_idx);
|
|
|
int Analysis_Channel(QX_channel_List *pChannelqxList, int qx_idx);
|
|
|
int Judge_OK_Config();
|
|
|
int Judge_NG_Config();
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
// 判断当前缺陷是否与关联通道(correlated_channels)中的过滤源缺陷(correlated_types)重叠
|
|
|
bool IsOverlapDirtyInCorrelatedChannel(const std::vector<std::string> &correlated_channels,
|
|
|
const std::string &cur_channel_name,
|
|
|
const std::string &cur_camera_name,
|
|
|
const cv::Rect &qx_product_roi,
|
|
|
int roi_expand,
|
|
|
float iou_threshold,
|
|
|
std::shared_ptr<DetLog> plog);
|
|
|
|
|
|
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName);
|
|
|
|
|
|
double DistanceBetweenRectCenters(const cv::Rect &rect1, const cv::Rect &rect2, float fx, float fy);
|
|
|
|
|
|
private:
|
|
|
ALL_Qx_DataList m_QXList[QX_ANALYSIS_COUNT];
|
|
|
ALL_QX_ParamList m_ConfigList[QX_ANALYSIS_COUNT];
|
|
|
|
|
|
std::mutex mtx_QXList;
|
|
|
std::mutex mtx_ConfigList;
|
|
|
|
|
|
std::mutex mtx_status;
|
|
|
std::condition_variable cv_status;
|
|
|
RUN_STATUS_ m_status;
|
|
|
std::unordered_map<std::string, RUN_STATUS_> m_statusList;
|
|
|
std::unordered_map<std::string, std::shared_ptr<DetLog>> m_pdetlogList;
|
|
|
|
|
|
QX_Analysis_Result_List m_reultList;
|
|
|
|
|
|
bool m_bExit; // 是否退出检测
|
|
|
|
|
|
std::vector<AD_Channel_Info_> AD_list;
|
|
|
|
|
|
std::unordered_map<string, vector<AD_Channel_BD_Info_>> AD_list_bind;
|
|
|
|
|
|
// 关联通道缺陷缓存:channel_name -> 缺陷列表(产品坐标系)
|
|
|
std::unordered_map<std::string, std::vector<Correlated_Qx_Info_>> m_correlatedQxMap;
|
|
|
std::mutex mtx_correlatedQx;
|
|
|
|
|
|
|
|
|
private:
|
|
|
};
|
|
|
|
|
|
#endif |