From 1a02b69445a38b3df00d190d07611d1b37489ea6 Mon Sep 17 00:00:00 2001 From: xiewenji <527774126@qq.com> Date: Mon, 12 Jan 2026 16:22:18 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E4=BC=A0=E7=BB=9F=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=8A=E4=B8=8B=E6=96=99=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ALL_Det/src/ALL_Detect.cpp | 9 +- CheckBase/include/CheckBaseParam.hpp | 10 + CheckBase/src/CheckBaseParam.cpp | 48 +++ Chip_Det/include/Chip_Detect.hpp | 4 +- Chip_Det/src/Chip_Detect.cpp | 527 +++++++++++++++------------ Common/src/CheckUtil.cpp | 18 +- 6 files changed, 372 insertions(+), 244 deletions(-) diff --git a/ALL_Det/src/ALL_Detect.cpp b/ALL_Det/src/ALL_Detect.cpp index a1dde69..ea13f74 100644 --- a/ALL_Det/src/ALL_Detect.cpp +++ b/ALL_Det/src/ALL_Detect.cpp @@ -87,12 +87,19 @@ int ALL_Detect::RunStart(void *pconfig1) break; } case CAMERA_Feeding: + { + if (!m_checkBase) + m_checkBase = std::make_shared(); + runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Chip.json"; + runconfig.str_RunJson = m_cam_param.check_param_path + "param_feed-up.json"; + break; + } case CAMERA_Blanking: { if (!m_checkBase) m_checkBase = std::make_shared(); runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Chip.json"; - // runconfig.str_RunJson = m_cam_param.check_param_path + "param_Chip.json"; + runconfig.str_RunJson = m_cam_param.check_param_path + "param_feed-down.json"; break; } default: diff --git a/CheckBase/include/CheckBaseParam.hpp b/CheckBase/include/CheckBaseParam.hpp index ac48f06..f685baf 100644 --- a/CheckBase/include/CheckBaseParam.hpp +++ b/CheckBase/include/CheckBaseParam.hpp @@ -117,6 +117,11 @@ enum DetRotateType Ratio_180 = 2, Ratio_270 = 3, }; +struct ChipDet{ + cv::Rect rect{0, 0, 0, 0}; + int detWidth = 0; + int detHeight = 0; +}; // 基础检测功能 基础检测 struct Base_Function_DetConfig @@ -132,6 +137,9 @@ struct Base_Function_DetConfig int chip_height_offset_mm; // 芯片高度偏差 mm 1107-add double calibration_coeff_x; // 标定系数x mm/pixel double calibration_coeff_y; // 标定系数y mm/pixel + ChipDet chipDetConfig1; + ChipDet chipDetConfig2; + double chipThr; Base_Function_DetConfig() { Init(); @@ -150,6 +158,7 @@ struct Base_Function_DetConfig chip_height_offset_mm = 0; calibration_coeff_x = 1.0; // 1107-add calibration_coeff_y = 1.0; // 1107-add + chipThr = 0; } void copy(Base_Function_DetConfig tem) @@ -165,6 +174,7 @@ struct Base_Function_DetConfig this->chip_height_offset_mm = tem.chip_height_offset_mm; this->calibration_coeff_x = tem.calibration_coeff_x; // 1107-add this->calibration_coeff_y = tem.calibration_coeff_y; // 1107-add + this->chipThr = tem.chipThr; } void print(std::string str) { diff --git a/CheckBase/src/CheckBaseParam.cpp b/CheckBase/src/CheckBaseParam.cpp index a40ea02..15a2c6a 100644 --- a/CheckBase/src/CheckBaseParam.cpp +++ b/CheckBase/src/CheckBaseParam.cpp @@ -559,5 +559,53 @@ int CheckBaseParamJson::GetFunction(Json::Value value) // pdetConfig->Init(); // } } + + if ("ChipDet" == strCode) // 1009-add + { + auto value_f = value; + std::cout << value_f << std::endl; + // std::cout << "m_pconfig->baseCheckFunction.bChipOffsetOpen=" << m_pconfig->baseCheckFunction.bChipOffsetOpen << std::endl; // 1009-add + Base_Function_DetConfig *pdetConfig = &m_pconfig->baseCheckFunction.detconfig; + pdetConfig->bOpen = value_f["isOpen"].asBool(); + + if (pdetConfig->bOpen) + { + auto DetCrop1 = value_f["form"]["DetCrop1"]; + if (DetCrop1.isObject()) { + cv::Rect rect{ + DetCrop1["crop"]["x"] ? DetCrop1["crop"]["x"].asInt() : 0, + DetCrop1["crop"]["y"] ? DetCrop1["crop"]["y"].asInt() : 0, + DetCrop1["crop"]["width"] ? DetCrop1["crop"]["width"].asInt() : 0, + DetCrop1["crop"]["height"] ? DetCrop1["crop"]["height"].asInt() : 0 + }; + pdetConfig->chipDetConfig1.rect = rect; + pdetConfig->chipDetConfig1.detWidth = DetCrop1["cellWidth"].asInt(); + pdetConfig->chipDetConfig1.detHeight = DetCrop1["cellHeight"].asInt(); + } + + auto DetCrop2 = value_f["form"]["DetCrop2"]; + if (DetCrop2.isObject()) { + cv::Rect rect{ + DetCrop2["crop"]["x"] ? DetCrop2["crop"]["x"].asInt() : 0, + DetCrop2["crop"]["y"] ? DetCrop2["crop"]["y"].asInt() : 0, + DetCrop2["crop"]["width"] ? DetCrop2["crop"]["width"].asInt() : 0, + DetCrop2["crop"]["height"] ? DetCrop2["crop"]["height"].asInt() : 0 + }; + pdetConfig->chipDetConfig2.rect = rect; + pdetConfig->chipDetConfig2.detWidth = DetCrop2["cellWidth"].asInt(); + pdetConfig->chipDetConfig2.detHeight = DetCrop2["cellHeight"].asInt(); + } + + pdetConfig->chipThr = value_f["form"]["ChipThr"].asFloat(); + if (pdetConfig->chipThr <= 0) + { + pdetConfig->chipThr = 0.1; + } + } + // else + // { + // pdetConfig->Init(); + // } + } return 0; } diff --git a/Chip_Det/include/Chip_Detect.hpp b/Chip_Det/include/Chip_Detect.hpp index d0b3d0b..a55a58c 100644 --- a/Chip_Det/include/Chip_Detect.hpp +++ b/Chip_Det/include/Chip_Detect.hpp @@ -28,8 +28,6 @@ private: // 初始化模型 int InitModel(); - int Thread_Run(const cv::Mat &img); - int Draw(const cv::Mat &img, cv::Mat &resultimg); int GetBlob(cv::Mat maskImg); @@ -38,6 +36,8 @@ private: int DetectImg(const cv::Mat &img); + int CutChipDetRoi(const cv::Mat &img, cv::Rect &Roi, std::vector &smallRoiList); + private: int m_nErrorCode; // 错误代码 std::shared_ptr DetImgInfo_shareP; diff --git a/Chip_Det/src/Chip_Detect.cpp b/Chip_Det/src/Chip_Detect.cpp index e920821..ffee59c 100644 --- a/Chip_Det/src/Chip_Detect.cpp +++ b/Chip_Det/src/Chip_Detect.cpp @@ -29,29 +29,29 @@ int Chip_Detect::RunStart(void *pconfig1) m_pRunConfig.copy(*(RunInfoST *)pconfig1); m_bInitSucc = false; - LoadAIModelParm(m_pRunConfig.str_AIModelJson, m_AIModelConfigList); - if (m_AIModelConfigList.get() == nullptr) - { - std::cout << "m_AIModelConfigList is null\n"; - return 1; - } - - m_AIModelConfigList->print("m_AIModelConfigList"); - - // LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig); - // if (m_CheckBaseConfig.get() == nullptr) + // LoadAIModelParm(m_pRunConfig.str_AIModelJson, m_AIModelConfigList); + // if (m_AIModelConfigList.get() == nullptr) // { - // std::cout << "m_CheckBaseConfig is null\n"; + // std::cout << "m_AIModelConfigList is null\n"; // return 1; // } - // m_CheckBaseConfig->print("m_CheckBaseConfig"); - int re = InitModel(); - if (0 != re) + // m_AIModelConfigList->print("m_AIModelConfigList"); + + LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig); + if (m_CheckBaseConfig.get() == nullptr) { - printf("AI_DetModel Init Fail\n"); - return re; + std::cout << "m_CheckBaseConfig is null\n"; + return 1; } + m_CheckBaseConfig->print("m_CheckBaseConfig"); + + // int re = InitModel(); + // if (0 != re) + // { + // printf("AI_DetModel Init Fail\n"); + // return re; + // } printf("init end \n"); m_bInitSucc = true; return 0; @@ -87,22 +87,26 @@ int Chip_Detect::CheckRun() t1 = CheckUtil::getcurTime(); CheckImgInit(); cv::Mat detimg = DetImgInfo_shareP->img; + if (detimg.empty()) { std::cout << "detimg is empty\n"; return 1; } - // if (!CheckUtil::RoiInImg(m_CheckBaseConfig->crop, detimg)) - // { - // return 1; - // } - // if (m_Update_config) - // { - // LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig); - // m_Update_config = false; - // } - // Base_Function_DetConfig *pdetConfig = &m_CheckBaseConfig->baseCheckFunction.detconfig; - // // detimg = DetImgInfo_shareP->img(pdetConfig->cropROI); + Base_Function_DetConfig *pdetConfig = &m_CheckBaseConfig->baseCheckFunction.detconfig; + auto rec1 = pdetConfig->chipDetConfig1.rect; + auto rec2 = pdetConfig->chipDetConfig2.rect; + if (!CheckUtil::RoiInImg(rec1, detimg) || !CheckUtil::RoiInImg(rec2, detimg)) + { + std::cout << "crop roi is invalid\n"; + return 1; + } + if (m_Update_config) + { + LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig); + m_Update_config = false; + } + // detimg = DetImgInfo_shareP->img(pdetConfig->cropROI); if (DetImgInfo_shareP->bdebugSaveImg) { bwriteImg = true; @@ -178,114 +182,6 @@ int Chip_Detect::InitModel() return 0; } -int Chip_Detect::Thread_Run(const cv::Mat &img) -{ - cv::Size windowSize(512, 512); // 每个区域大小 - cv::Size stride(450, 450); // 步长(小于区域大小就是重叠) - - cv::Mat img_gray; - if (img.channels() != 1) - { - cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); - } - else - { - img_gray = img; - } - - cv::Mat blurred; - cv::GaussianBlur(img_gray, blurred, cv::Size(21, 21), 5.5); - - cv::Mat showimg = blurred.clone(); - - cv::Mat maskimg = cv::Mat::zeros(img.size(), CV_8U); - - for (int y = 0; y < img.rows; y += stride.height) - { - for (int x = 0; x < img.cols; x += stride.width) - { - int width = std::min(windowSize.width, img.cols - x); - int height = std::min(windowSize.height, img.rows - y); - cv::Rect roi(x, y, width, height); - - cv::rectangle(showimg, roi, cv::Scalar(255, 0, 50)); - - cv::Mat patch = blurred(roi); - - double meanVal = cv::mean(patch)[0]; - - cv::Mat mean, stddev; - - cv::meanStdDev(patch, mean, stddev); - double sd = stddev.at(0, 0); - - double lowerThresh = m_CheckBaseConfig->det_ratio_min * meanVal; - double upperThresh = m_CheckBaseConfig->det_ratio_max * meanVal; - // 创建二值图 - cv::Mat maskLow, maskHigh, resultMask; - - // 低于下限 - cv::threshold(patch, maskLow, lowerThresh, 255, cv::THRESH_BINARY_INV); - - // 高于上限 - cv::threshold(patch, maskHigh, upperThresh, 255, cv::THRESH_BINARY); - - // 合并两个条件:低或高 - cv::bitwise_or(maskLow, maskHigh, resultMask); - resultMask.copyTo(maskimg(roi), resultMask); - } - } - - cv::Mat m_element; - m_element = getStructuringElement(cv::MORPH_RECT, cv::Size(17, 17)); - cv::Mat m12322; - // 增加闭运算 - cv::morphologyEx(maskimg, m12322, cv::MORPH_CLOSE, m_element); - - GetBlob(m12322); - for (int i = 0; i < m_blob.blobCount; i++) - { - - BlobResult tem; - cv::Rect roi; - roi.x = m_blob.blobTab[i].minx; - roi.y = m_blob.blobTab[i].miny; - roi.width = m_blob.blobTab[i].maxx - m_blob.blobTab[i].minx + 1; - roi.height = m_blob.blobTab[i].maxy - m_blob.blobTab[i].miny + 1; - - tem.roi = roi; - cv::Point pCenter; - pCenter.x = roi.x + roi.width * 0.5; - pCenter.y = roi.y + roi.height * 0.5; - double result = cv::pointPolygonTest(m_CheckBaseConfig->pointArry, pCenter, false); - if (result < 0) - { - printf("Not in region \n"); - continue; - } - - CheckUtil::printROI(roi, "roi"); - CheckUtil::printROI(tem.roi, "tem.roi "); - tem.area_piexl = m_blob.blobTab[i].area; - tem.hj = m_blob.blobTab[i].grayDis; - tem.type = m_blob.blobTab[i].UserErrorType; - - tem.area_mm2 = m_blob.blobTab[i].area * m_CheckBaseConfig->imageScaleParam.fScale_X * m_CheckBaseConfig->imageScaleParam.fScale_Y; - if (tem.area_mm2 > m_CheckBaseConfig->qxSegParam.Area) - { - tem.nresult = 1; - m_CheckResult_shareP->nresult = 1; - } - printf("tem.nresult %d = %f %f \n", tem.nresult, tem.area_mm2, m_CheckBaseConfig->qxSegParam.Area); - m_resultList.push_back(tem); - } - - // cv::imwrite("feeee.png", showimg); - // cv::imwrite("feeeemask.png", maskimg); - // cv::imwrite("feeeemask123.png", m12322); - return 0; -} - int Chip_Detect::Draw(const cv::Mat &img, cv::Mat &resultimg) { if (img.channels() == 1) @@ -639,123 +535,84 @@ int Chip_Detect::ImgAlinRotate(const cv::Mat &img, cv::Mat &alignImg) int Chip_Detect::DetectImg(const cv::Mat &img) { printf("AI_Run>>>>>>>>>>> start \n"); - - cv::Mat ColorImg; - if (img.channels() == 1) + auto basecheckconfig = m_CheckBaseConfig->baseCheckFunction.detconfig; + // 区域1 + std::vector smallRoiList1; + int re = CutChipDetRoi(img, basecheckconfig.chipDetConfig1.rect, smallRoiList1); + if (re != 0) { - cv::cvtColor(img, ColorImg, cv::COLOR_GRAY2BGR); + std::cout << "CutChipDetRoi region1 fail \n"; + return re; } - else + if (smallRoiList1.size() != CHIP_SIZE / 2) { - ColorImg = img; + std::cout << "CutChipDetRoi region1 size error size=" << smallRoiList1.size() << "\n"; + return 1; } - int re = 0; - cv::Mat AlignImg = img; - - printf("start --- seg \n"); - cv::Mat detSrcMask = cv::Mat(AlignImg.rows, AlignImg.cols, CV_8U, cv::Scalar(0)); - ROI2ROI_SCALE SegImgToSrcImg; - // 2、分割 - for (int i = 0; i < m_AIModelConfigList->AIModelConfigList.size(); i++) + // 区域2 + std::vector smallRoiList2; + re = CutChipDetRoi(img, basecheckconfig.chipDetConfig2.rect, smallRoiList2); + if (re != 0) { - AI_Model_Param *p = &m_AIModelConfigList->AIModelConfigList.at(i); - // 分割类型 - if (p->type != AI_Model_Type_Seg) - { - continue; - } - long t1, t2, t3; - t1 = CheckUtil::getcurTime(); - - cv::Size sz; - sz.width = p->in_img.width; - sz.height = p->in_img.height; - cv::Mat temimg; - cv::resize(AlignImg, temimg, sz); - SegImgToSrcImg.setResize(AlignImg, temimg); - - if (bwriteImg) - { - std::string str = p->strAIModelName + "_cut_AI_in.png"; - cv::imwrite(str, temimg); - } - cv::Mat SegmaskImg; - int re = p->pdetect->run(temimg, SegmaskImg, false); - if (re != 0) - { - printf("AI_Run seg run fail \n"); - return re; - } - SegmaskImg *= 255; - if (bwriteImg) - { - std::string str = p->strAIModelName + "_cut_AI_out_.png"; - cv::imwrite(str, SegmaskImg); - } - - cv::Size srcsz; - srcsz.width = AlignImg.cols; - srcsz.height = AlignImg.rows; - cv::Mat temmask; - cv::resize(SegmaskImg, detSrcMask, srcsz); - if (bwriteImg) - { - std::string str = p->strAIModelName + "_detSrcMask_res.png"; - cv::imwrite(str, detSrcMask); - } - break; + std::cout << "CutChipDetRoi region2 fail \n"; + return re; } - printf("End --- seg \n"); - - if (detSrcMask.empty()) + if (smallRoiList2.size() != CHIP_SIZE / 2) { - printf("Seg is Error exit \n"); + std::cout << "CutChipDetRoi region2 size error size=" << smallRoiList2.size() << "\n"; return 1; } - m_resultImg = AlignImg; - - { - // 定义腐蚀操作的内核 - cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); - cv::erode(detSrcMask, detSrcMask, kernel); - } - - std::vector hierarchy; - std::vector> contours; // 0929-add - cv::findContours(detSrcMask, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); - if (contours.size() != CHIP_SIZE) + // 转换为原图rec + for (auto &r : smallRoiList1) { - std::cout << "contours size != " << CHIP_SIZE << ", actual size: " << contours.size() << std::endl; - return 1; + r.x += basecheckconfig.chipDetConfig1.rect.x; + r.y += basecheckconfig.chipDetConfig1.rect.y; } - std::vector boundRect; - for (const auto &contour : contours) + for (auto &r : smallRoiList2) { - boundRect.emplace_back(cv::boundingRect(contour)); + r.x += basecheckconfig.chipDetConfig2.rect.x; + r.y += basecheckconfig.chipDetConfig2.rect.y; } - if (boundRect.empty()) + // 合并两个list + smallRoiList1.insert(smallRoiList1.end(), smallRoiList2.begin(), smallRoiList2.end()); + + if (bwriteImg) { - std::cout << "boundRect is empty\n"; - return 1; + auto test = img.clone(); + for (auto &r : smallRoiList1) + { + cv::rectangle(test, r, cv::Scalar(0, 255, 0), 1); + } + cv::imwrite("tesssss.png", test); // 0929-add } - // 按从上到下、从左到右排序 - std::sort(boundRect.begin(), boundRect.end(), [](const cv::Rect &a, const cv::Rect &b) -> bool + // 排序 + std::sort(smallRoiList1.begin(), smallRoiList1.end(), [&](const cv::Rect &a, const cv::Rect &b) -> bool { int rowTolerance = 50; // 如果在同一行(y坐标相近) if (abs(a.y - b.y) <= rowTolerance) { - return a.x < b.x; // 从左到右 + // CAMERA_Feeding从左到右, CAMERA_Blanking从右到左 + return m_pRunConfig.flag0 == CAMERA_Feeding ? a.x < b.x : a.x > b.x; } // 否则从下到上排序 return a.y > b.y; }); + //初始化存图 + if (img.channels() == 1) + { + cv::cvtColor(img, m_CheckResult_shareP->resultImg, cv::COLOR_GRAY2BGR); + } + else + { + m_CheckResult_shareP->resultImg = img.clone(); + } + int j = 0; - auto showimg = AlignImg.clone(); - for (const auto &rect : boundRect) + for (const auto &rect : smallRoiList1) { - auto smallImg = AlignImg(rect); + auto smallImg = img(rect); cv::Mat gray; if (smallImg.channels() == 3) { @@ -772,29 +629,227 @@ int Chip_Detect::DetectImg(const cv::Mat &img) int totalPixels = binaryImg.rows * binaryImg.cols; double nonZeroRatio = static_cast(nonZeroCount) / totalPixels; int res = 0; - if (nonZeroRatio >= 0.1) + if (nonZeroRatio >= basecheckconfig.chipThr) { res = 1; } m_CheckResult_shareP->chipDataList.emplace_back(res); + auto ts = CheckUtil::getcurTime(); // 绘制 - if (bwriteImg) + // if (bwriteImg) { - std::string chipBinaryImgName = "chip_binary_" + std::to_string(j) + ".png"; - cv::imwrite(chipBinaryImgName, binaryImg); // 0929-add - cv::rectangle(showimg, rect, cv::Scalar(0, 255, 0), 1); - cv::putText(showimg, std::to_string(j), cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 0, 0), 1); - cv::putText(showimg, std::to_string(res) + "::" + std::to_string(nonZeroRatio), cv::Point(rect.x + rect.width / 2 - 50, rect.y + rect.height / 2 + 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1); + if (bwriteImg) + { + std::string chipBinaryImgName = "chip_binary_" + std::to_string(j) + ".png"; + cv::imwrite(chipBinaryImgName, binaryImg); // 0929-add + } + cv::rectangle(m_CheckResult_shareP->resultImg, rect, cv::Scalar(0, 255, 0), 1); + cv::putText(m_CheckResult_shareP->resultImg, std::to_string(j), cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 0, 0), 1); + cv::putText(m_CheckResult_shareP->resultImg, std::to_string(res) + "::" + std::to_string(nonZeroRatio), cv::Point(rect.x + rect.width / 2 - 50, rect.y + rect.height / 2 + 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1); j++; } } + printf("AI_Run>>>>>>>>>>> End \n"); + return 0; +} + +int Chip_Detect::CutChipDetRoi(const cv::Mat &img, cv::Rect &Roi, std::vector &smallRoiList) +{ + if (!CheckUtil::RoiInImg(Roi, img)) + { + std::cout << "CutChipDetRoi --- crop roi is invalid\n"; + return 1; + } + auto detimg1 = img(Roi); + cv::Rect cutRoi; + cutRoi.x = 0; + cutRoi.y = 0; + cutRoi.width = detimg1.cols - 0; + cutRoi.height = detimg1.rows - 0; + auto basecheckconfig = m_CheckBaseConfig->baseCheckFunction.detconfig; + int re = CheckUtil::cutSmallImg(detimg1, smallRoiList, cutRoi, basecheckconfig.chipDetConfig1.detWidth, basecheckconfig.chipDetConfig1.detHeight, 0, 0); + if (re != 0) + { + return re; + } + if (smallRoiList.size() <= 0) + { + std::cout << "CutChipDetRoi --- smallRoiList <= 0\n"; + return 1; + } if (bwriteImg) { - cv::imwrite("chip_res.png", showimg); // 0929-add + auto test = detimg1.clone(); + for (auto &r : smallRoiList) + { + cv::rectangle(test, r, cv::Scalar(0, 255, 0), 1); + } + cv::imwrite("chip_detect_cutroi.png", test); // 0929-add } - - printf("AI_Run>>>>>>>>>>> End \n"); return 0; } + +// int Chip_Detect::DetectImg(const cv::Mat &img) +// { +// printf("AI_Run>>>>>>>>>>> start \n"); + +// cv::Mat ColorImg; +// if (img.channels() == 1) +// { +// cv::cvtColor(img, ColorImg, cv::COLOR_GRAY2BGR); +// } +// else +// { +// ColorImg = img; +// } +// int re = 0; +// cv::Mat AlignImg = img; + +// printf("start --- seg \n"); +// cv::Mat detSrcMask = cv::Mat(AlignImg.rows, AlignImg.cols, CV_8U, cv::Scalar(0)); +// ROI2ROI_SCALE SegImgToSrcImg; +// // 2、分割 +// for (int i = 0; i < m_AIModelConfigList->AIModelConfigList.size(); i++) +// { +// AI_Model_Param *p = &m_AIModelConfigList->AIModelConfigList.at(i); +// // 分割类型 +// if (p->type != AI_Model_Type_Seg) +// { +// continue; +// } +// long t1, t2, t3; +// t1 = CheckUtil::getcurTime(); + +// cv::Size sz; +// sz.width = p->in_img.width; +// sz.height = p->in_img.height; +// cv::Mat temimg; +// cv::resize(AlignImg, temimg, sz); +// SegImgToSrcImg.setResize(AlignImg, temimg); + +// if (bwriteImg) +// { +// std::string str = p->strAIModelName + "_cut_AI_in.png"; +// cv::imwrite(str, temimg); +// } +// cv::Mat SegmaskImg; +// int re = p->pdetect->run(temimg, SegmaskImg, false); +// if (re != 0) +// { +// printf("AI_Run seg run fail \n"); +// return re; +// } +// SegmaskImg *= 255; +// if (bwriteImg) +// { +// std::string str = p->strAIModelName + "_cut_AI_out_.png"; +// cv::imwrite(str, SegmaskImg); +// } + +// cv::Size srcsz; +// srcsz.width = AlignImg.cols; +// srcsz.height = AlignImg.rows; +// cv::Mat temmask; +// cv::resize(SegmaskImg, detSrcMask, srcsz); +// if (bwriteImg) +// { +// std::string str = p->strAIModelName + "_detSrcMask_res.png"; +// cv::imwrite(str, detSrcMask); +// } +// break; +// } +// printf("End --- seg \n"); + +// if (detSrcMask.empty()) +// { +// printf("Seg is Error exit \n"); +// return 1; +// } +// m_resultImg = AlignImg; + +// { +// // 定义腐蚀操作的内核 +// cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); +// cv::erode(detSrcMask, detSrcMask, kernel); +// } + +// std::vector hierarchy; +// std::vector> contours; // 0929-add +// cv::findContours(detSrcMask, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); +// if (contours.size() != CHIP_SIZE) +// { +// std::cout << "contours size != " << CHIP_SIZE << ", actual size: " << contours.size() << std::endl; +// return 1; +// } +// std::vector boundRect; +// for (const auto &contour : contours) +// { +// boundRect.emplace_back(cv::boundingRect(contour)); +// } +// if (boundRect.empty()) +// { +// std::cout << "boundRect is empty\n"; +// return 1; +// } + +// // 按从上到下、从左到右排序 +// std::sort(boundRect.begin(), boundRect.end(), [](const cv::Rect &a, const cv::Rect &b) -> bool +// { +// int rowTolerance = 50; +// // 如果在同一行(y坐标相近) +// if (abs(a.y - b.y) <= rowTolerance) +// { +// return a.x < b.x; // 从左到右 +// } +// // 否则从下到上排序 +// return a.y > b.y; }); + +// int j = 0; +// auto showimg = AlignImg.clone(); +// for (const auto &rect : boundRect) +// { +// auto smallImg = AlignImg(rect); +// cv::Mat gray; +// if (smallImg.channels() == 3) +// { +// cv::cvtColor(smallImg, gray, cv::COLOR_BGR2GRAY); +// } +// else +// { +// gray = smallImg.clone(); +// } +// cv::Mat binaryImg; +// // cv::threshold(gray, binaryImg, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU); +// cv::threshold(gray, binaryImg, 128, 255, cv::THRESH_BINARY_INV); +// int nonZeroCount = cv::countNonZero(binaryImg); +// int totalPixels = binaryImg.rows * binaryImg.cols; +// double nonZeroRatio = static_cast(nonZeroCount) / totalPixels; +// int res = 0; +// if (nonZeroRatio >= 0.1) +// { +// res = 1; +// } +// m_CheckResult_shareP->chipDataList.emplace_back(res); + +// // 绘制 +// if (bwriteImg) +// { +// std::string chipBinaryImgName = "chip_binary_" + std::to_string(j) + ".png"; +// cv::imwrite(chipBinaryImgName, binaryImg); // 0929-add +// cv::rectangle(showimg, rect, cv::Scalar(0, 255, 0), 1); +// cv::putText(showimg, std::to_string(j), cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 0, 0), 1); +// cv::putText(showimg, std::to_string(res) + "::" + std::to_string(nonZeroRatio), cv::Point(rect.x + rect.width / 2 - 50, rect.y + rect.height / 2 + 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1); +// j++; +// } +// } + +// if (bwriteImg) +// { +// cv::imwrite("chip_res.png", showimg); // 0929-add +// } + +// printf("AI_Run>>>>>>>>>>> End \n"); +// return 0; +// } diff --git a/Common/src/CheckUtil.cpp b/Common/src/CheckUtil.cpp index 3b0566a..8289e07 100644 --- a/Common/src/CheckUtil.cpp +++ b/Common/src/CheckUtil.cpp @@ -146,6 +146,14 @@ int CheckUtil::printROI(cv::Rect roi, std::string str) bool CheckUtil::RoiInImg(cv::Rect roi, cv::Mat img) { + if (img.empty()) + return false; + + // 检查 ROI 是否有效 + if (roi.width <= 0 || roi.height <= 0) + { + return false; + } if ((roi & cv::Rect(0, 0, img.cols, img.rows)) == roi) { return true; @@ -510,16 +518,16 @@ int CheckUtil::adjustRectToBounds(cv::Rect &rect, const cv::Size &imgSize) double CheckUtil::point2fDistance(const cv::Point2f &p1, const cv::Point2f &p2) { - double dx=p1.x-p2.x; - double dy=p1.y-p2.y; - double distance=std::sqrt(static_cast(dx*dx+dy*dy)); + double dx = p1.x - p2.x; + double dy = p1.y - p2.y; + double distance = std::sqrt(static_cast(dx * dx + dy * dy)); return distance; } cv::Point CheckUtil::getCenterPoint(cv::Rect rect) { cv::Point cpt; - cpt.x=rect.x+cvRound(rect.width/2.0); - cpt.y=rect.y+cvRound(rect.height/2.0); + cpt.x = rect.x + cvRound(rect.width / 2.0); + cpt.y = rect.y + cvRound(rect.height / 2.0); return cpt; }