From 61f3682680f8002659cf5b8992d745404a891079 Mon Sep 17 00:00:00 2001 From: liusiyang Date: Wed, 9 Sep 2026 10:08:12 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E4=BC=A0=E7=BB=9F=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AlgorithmModule/src/ALLImgCheckAnalysisy.cpp | 7 +-- AlgorithmModule/src/ImgCheckAnalysisy.cpp | 46 +++++++++++++++++--- TcsCheckModule/include/TcsCheck.h | 1 + TcsCheckModule/src/TcsCheck.cpp | 29 +++--------- 4 files changed, 52 insertions(+), 31 deletions(-) diff --git a/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp b/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp index f973d06..d385ea2 100644 --- a/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp +++ b/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp @@ -420,7 +420,8 @@ int ALLImgCheckAnalysisy::InitData() int ALLImgCheckAnalysisy::Det_Product(std::shared_ptr &product) { - + string cur_time_s = CheckUtil::getCurTimeHMS(); + printf("[%s]>>>>>>>>>>>>>>>Det_Product****************det Start************\n", cur_time_s.c_str()); // 处理每个相机 while (true) { @@ -449,8 +450,8 @@ int ALLImgCheckAnalysisy::Det_Product(std::shared_ptr &product) // AnalysiyAll(0); SetProductResult(product); product->SetCheckEnd(); - string cur_time = CheckUtil::getCurTimeHMS(); - printf("[%s]>>>>>>>>>>>>>>>Det_Product****************det End************\n", cur_time.c_str()); + string cur_time_e = CheckUtil::getCurTimeHMS(); + printf("[%s]>>>>>>>>>>>>>>>Det_Product****************det End************\n", cur_time_e.c_str()); return 0; } diff --git a/AlgorithmModule/src/ImgCheckAnalysisy.cpp b/AlgorithmModule/src/ImgCheckAnalysisy.cpp index f1d5545..5528047 100644 --- a/AlgorithmModule/src/ImgCheckAnalysisy.cpp +++ b/AlgorithmModule/src/ImgCheckAnalysisy.cpp @@ -465,9 +465,12 @@ int GetEdgeRoi(Mat img, Rect &new_roi, cv::RotatedRect &rotated_roi, float scale // 二值化找最大连通域 Mat r_img_bin; - threshold(r_img, r_img_bin, 15, 255, THRESH_BINARY); + threshold(r_img, r_img_bin, 35, 255, THRESH_BINARY); + // 做一步闭运算 + Mat r_img_bin_close; + morphologyEx(r_img_bin, r_img_bin_close, MORPH_CLOSE, Mat::ones(15, 15, CV_8U)); std::vector> contours; - cv::findContours(r_img_bin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(r_img_bin_close, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); if (contours.empty()) { return 2; @@ -779,7 +782,6 @@ int ImgCheckAnalysisy::CheckRun() { m_pdetlog->bPrintStr = true; } - m_pdetlog->bPrintStr = true; m_pdetlog->AddCheckstr(PrintLevel_0, "1、basic Info", "---------------------------1、basic Info---------------------------------"); m_pdetlog->AddCheckstr(PrintLevel_0, "Version", "%s", GetVersion().c_str()); @@ -2509,9 +2511,43 @@ int ImgCheckAnalysisy::BLobToDetResult() long t1 = CheckUtil::getcurTime(); m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", " Start old qx num %ld", m_pDetResult->pQx_ErrorList->size()); + // 传统检测:按 nAreaFilter(原图面积)+ nCountFilter(个数)直接卡控最终上报。 + // 对 blobs.blobTab 按面积降序,过滤 area <= nAreaFilter 的 blob,再取前 nCountFilter 个。 + // AI 路径(bOpen=false)不做此过滤,保持原有全量上报。 + const bool bTcsCountFilter = (m_pbaseCheckFunction != nullptr && m_pbaseCheckFunction->traditionDet.bOpen); + const float fAreaFilter = bTcsCountFilter ? m_pbaseCheckFunction->traditionDet.nAreaFilter : 0.0f; + const int nCountFilter = bTcsCountFilter ? m_pbaseCheckFunction->traditionDet.nCountFilter : blobs.blobCount; + int nFiltered = 0; + + // 传统路径:构造按面积降序的索引,用于面积 + 个数卡控 + std::vector sortedIdx; + int nReport = blobs.blobCount; // 实际需要遍历上报的 blob 数量 + if (bTcsCountFilter) + { + sortedIdx.resize(blobs.blobCount); + for (int j = 0; j < blobs.blobCount; j++) sortedIdx[j] = j; + std::sort(sortedIdx.begin(), sortedIdx.end(), [&](int a, int b) { + return blobs.blobTab[a].area > blobs.blobTab[b].area; + }); + + // 已按面积降序:第一个 area <= nAreaFilter 的 blob 即为有效区间终点 + nReport = 0; + while (nReport < blobs.blobCount && blobs.blobTab[sortedIdx[nReport]].area > fAreaFilter) + { + nReport++; + } + if (nReport > nCountFilter) + { + nReport = nCountFilter; + } + nFiltered = blobs.blobCount - nReport; + } + // 遍历每个检测blob - for (int i = 0; i < blobs.blobCount; i++) + for (int idx = 0; idx < nReport; idx++) { + const int i = bTcsCountFilter ? sortedIdx[idx] : idx; + cv::Rect roi; roi.x = blobs.blobTab[i].minx; roi.y = blobs.blobTab[i].miny; @@ -2591,7 +2627,7 @@ int ImgCheckAnalysisy::BLobToDetResult() } } long t2 = CheckUtil::getcurTime(); - m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", " end qx num %ld use time %ld", m_pDetResult->pQx_ErrorList->size(), t2 - t1); + m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", " end qx num %ld filtered %d use time %ld", m_pDetResult->pQx_ErrorList->size(), nFiltered, t2 - t1); return 0; } diff --git a/TcsCheckModule/include/TcsCheck.h b/TcsCheckModule/include/TcsCheck.h index deb78d9..3ddb7ae 100644 --- a/TcsCheckModule/include/TcsCheck.h +++ b/TcsCheckModule/include/TcsCheck.h @@ -130,6 +130,7 @@ private: void Process(bool bDraw = false); // 纯分类:对二值图做连通域分析+缺陷分类,结果写入 m_vecDefectInfo + // 面积/个数过滤已上移至 BLobToDetResult 统一处理,此处仅做缺陷类型打标签 void ClassifyBlobs(const cv::Mat& blurCrop, const cv::Mat& imgBlob); // 纯绘制:基于 m_vecDefectInfo 绘制缺陷标注 cv::Mat DrawBlobInfoImage(const cv::Mat& imgCrop, const cv::Mat& imgBlob); diff --git a/TcsCheckModule/src/TcsCheck.cpp b/TcsCheckModule/src/TcsCheck.cpp index 29713aa..639656a 100644 --- a/TcsCheckModule/src/TcsCheck.cpp +++ b/TcsCheckModule/src/TcsCheck.cpp @@ -240,31 +240,14 @@ void CTcsCheck::ClassifyBlobs(const cv::Mat& blurCrop, const cv::Mat& imgBlob) // logStep("1.连通域分析"); if (nLabels <= 1) return; - struct BlobItem { int label; int area; }; - std::vector blobs; - blobs.reserve(std::max(0, nLabels - 1)); - for (int label = 1; label < nLabels; ++label) { - const int area = stats.at(label, cv::CC_STAT_AREA); - if (area > m_cpCfg.nAreaFilter) { - blobs.push_back({ label, area }); - } - } - // logStep("2.面积过滤"); - if (blobs.empty()) return; - - std::sort(blobs.begin(), blobs.end(), [](const BlobItem& a, const BlobItem& b) { - return a.area > b.area; - }); - // logStep("3.面积排序"); - - // 大块缺陷的面积阈值 + // 大块缺陷的面积阈值(分类决策用,非过滤) const int largeAreaThreshold = std::max(1, m_cpCfg.nBlockSize * m_cpCfg.nBlockSize / 4); - const int topK = std::min(m_cpCfg.nCountFilter, static_cast(blobs.size())); - - for (int i = 0; i < topK; ++i) { - const int label = blobs[i].label; - const int area = blobs[i].area; + // 面积/个数过滤已统一上移到 BLobToDetResult 处理, + // 此处对所有连通域逐一分类,仅做缺陷类型打标签。 + for (int label = 1; label < nLabels; ++label) { + const int area = stats.at(label, cv::CC_STAT_AREA); + if (area < 5) continue; // bounding rect const int x = stats.at(label, cv::CC_STAT_LEFT); const int y = stats.at(label, cv::CC_STAT_TOP);