diff --git a/AIEngineModule/include_base/AI_Factory.h b/AIEngineModule/include_base/AI_Factory.h index de005b8..9ac9243 100644 --- a/AIEngineModule/include_base/AI_Factory.h +++ b/AIEngineModule/include_base/AI_Factory.h @@ -174,7 +174,8 @@ public: std::shared_ptr AI_defect_zf; // L127 L255 - std::shared_ptr AI_defect_bq; // L127 L255 + std::shared_ptr AI_defect_bq; + std::shared_ptr AI_defect_Tag; std::shared_ptr AI_defect_127Cell; // L127 L255 diff --git a/AIEngineModule/src/AI_Factory.cpp b/AIEngineModule/src/AI_Factory.cpp index dfdbbe5..3d79bcb 100644 --- a/AIEngineModule/src/AI_Factory.cpp +++ b/AIEngineModule/src/AI_Factory.cpp @@ -143,7 +143,7 @@ int AIFactory::InitALLAIModle(GPU_Config gupconfig) boe_config.inputType = AIModel_Base::Input_CHW; AI_defect_zf->Init(boe_config); } - // 标签 检测 + // 标签 定位 if (!AI_defect_bq) { AI_defect_bq = AIModel_Base::GetInstance(); @@ -154,6 +154,17 @@ int AIFactory::InitALLAIModle(GPU_Config gupconfig) boe_config.inputType = AIModel_Base::Input_CHW; AI_defect_bq->Init(boe_config); } + // 标签 检测 + if (!AI_defect_Tag) + { + AI_defect_Tag = AIModel_Base::GetInstance(); + AIModel_Base::AIModelRun_Config boe_config; + boe_config.gpuconfig.copy(gupconfig); + boe_config.strPath = "/home/aidlux/BOE/UseModel_FOG/defect_L127.engine"; + boe_config.strName = "tag"; + boe_config.inputType = AIModel_Base::Input_CHW; + AI_defect_Tag->Init(boe_config); + } // 字符 127cell if (!AI_defect_127Cell) { diff --git a/AlgorithmModule/include/ImageAllResult.h b/AlgorithmModule/include/ImageAllResult.h index 20f17b3..36976f0 100644 --- a/AlgorithmModule/include/ImageAllResult.h +++ b/AlgorithmModule/include/ImageAllResult.h @@ -175,6 +175,7 @@ public: std::shared_ptr qx_DetAIResult; // BLob 检测要用到的一些 参数 。 std::shared_ptr cell127_DetAIResult; // 127 cell 检测要用到的一些 参数 。 + std::shared_ptr bq_DetAIResult; // BQ标签检测要用到的一些 参数 。 // 结果图片 cv::Mat resultImg; diff --git a/AlgorithmModule/include/ImageDetConfig.h b/AlgorithmModule/include/ImageDetConfig.h index 9859ef6..a332917 100644 --- a/AlgorithmModule/include/ImageDetConfig.h +++ b/AlgorithmModule/include/ImageDetConfig.h @@ -345,7 +345,10 @@ struct BQ_Result { int nresult = 1; bool bShield_BQ = true; // 是否屏蔽标签 - std::vector pBQ_roiList; // 标签的区域 + bool bBQ_AI_Det = false; // 是否启用标签独立AI检测 + std::vector pBQ_roiList; // 标签的原始区域 + std::vector pBQ_expandedRoiList; // 标签的扩展后区域(用于AI检测) + std::vector pBQ_cropImages; // 标签扩展区域图像 std::vector BQ_centerPoint; // 标签的中心点位置 }; struct CameraBaseResult diff --git a/AlgorithmModule/include/ImgCheckAnalysisy.hpp b/AlgorithmModule/include/ImgCheckAnalysisy.hpp index a8e22bf..fc4ff95 100644 --- a/AlgorithmModule/include/ImgCheckAnalysisy.hpp +++ b/AlgorithmModule/include/ImgCheckAnalysisy.hpp @@ -194,6 +194,12 @@ private: // 获得 127cell blob int GetBlob_127cell(); + // 获得 BQ标签 blob + int GetBlob_BQ(); + + // BQ标签 AI 检测 + int AI_Detect_BQ(); + // 对AI mask图片进行 结果处理 int AIMaskDet(); diff --git a/AlgorithmModule/src/AI_Edge_Algin.cpp b/AlgorithmModule/src/AI_Edge_Algin.cpp index 0553a5a..c5897f3 100644 --- a/AlgorithmModule/src/AI_Edge_Algin.cpp +++ b/AlgorithmModule/src/AI_Edge_Algin.cpp @@ -123,7 +123,7 @@ int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared return 7; } - if (max_contour_index >= 0) + if (max_contour_index >= 0&& contours.size() > 0) { result_roi = boundingRect(contours[max_contour_index]); } diff --git a/AlgorithmModule/src/CameraCheckAnalysisy.cpp b/AlgorithmModule/src/CameraCheckAnalysisy.cpp index 0ddf6e5..00ddbf2 100644 --- a/AlgorithmModule/src/CameraCheckAnalysisy.cpp +++ b/AlgorithmModule/src/CameraCheckAnalysisy.cpp @@ -697,6 +697,7 @@ int CameraCheckAnalysisy::preDet_BQ(const cv::Mat &L255CutImg, std::shared_ptrcameraBaseResult->pBQ_Result = std::make_shared(); m_pCheck_Result->cameraBaseResult->pBQ_Result->bShield_BQ = m_AnalysisyConfig.commonCheckConfig.baseConfig.bShield_BQ; + m_pCheck_Result->cameraBaseResult->pBQ_Result->bBQ_AI_Det = m_pbaseCheckFunction->Det_BQ.bBQ_AI_Det; cv::Rect Det_CropRoi = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->cutRoi; @@ -725,11 +726,25 @@ int CameraCheckAnalysisy::preDet_BQ(const cv::Mat &L255CutImg, std::shared_ptrcameraBaseResult->pBQ_Result->pBQ_roiList.size(); i++) { cv::Rect boundingRect = m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.at(i); - boundingRect.x -= 5; - boundingRect.y -= 5; - boundingRect.width += 10; - boundingRect.height += 10; - detImg_mask(boundingRect).setTo(255); + int BQ_expand = m_pbaseCheckFunction->Det_BQ.BQ_expand; + boundingRect.x -= BQ_expand; + boundingRect.y -= BQ_expand; + boundingRect.width += 2 * BQ_expand; + boundingRect.height += 2 * BQ_expand; + boundingRect = boundingRect & cv::Rect(0, 0, detImg_mask.cols, detImg_mask.rows); + if (boundingRect.width > 0 && boundingRect.height > 0) + { + // 同时屏蔽主AI,避免重复检测 + detImg_mask(boundingRect).setTo(255); + + // 保存裁剪图像供独立BQ AI检测 + if (m_pbaseCheckFunction->Det_BQ.bBQ_AI_Det) + { + m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_expandedRoiList.push_back(boundingRect); + cv::Mat bqCrop = L255CutImg(boundingRect).clone(); + m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_cropImages.push_back(bqCrop); + } + } } if (L255->result->in_shareImage->bDebugsaveImg) { diff --git a/AlgorithmModule/src/ImgCheckAnalysisy.cpp b/AlgorithmModule/src/ImgCheckAnalysisy.cpp index 0bc9f13..4d75d67 100644 --- a/AlgorithmModule/src/ImgCheckAnalysisy.cpp +++ b/AlgorithmModule/src/ImgCheckAnalysisy.cpp @@ -170,7 +170,7 @@ int ImgCheckAnalysisy::GetStatus() std::string ImgCheckAnalysisy::GetVersion() { - return std::string("BOE_1.2.7_" + std::string(__DATE__) + "_" + std::string(__TIME__)); + return std::string("BOE_1.2.8_" + std::string(__DATE__) + "_" + std::string(__TIME__)); } std::string ImgCheckAnalysisy::GetErrorInfo() @@ -518,6 +518,14 @@ int ImgCheckAnalysisy::CheckRun() Edge_Det(); + // BQ标签AI检测 + { + long t_BQ_s = CheckUtil::getcurTime(); + int recBQ = AI_Detect_BQ(); + long t_BQ_e = CheckUtil::getcurTime(); + m_pdetlog->AddCheckstr(PrintLevel_0, "4、BQ Detect", "-------------------------BQ AI Detect--------%ld ms-------\n", t_BQ_e - t_BQ_s); + } + m_CheckResult_shareP->resultMaskImg = m_pImageAllResult->qx_DetAIResult->AI_MaskImg; // cv::imwrite("dddddddd.png", m_pImageAllResult->qx_DetAIResult->AI_MaskImg); @@ -1697,6 +1705,8 @@ int ImgCheckAnalysisy::GetALLBlob() re = GetBlob_QX(); long t4 = CheckUtil::getcurTime(); re = GetBlob_127cell(); + long t5 = CheckUtil::getcurTime(); + re = GetBlob_BQ(); if (blobs.blobCount > 100) { @@ -1706,8 +1716,8 @@ int ImgCheckAnalysisy::GetALLBlob() long te = CheckUtil::getcurTime(); m_pdetlog->AddCheckstr(PrintLevel_0, strBaseLog, - "---GetALLBlob End ;use time %ld ms yx %ld ms lack %ld ms qx %ld ms 127 %ld ms", - te - t1, t2 - t1, t3 - t2, t4 - t3, te - t4); + "---GetALLBlob End ;use time %ld ms yx %ld ms lack %ld ms qx %ld ms 127 %ld ms bq %ld ms", + te - t1, t2 - t1, t3 - t2, t4 - t3, t5 - t4, te - t5); // getchar(); return 0; @@ -2145,6 +2155,199 @@ int ImgCheckAnalysisy::GetBlob_127cell() return 0; } +// BQAI检测 +int ImgCheckAnalysisy::AI_Detect_BQ() +{ + std::string strBaseLog = "AI_Detect_BQ"; + + // 检查BQ标签AI检测是否启用 + if (!m_pImageAllResult->cameraBaseResult->pBQ_Result) + { + return 0; + } + if (!m_pImageAllResult->cameraBaseResult->pBQ_Result->bBQ_AI_Det) + { + return 0; + } + + int bqNum = static_cast(m_pImageAllResult->cameraBaseResult->pBQ_Result->pBQ_cropImages.size()); + if (bqNum <= 0) + { + return 0; + } + + m_pdetlog->AddCheckstr(PrintLevel_1, strBaseLog, "============= Start, BQ num = %d", bqNum); + long ts = CheckUtil::getcurTime(); + + // 初始化BQ AI检测结果 + m_pImageAllResult->bq_DetAIResult = std::make_shared(); + std::shared_ptr pDetAIResult = m_pImageAllResult->bq_DetAIResult; + + // 使用与主检测相同的AI模型(后续更改为BQ AI模型) + std::shared_ptr pAI_Model = AI_Factory->AI_defect_Tag; + + int AIInputImg_width = pAI_Model->input_0.width; + int AIInputImg_height = pAI_Model->input_0.height; + cv::Size modelInputSize(AIInputImg_width, AIInputImg_height); + + // 创建全图大小的AI mask(与主检测detImg同尺寸) + cv::Mat AI_detImage = m_pImageAllResult->AI_detImg; + pDetAIResult->AI_MaskImg = cv::Mat::zeros(AI_detImage.size(), CV_8UC1); + + // 先提交所有BQ AI推理任务(仿照AI_Detect_QX的提交-收集模式) + int submitted = 0; + int completed = 0; + while (completed < bqNum) + { + // 提交任务(限制并发数不超过2,避免占用过多资源) + if (submitted < bqNum && runner->GetProcessingCount() < 2) + { + cv::Mat bqCrop = m_pImageAllResult->cameraBaseResult->pBQ_Result->pBQ_cropImages.at(submitted); + if (!bqCrop.empty()) + { + cv::Mat resizedCrop; + cv::resize(bqCrop, resizedCrop, modelInputSize); + + std::shared_ptr task = std::make_shared(); + task->id = submitted; + task->roi = cv::Rect(0, 0, modelInputSize.width, modelInputSize.height); + task->input = resizedCrop; + task->output = std::make_shared(); + task->engine = pAI_Model; + + runner->SubmitTask(task); + } + submitted++; + } + + // 收集已完成的结果 + std::shared_ptr result; + if (runner->PopResult(result)) + { + int idx = result->id; + if (idx >= 0 && idx < bqNum) + { + cv::Rect bqRoi = m_pImageAllResult->cameraBaseResult->pBQ_Result->pBQ_expandedRoiList.at(idx); + cv::Rect validRoi = bqRoi & cv::Rect(0, 0, AI_detImage.cols, AI_detImage.rows); + + if (validRoi.width > 0 && validRoi.height > 0) + { + cv::Mat &outMask = *(result->output); + if (!outMask.empty()) + { + // 将AI输出mask resize回BQ裁剪图原始尺寸 + cv::Mat resizedMask; + cv::resize(outMask, resizedMask, cv::Size(bqRoi.width, bqRoi.height)); + + // 将BQ的mask结果放到全图mask的对应位置 + resizedMask.copyTo(pDetAIResult->AI_MaskImg(validRoi), resizedMask); + + m_pdetlog->AddCheckstr(PrintLevel_2, strBaseLog, "BQ[%d] AI done, roi=[%d,%d,%d,%d]", + idx, validRoi.x, validRoi.y, validRoi.width, validRoi.height); + } + else + { + m_pdetlog->AddCheckstr(PrintLevel_2, strBaseLog, "BQ[%d] AI output empty", idx); + } + } + } + completed++; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + } + + long te = CheckUtil::getcurTime(); + m_pdetlog->AddCheckstr(PrintLevel_1, strBaseLog, "============= End, time=%ld ms", te - ts); + + // 调试存图 + if (DetImgInfo_shareP->bDebugsaveImg) + { + cv::imwrite(m_strCurDetCamChannel + "_AI_BQ_mask.png", pDetAIResult->AI_MaskImg); + } + + return 0; +} + +int ImgCheckAnalysisy::GetBlob_BQ() +{ + std::string strBaseLog = "GetBlob_BQ"; + + // 检查BQ标签AI检测是否启用 + if (!m_pImageAllResult->cameraBaseResult->pBQ_Result) + { + return 0; + } + if (!m_pImageAllResult->cameraBaseResult->pBQ_Result->bBQ_AI_Det) + { + return 0; + } + if (!m_pImageAllResult->bq_DetAIResult) + { + m_pdetlog->AddCheckstr(PrintLevel_2, strBaseLog, "bq_DetAIResult is null, skip"); + return 0; + } + + std::shared_ptr pDetAIResult = m_pImageAllResult->bq_DetAIResult; + cv::Mat maskimg = pDetAIResult->AI_MaskImg; + if (maskimg.empty()) + { + m_pdetlog->AddCheckstr(PrintLevel_2, strBaseLog, "AI_MaskImg is empty, skip"); + return 0; + } + + long t1 = CheckUtil::getcurTime(); + + // 使用与主流程相同的blob提取方式:GetBlobs_V3 + // BQ检测的mask中,缺陷像素值为非零值 + ERROR_DOTS_BLOBS blobs_bq; + memset(&blobs_bq, 0x00, sizeof(ERROR_DOTS_BLOBS)); + + unsigned char *pGrayErrordata = (unsigned char *)maskimg.data; + int width = maskimg.cols; + int height = maskimg.rows; + int minArea = 10; // BQ标签区域最小缺陷面积阈值 + + // 使用逐像素扫描方式提取blob(GetBlobs_V3对mask中的非零值进行blob提取) + GetBlobs_V3(&blobs_bq, pGrayErrordata, width, height, minArea); + + // 设置BQ blob的默认缺陷类型(后续分类会重新确定类型) + // 使用非cell类型,确保进入AI_Classify_New分类流程 + for (int i = 0; i < blobs_bq.blobCount; i++) + { + blobs_bq.blobTab[i].ErrType = CONFIG_QX_NAME_LD; // 以亮点作为初始类型,后续分类修正 + } + + // 将BQ的blob汇入主blob列表 + PushBlob(&blobs, &blobs_bq); + + long te = CheckUtil::getcurTime(); + m_pdetlog->AddCheckstr(PrintLevel_1, strBaseLog, + "BQ blob num = %d, merged to main blobs (total=%d), time=%ld ms", + blobs_bq.blobCount, blobs.blobCount, te - t1); + + // 调试存图 + if (DetImgInfo_shareP->bDebugsaveImg && blobs_bq.blobCount > 0) + { + cv::Mat tm; + cv::cvtColor(maskimg, tm, cv::COLOR_GRAY2RGB); + for (int i = 0; i < blobs_bq.blobCount; i++) + { + cv::Rect roi; + roi.x = blobs_bq.blobTab[i].minx; + roi.y = blobs_bq.blobTab[i].miny; + roi.width = blobs_bq.blobTab[i].maxx - blobs_bq.blobTab[i].minx + 1; + roi.height = blobs_bq.blobTab[i].maxy - blobs_bq.blobTab[i].miny + 1; + cv::rectangle(tm, roi, cv::Scalar(0, 0, 255), 2); + } + cv::imwrite(m_strCurDetCamChannel + "_BQ_blob.png", tm); + } + + return 0; +} + int ImgCheckAnalysisy::AIMaskDet() { m_pdetlog->AddCheckstr(PrintLevel_0, "AIMaskDet", "=======start"); diff --git a/ConfigModule/include/CheckConfigDefine.h b/ConfigModule/include/CheckConfigDefine.h index e1ddb7c..9d031bc 100644 --- a/ConfigModule/include/CheckConfigDefine.h +++ b/ConfigModule/include/CheckConfigDefine.h @@ -2261,6 +2261,40 @@ struct Base_Function_AD_Check } }; +struct Base_Function_Det_BQ +{ + int BQ_expand; + bool bBQ_AI_Det; // 是否启用标签独立AI检测,汇入主流程分类 + + Base_Function_Det_BQ() + { + Init(); + } + void Init() + { + BQ_expand = 0; + bBQ_AI_Det = false; + } + void copy(Base_Function_Det_BQ tem) + { + this->BQ_expand = tem.BQ_expand; + this->bBQ_AI_Det = tem.bBQ_AI_Det; + } + void print(std::string str) + { + printf("%d BQ_expand %d bBQ_AI_Det %d\n", str.c_str(), + BQ_expand, bBQ_AI_Det); + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%d BQ_expand %d bBQ_AI_Det %d\n", str.c_str(), + BQ_expand, bBQ_AI_Det); + std::string str123 = buffer; + return str123; + } + +}; // 基础检测功能 struct BaseCheckFunction { @@ -2270,6 +2304,7 @@ struct BaseCheckFunction Base_Function_BigNG bigNG; Base_Function_EdgeChannel edgeChannel; Base_Function_AD_Check ad_check; + Base_Function_Det_BQ Det_BQ; BaseCheckFunction() { Init(); @@ -2282,6 +2317,7 @@ struct BaseCheckFunction bigNG.Init(); edgeChannel.Init(); ad_check.Init(); + Det_BQ.Init(); } void copy(BaseCheckFunction tem) { @@ -2291,6 +2327,7 @@ struct BaseCheckFunction this->bigNG.copy(tem.bigNG); this->edgeChannel.copy(tem.edgeChannel); this->ad_check.copy(tem.ad_check); + this->Det_BQ.copy(tem.Det_BQ); } void print(std::string str) { @@ -2301,6 +2338,7 @@ struct BaseCheckFunction bigNG.print("bigNG"); edgeChannel.print("edgeChannel"); ad_check.print("ad_check"); + Det_BQ.print("Det_BQ"); } std::string GetInfo(std::string str) { @@ -2311,6 +2349,7 @@ struct BaseCheckFunction str123 += bigNG.GetInfo("bigNG"); str123 += edgeChannel.GetInfo("edgeChannel"); str123 += ad_check.GetInfo("ad_check"); + str123 += Det_BQ.GetInfo("Det_BQ"); // str123 += "\n"; return str123; } diff --git a/ConfigModule/src/JsonConfig.cpp b/ConfigModule/src/JsonConfig.cpp index a2e1f79..ba11b73 100644 --- a/ConfigModule/src/JsonConfig.cpp +++ b/ConfigModule/src/JsonConfig.cpp @@ -1471,6 +1471,21 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value) _config.ad_check.Init(); } } - + // 标签配置参数 + if ("Det_BQ" == strCode) + { + auto value_f = value; + // std::cout << value_f << std::endl; + // getchar(); + _config.Det_BQ.bBQ_AI_Det = value_f["isOpen"].asBool(); + { + if (value_f["form"]["bShield_BQ"]["BQ_expand"]) + { + _config.Det_BQ.BQ_expand = value_f["form"]["bShield_BQ"]["BQ_expand"].asInt(); + } + } + // _config.edgeDet.print("edgeDet"); + // getchar(); + } return 0; }