/* //实现对部分缺陷 需要进行 数量 和距离上分析的 */ #ifndef QX_Merge_Analysis_H_ #define QX_Merge_Analysis_H_ #include #include "CheckUtil.hpp" #include #include #include #include #include #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 numIdxList; vector num_2sIdxList; vector 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 s_name_2; vector 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 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 plog, std::shared_ptr pchannelLog); // 登记关联通道(非主/次通道)的缺陷信息,如脏污(dirty),供 AD 绑定分析判断重叠缺陷 bool AddCorrelatedQxInfo(Correlated_Qx_Info_ qxinfo, std::shared_ptr 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 plog); bool setSendStatus(std::string cameraName, RUN_STATUS_ status); bool waitComplete(int timeoutMs = 15000); std::shared_ptr m_pMergedetlog; ALLChannelCheckFunction *m_pChannelFuntion; BaseCheckFunction *m_pbaseCheckFunction; private: std::shared_ptr 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 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(); 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 &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 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 m_statusList; std::unordered_map> m_pdetlogList; QX_Analysis_Result_List m_reultList; bool m_bExit; // 是否退出检测 std::vector AD_list; std::unordered_map> AD_list_bind; // 关联通道缺陷缓存:channel_name -> 缺陷列表(产品坐标系) std::unordered_map> m_correlatedQxMap; std::mutex mtx_correlatedQx; private: }; #endif