From 55eb4e571d8cf0ac8e6927ada2f3e32a0a1d6227 Mon Sep 17 00:00:00 2001 From: liusiyang Date: Thu, 3 Sep 2026 18:06:09 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E6=B7=BB=E5=8A=A0=E6=94=AF=E6=9E=B6?= =?UTF-8?q?=E5=81=8F=E7=A7=BB=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AlgorithmModule/src/ImgCheckAnalysisy.cpp | 80 ++++++++++++++++- ConfigModule/include/CheckConfigDefine.h | 56 ++++++++++++ ConfigModule/src/JsonConfig.cpp | 100 ++++------------------ 3 files changed, 153 insertions(+), 83 deletions(-) diff --git a/AlgorithmModule/src/ImgCheckAnalysisy.cpp b/AlgorithmModule/src/ImgCheckAnalysisy.cpp index 601cea9..86657b3 100644 --- a/AlgorithmModule/src/ImgCheckAnalysisy.cpp +++ b/AlgorithmModule/src/ImgCheckAnalysisy.cpp @@ -499,7 +499,85 @@ int ImgCheckAnalysisy::CheckRun() m_pdetlog->AddCheckstr(PrintLevel_0, "3、pre detect", "-------------------------pre Det--------------- \n"); /* 检测支架偏移 */ - // 分析m_inner_rroi + { + Base_Function_Support_Det &supportDet = m_pbaseCheckFunction->supportDet; + if (supportDet.bOpen && supportDet.supportRect.size.width > 0 && supportDet.supportRect.size.height > 0) + { + cv::RotatedRect &inner = m_inner_rroi; + cv::RotatedRect &support = supportDet.supportRect; + + // x、y 中心偏移 + float dx = fabs(inner.center.x - support.center.x); + float dy = fabs(inner.center.y - support.center.y); + // 旋转偏移(矩形旋转 90 度等价,角度取最小差) + float dangle = fabs(inner.angle - support.angle); + if (dangle > 45.0f) + { + dangle = fabs(dangle - 90.0f); + } + + bool bOffset = (dx > supportDet.x_offset) || (dy > supportDet.y_offset) || (dangle > supportDet.r_offset); + + // 缺失判定:内边缘面积小于支架模板面积的 75% + float innerArea = inner.size.width * inner.size.height; + float supportArea = support.size.width * support.size.height; + bool bLoss = (supportArea > 0.0f) && (innerArea < supportArea * 0.75f); + + if (bOffset || bLoss) + { + QX_ERROR_INFO_ temerror; + temerror.Idx = m_pDetResult->pQx_ErrorList->size(); + + // roi 在原图坐标系,转换为检测图(detImg)坐标系 + cv::Rect roi = inner.boundingRect(); + roi.x -= m_outer_roi.x; + roi.y -= m_outer_roi.y; + roi &= cv::Rect(0, 0, m_pImageAllResult->detImg.cols, m_pImageAllResult->detImg.rows); + temerror.roi = roi; + temerror.area = roi.width * roi.height; + temerror.JudgArea = roi.width * m_fImgage_Scale_X * roi.height * m_fImgage_Scale_Y; + temerror.JudgArea_second = temerror.JudgArea; + float w = inner.size.width; + float h = inner.size.height; + temerror.flen = (w > h ? w : h) * m_fImgage_Scale_X; + temerror.fbreadth = (w > h ? h : w) * m_fImgage_Scale_Y; + + if (bLoss) + { + temerror.nconfig_qx_type = CONFIG_QX_NAME_support_loss; + } + else + { + temerror.nconfig_qx_type = CONFIG_QX_NAME_support_offset; + } + temerror.qx_name = CONFIG_QX_NAME_Names[temerror.nconfig_qx_type]; + temerror.result = QX_RESULT_TYPE_NG; + temerror.result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_NG]; + + // 计算支架中心所在的检测区域 + cv::Point pCenter; + pCenter.x = roi.x + roi.width * 0.5; + pCenter.y = roi.y + roi.height * 0.5; + int nmaxregionIdx = 0; + for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++) + { + const std::vector &polygon = m_DetRoiList.roiList_Src[iregion]; + double result = cv::pointPolygonTest(polygon, pCenter, false); + if (result < 0) + { + continue; + } + nmaxregionIdx = iregion; + } + temerror.detRegionidxList.push_back(nmaxregionIdx); + + m_pDetResult->pQx_ErrorList->push_back(temerror); + + m_pdetlog->AddCheckstr(PrintLevel_0, "支架检测", "%s %d roi [%d %d %d %d] dx %f dy %f dangle %f", + temerror.qx_name.c_str(), temerror.Idx, roi.x, roi.y, roi.width, roi.height, dx, dy, dangle); + } + } + } /* Tag检测 */ { diff --git a/ConfigModule/include/CheckConfigDefine.h b/ConfigModule/include/CheckConfigDefine.h index ab870ae..040289c 100644 --- a/ConfigModule/include/CheckConfigDefine.h +++ b/ConfigModule/include/CheckConfigDefine.h @@ -52,6 +52,8 @@ enum CONFIG_QX_NAME_ CONFIG_QX_NAME_cell_danban, // 分类 淡斑 CONFIG_QX_NAME_cell_fuchen, // 分类 浮尘 CONFIG_QX_NAME_cell_tag, // 分类 标签 + CONFIG_QX_NAME_support_offset, // 支架偏移 + CONFIG_QX_NAME_support_loss, // 支架缺失 CONFIG_QX_NAME_count, }; // 缺陷项对应在参数中的名称 @@ -70,6 +72,8 @@ static std::vector CONFIG_QX_NAME_Names = "danban", "fuchen", "tag", + "support_offset", + "support_loss", }; // 分析类型 @@ -1297,6 +1301,56 @@ struct Base_Function_Edge_Det return str123; } }; + +// 支架检测 +struct Base_Function_Support_Det +{ + bool bOpen; // 是否开启 + std::vector region; + cv::RotatedRect supportRect; + float x_offset; + float y_offset; + float r_offset; + + Base_Function_Support_Det() + { + Init(); + } + + void Init() + { + bOpen = false; + region.clear(); + region.erase(region.begin(), region.end()); + supportRect = cv::RotatedRect(); + x_offset = 0; + y_offset = 0; + r_offset = 0; + } + void copy(Base_Function_Support_Det tem) + { + this->bOpen = tem.bOpen; + this->region.assign(tem.region.begin(), tem.region.end()); + this->supportRect = tem.supportRect; + this->x_offset = tem.x_offset; + this->y_offset = tem.y_offset; + this->r_offset = tem.r_offset; + } + void print(std::string str) + { + printf("%s>>bOpen %d x_offset %f y_offset %f r_offset %f\n", str.c_str(), + bOpen, x_offset, y_offset, r_offset); + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s>>bOpen %d x_offset %f y_offset %f r_offset %f\n", str.c_str(), + bOpen, x_offset, y_offset, r_offset); + std::string str123 = buffer; + return str123; + } + +}; // 基础检测功能 struct BaseCheckFunction { @@ -1304,6 +1358,8 @@ struct BaseCheckFunction Base_Function_Edge_Det edgeDet; Base_Function_SaveImg saveImg; Base_Function_BigNG bigNG; + Base_Function_Support_Det supportDet; + BaseCheckFunction() { Init(); diff --git a/ConfigModule/src/JsonConfig.cpp b/ConfigModule/src/JsonConfig.cpp index 14baac6..2b2d1a8 100644 --- a/ConfigModule/src/JsonConfig.cpp +++ b/ConfigModule/src/JsonConfig.cpp @@ -849,87 +849,17 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value) _config.markLine.Init(); } } - if ("Pin_QX_Detect" == strCode) + if ("Support_QX_Detect" == strCode) { auto value_f = value; // std::cout << value_f << std::endl; // getchar(); - _config.edgeDet.bOpen = value_f["isOpen"].asBool(); - if (_config.edgeDet.bOpen) + _config.supportDet.bOpen = value_f["isOpen"].asBool(); + if (_config.supportDet.bOpen) { - if (value_f["form"]["Search_Config"]["Search_threshold"]) { - _config.edgeDet.Search_threshold = value_f["form"]["Search_Config"]["Search_threshold"].asInt(); - } - if (value_f["form"]["Detect_Config"]["Det_threshold"]) - { - _config.edgeDet.Det_threshold = value_f["form"]["Detect_Config"]["Det_threshold"].asInt(); - } - if (value_f["form"]["Detect_Config"]["Det_Range"]) - { - _config.edgeDet.Det_Range = value_f["form"]["Detect_Config"]["Det_Range"].asInt(); - } - - if (value_f["form"]["Detect_Config"]["QX_Widht_min"]) - { - _config.edgeDet.QX_Widht_min = value_f["form"]["Detect_Config"]["QX_Widht_min"].asInt(); - } - - if (value_f["form"]["Detect_Config"]["QX_Widht_max"]) - { - _config.edgeDet.QX_Widht_max = value_f["form"]["Detect_Config"]["QX_Widht_max"].asInt(); - } - - if (value_f["form"]["Detect_Config"]["QX_Height_min"]) - { - _config.edgeDet.QX_Height_min = value_f["form"]["Detect_Config"]["QX_Height_min"].asInt(); - } - - if (value_f["form"]["Detect_Config"]["QX_Height_max"]) - { - _config.edgeDet.QX_Height_max = value_f["form"]["Detect_Config"]["QX_Height_max"].asInt(); - } - - ///============================================ - - if (value_f["form"]["Jiao_Config"]["LU_Jiao"]) - { - _config.edgeDet.queJiao_LU_Open = value_f["form"]["Jiao_Config"]["LU_Jiao"].asBool(); - } - if (value_f["form"]["Jiao_Config"]["RU_Jiao"]) - { - _config.edgeDet.queJiao_RU_Open = value_f["form"]["Jiao_Config"]["RU_Jiao"].asBool(); - } - - if (value_f["form"]["Jiao_Config"]["LD_Jiao"]) - { - _config.edgeDet.queJiao_LD_Open = value_f["form"]["Jiao_Config"]["LD_Jiao"].asBool(); - } - - if (value_f["form"]["Jiao_Config"]["RD_Jiao"]) - { - _config.edgeDet.queJiao_RD_Open = value_f["form"]["Jiao_Config"]["RD_Jiao"].asBool(); - } - - if (value_f["form"]["Jiao_Config"]["Jiao_Width"]) - { - _config.edgeDet.queJiao_width = value_f["form"]["Jiao_Config"]["Jiao_Width"].asInt(); - } - - if (value_f["form"]["Jiao_Config"]["Jiao_Height"]) - { - _config.edgeDet.queJiao_height = value_f["form"]["Jiao_Config"]["Jiao_Height"].asInt(); - } - - if (value_f["form"]["Draw_Config"]["Open"]) - { - _config.edgeDet.bDrawRoi = value_f["form"]["Draw_Config"]["Open"].asBool(); - } - - // 2、读取区域点 - { - auto value_region = value_f["form"]["Draw_Config"]["Edge_ROI"]; + auto value_region = value_f["form"]["support_param"]["support_region"]; if (value_region.isArray()) { for (int idx = 0; idx < value_region.size(); idx++) @@ -938,25 +868,31 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value) p.x = value_region[idx][0].asInt(); p.y = value_region[idx][1].asInt(); - _config.edgeDet.region.emplace_back(p); + _config.supportDet.region.emplace_back(p); } - if (_config.edgeDet.region.size() > 0) + if (_config.supportDet.region.size() > 0) { - _config.edgeDet.draw_ROI = boundingRect(_config.edgeDet.region); + _config.supportDet.supportRect = minAreaRect(_config.supportDet.region); } } } - if (value_f["form"]["otherConfig"]["bDrawResult"]) + if (value_f["form"]["support_param"]["x_offset"]) { - _config.edgeDet.bDrawResult = value_f["form"]["otherConfig"]["bDrawResult"].asBool(); + _config.supportDet.x_offset = value_f["form"]["support_param"]["x_offset"].asFloat(); + } + if (value_f["form"]["support_param"]["y_offset"]) + { + _config.supportDet.y_offset = value_f["form"]["support_param"]["y_offset"].asFloat(); + } + if (value_f["form"]["support_param"]["r_offset"]) + { + _config.supportDet.r_offset = value_f["form"]["support_param"]["r_offset"].asFloat(); } } else { - _config.edgeDet.Init(); + _config.supportDet.Init(); } - // _config.edgeDet.print("edgeDet"); - // getchar(); } if ("Det_Image_Save" == strCode) {