From a50a2c1c6ae670d5e84ebddec89b812a6f8dd3ce Mon Sep 17 00:00:00 2001 From: xiewenji <527774126@qq.com> Date: Thu, 4 Dec 2025 15:10:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=A8=8B=E5=BA=8F=EF=BC=8Cto?= =?UTF-8?q?p=E7=9B=B8=E6=9C=BA=E5=A2=9E=E5=8A=A0=E4=BA=8C=E7=BB=B4?= =?UTF-8?q?=E7=A0=81=E8=AF=86=E5=88=AB=E5=AE=9A=E4=BD=8D=EF=BC=8C=E5=BA=95?= =?UTF-8?q?=E9=83=A8=E7=9B=B8=E6=9C=BA=E5=A2=9E=E5=8A=A0=E6=A0=87=E5=AE=9A?= =?UTF-8?q?=E7=B3=BB=E6=95=B0=E5=8F=82=E4=B8=8E=E8=AE=A1=E7=AE=97=E5=81=8F?= =?UTF-8?q?=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ALL_Det/include/ALL_Detect.hpp | 10 +- ALL_Det/src/ALL_Detect.cpp | 58 +++----- CheckBase/include/AI_Moudel.hpp | 1 + CheckBase/include/CheckBaseParam.hpp | 10 ++ CheckBase/src/CheckBaseParam.cpp | 18 ++- Common/include/CheckUtil.hpp | 1 + Common/src/CheckUtil.cpp | 8 ++ Down_Angle_Det/src/Down_Angle_Detect.cpp | 135 +++++++------------ Down_Det/include/Down_Detect.hpp | 2 + Down_Det/src/Down_Detect.cpp | 84 +++++++++--- TOP_Det/include/Top_Detect.hpp | 1 - TOP_Det/src/Top_Detect.cpp | 162 ++++++++++++++++++++--- 12 files changed, 312 insertions(+), 178 deletions(-) diff --git a/ALL_Det/include/ALL_Detect.hpp b/ALL_Det/include/ALL_Detect.hpp index d59b63c..b2e5755 100644 --- a/ALL_Det/include/ALL_Detect.hpp +++ b/ALL_Det/include/ALL_Detect.hpp @@ -24,17 +24,11 @@ public: // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 int UpdateConfig(void *pconfig, int nConfigType); -public: private: - Top_Detect top_1_detect; - Top_Detect top_2_detect; - Side_Detect side_1_detect; - Side_Detect side_2_detect; - Down_Detect down_detect; - Down_Angle_Detect down_angle_detect; + std::shared_ptr m_checkBase = nullptr; + std::shared_ptr m_down_angle_detect = nullptr; Cam_Param m_cam_param; -private: }; #endif \ No newline at end of file diff --git a/ALL_Det/src/ALL_Detect.cpp b/ALL_Det/src/ALL_Detect.cpp index 60fd09f..649e6ef 100644 --- a/ALL_Det/src/ALL_Detect.cpp +++ b/ALL_Det/src/ALL_Detect.cpp @@ -25,44 +25,51 @@ int ALL_Detect::RunStart(void *pconfig1) // 初始化 m_cam_param.copy(*(Cam_Param *)pconfig1); RunInfoST runconfig; + runconfig.flag0 = m_cam_param.cam_position; switch (m_cam_param.cam_position) { case CAMERA_TOP_1: + if (!m_checkBase) + m_checkBase = std::make_shared(); runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Top.json"; runconfig.str_RunJson = m_cam_param.check_param_path + "param_Top-1.json"; - this->top_1_detect.RunStart((void *)&runconfig); break; case CAMERA_TOP_2: + if (!m_checkBase) + m_checkBase = std::make_shared(); runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Top.json"; runconfig.str_RunJson = m_cam_param.check_param_path + "param_Top-2.json"; - this->top_2_detect.RunStart((void *)&runconfig); break; case CAMERA_SIDE_1: + if (!m_checkBase) + m_checkBase = std::make_shared(); runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Side.json"; runconfig.str_RunJson = m_cam_param.check_param_path + "param_Side-1.json"; - this->side_1_detect.RunStart((void *)&runconfig); break; case CAMERA_SIDE_2: + if (!m_checkBase) + m_checkBase = std::make_shared(); runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Side.json"; runconfig.str_RunJson = m_cam_param.check_param_path + "param_Side-2.json"; - this->side_2_detect.RunStart((void *)&runconfig); break; case CAMERA_DOWN_1: + if (!m_checkBase) + m_checkBase = std::make_shared(); + if (!m_down_angle_detect) + m_down_angle_detect = std::make_shared(); runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Down.json"; runconfig.str_RunJson = m_cam_param.check_param_path + "param_Down.json"; - this->down_detect.RunStart((void *)&runconfig); - this->down_angle_detect.RunStart((void *)&runconfig); + this->m_down_angle_detect->RunStart((void *)&runconfig); break; default: break; } + this->m_checkBase->RunStart((void *)&runconfig); return 0; } int ALL_Detect::CheckImg(std::shared_ptr p, std::shared_ptr &pResult) { - // DetImgInfo_shareP = p; - // printf("%d DetImgInfo_shareP count %ld \n", m_RunConfig.nThreadIdx, DetImgInfo_shareP.use_count()); if (m_cam_param.cam_position != p->cam_position) { std::cout << "ERROR: ALL_Detect cam_position not match, expect: " << m_cam_param.cam_position @@ -72,41 +79,18 @@ int ALL_Detect::CheckImg(std::shared_ptr p, std::shared_ptrdetect_type == DETECT_TYPE_ANGLE) { - if (p->cam_position != CAMERA_DOWN_1) { + if (p->cam_position != CAMERA_DOWN_1) + { std::cout << "ERROR: Down_Angle_Detect only support CAMERA_DOWN_1" << std::endl; return -2; } - this->down_angle_detect.CheckImg(p, pResult); - } - else - { - switch (p->cam_position) - { - case CAMERA_TOP_1: - this->top_1_detect.CheckImg(p, pResult); - break; - case CAMERA_TOP_2: - this->top_2_detect.CheckImg(p, pResult); - break; - case CAMERA_SIDE_1: - this->side_1_detect.CheckImg(p, pResult); - break; - case CAMERA_SIDE_2: - this->side_2_detect.CheckImg(p, pResult); - break; - case CAMERA_DOWN_1: - this->down_detect.CheckImg(p, pResult); - break; - default: - break; - } + return this->m_down_angle_detect->CheckImg(p, pResult); + } else { + return this->m_checkBase->CheckImg(p, pResult); } - - return 0; } int ALL_Detect::UpdateConfig(void *pconfig, int nConfigType) { - - return 0; + return this->m_checkBase->UpdateConfig(pconfig, nConfigType); } diff --git a/CheckBase/include/AI_Moudel.hpp b/CheckBase/include/AI_Moudel.hpp index 0c3056a..0616621 100644 --- a/CheckBase/include/AI_Moudel.hpp +++ b/CheckBase/include/AI_Moudel.hpp @@ -15,6 +15,7 @@ enum AI_Model_Type_ AI_Model_Type_Seg, AI_Model_Type_Reconstruct, AI_Model_Type_EdgeAngle, + AI_Model_Type_CodeAlign, AI_Model_Type_Count, }; enum AI_MODEL_TYPE_ diff --git a/CheckBase/include/CheckBaseParam.hpp b/CheckBase/include/CheckBaseParam.hpp index a129cbe..ac48f06 100644 --- a/CheckBase/include/CheckBaseParam.hpp +++ b/CheckBase/include/CheckBaseParam.hpp @@ -130,6 +130,8 @@ struct Base_Function_DetConfig int chip_height_mm; // 芯片高度 mm 1107-add int chip_width_offset_mm; // 芯片宽度偏差 mm int chip_height_offset_mm; // 芯片高度偏差 mm 1107-add + double calibration_coeff_x; // 标定系数x mm/pixel + double calibration_coeff_y; // 标定系数y mm/pixel Base_Function_DetConfig() { Init(); @@ -144,6 +146,10 @@ struct Base_Function_DetConfig pointArry.shrink_to_fit(); // 1107-add chip_width_mm = 0; // 1107-add chip_height_mm = 0; // 1107-add + chip_width_offset_mm = 0; + chip_height_offset_mm = 0; + calibration_coeff_x = 1.0; // 1107-add + calibration_coeff_y = 1.0; // 1107-add } void copy(Base_Function_DetConfig tem) @@ -155,6 +161,10 @@ struct Base_Function_DetConfig this->LabelPolygonBoundingRect = tem.LabelPolygonBoundingRect; // 1107-add this->chip_width_mm = tem.chip_width_mm; // 1107-add this->chip_height_mm = tem.chip_height_mm; // 1107 + this->chip_width_offset_mm = tem.chip_width_offset_mm; + 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 } void print(std::string str) { diff --git a/CheckBase/src/CheckBaseParam.cpp b/CheckBase/src/CheckBaseParam.cpp index 64c4261..a40ea02 100644 --- a/CheckBase/src/CheckBaseParam.cpp +++ b/CheckBase/src/CheckBaseParam.cpp @@ -452,9 +452,9 @@ int CheckBaseParamJson::GetFunction(Json::Value value) } // 芯片尺寸 - pdetConfig->chip_width_mm = value_f["form"]["Chip_Size"]["ChipWidth"].asInt(); // 1020-add - pdetConfig->chip_height_mm = value_f["form"]["Chip_Size"]["ChipHeight"].asInt(); // 1020-add - pdetConfig->chip_width_offset_mm = value_f["form"]["Chip_Size"]["ChipWOffset"].asInt(); // 1020-add + pdetConfig->chip_width_mm = value_f["form"]["Chip_Size"]["ChipWidth"].asInt(); // 1020-add + pdetConfig->chip_height_mm = value_f["form"]["Chip_Size"]["ChipHeight"].asInt(); // 1020-add + pdetConfig->chip_width_offset_mm = value_f["form"]["Chip_Size"]["ChipWOffset"].asInt(); // 1020-add pdetConfig->chip_height_offset_mm = value_f["form"]["Chip_Size"]["ChipHOffset"].asInt(); // 1020-add // 旋转角度 @@ -541,6 +541,18 @@ int CheckBaseParamJson::GetFunction(Json::Value value) } pdetConfig->LabelPolygonBoundingRect = cv::boundingRect(pdetConfig->pointArry); // 获取芯片区域的标记多边形最大外接矩形 } + + // 标定系数 + pdetConfig->calibration_coeff_x = value_f["form"]["Camera_Cali"]["x_coefficient"].asDouble(); // 1107-add + pdetConfig->calibration_coeff_y = value_f["form"]["Camera_Cali"]["y_coefficient"].asDouble(); // 1107-add + if (pdetConfig->calibration_coeff_x < 0) + { + pdetConfig->calibration_coeff_x = 0; + } + if (pdetConfig->calibration_coeff_y < 0) + { + pdetConfig->calibration_coeff_y = 0; + } } // else // { diff --git a/Common/include/CheckUtil.hpp b/Common/include/CheckUtil.hpp index ad17e13..b7e165d 100644 --- a/Common/include/CheckUtil.hpp +++ b/Common/include/CheckUtil.hpp @@ -47,6 +47,7 @@ public: static cv::RotatedRect UpdataRotatedRect(cv::RotatedRect oldRrect, int start_x, int start_y, float fscale_x, float fscale_y); static int adjustRectToBounds(cv::Rect &rect, const cv::Size &imgSize); static double point2fDistance(const cv::Point2f &p1, const cv::Point2f &p2); // 1107-add + static cv::Point getCenterPoint(cv::Rect rect);//0922-add }; template static std::string str_Format(const std::string &format, Args... args) diff --git a/Common/src/CheckUtil.cpp b/Common/src/CheckUtil.cpp index 2bfeaf1..3b0566a 100644 --- a/Common/src/CheckUtil.cpp +++ b/Common/src/CheckUtil.cpp @@ -515,3 +515,11 @@ double CheckUtil::point2fDistance(const cv::Point2f &p1, const cv::Point2f &p2) 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); + return cpt; +} diff --git a/Down_Angle_Det/src/Down_Angle_Detect.cpp b/Down_Angle_Det/src/Down_Angle_Detect.cpp index 6321bd2..408275c 100644 --- a/Down_Angle_Det/src/Down_Angle_Detect.cpp +++ b/Down_Angle_Det/src/Down_Angle_Detect.cpp @@ -22,6 +22,7 @@ Down_Angle_Detect::Down_Angle_Detect() } Down_Angle_Detect::~Down_Angle_Detect() { + printf("----------------~Down_Angle_Detect \n"); } int Down_Angle_Detect::RunStart(void *pconfig1) @@ -316,6 +317,11 @@ int Down_Angle_Detect::CheckRun() Base_Function_DetConfig *pdetConfig = &m_CheckBaseConfig->baseCheckFunction.detconfig; bool openFlag = pdetConfig->bOpen; + if (DetImgInfo_shareP->bdebugSaveImg) + { + bwriteImg = true; + } + // cv::Rect detROI = pdetConfig->cropROI;//检测ROI // 获取产品ROI区域 auto t110 = CheckUtil::getcurTime(); @@ -407,80 +413,21 @@ int Down_Angle_Detect::CheckRun() // getchar(); } - // if ((LeftDownP.x < 0) || (LeftDownP.x > inputROIimg.cols - 1)) - // { - // re = 1; - // } - // if ((LeftDownP.y < 0) || (LeftDownP.y > inputROIimg.rows - 1)) - // { - // re = 2; // 1104-add - // } - cv::Point2f detROi2f{detROI.x, detROI.y}; cv::Point2f BigImgChipCenter = CenterP + detROi2f; // 1105 cv::Point2f CenterOffsetP = BigImgChipCenter - LabelCenterP; - std::cout << "OffsetXOut=" << CenterOffsetP.x << std::endl; - std::cout << "OffsetYOut=" << CenterOffsetP.y << std::endl; - - // float offsetAngle=abs(angleOut-InputBaseAngle);//这里选择从界面读取的angle-可能不准 float offsetAngle = angleOut - LabelAngle; // //角度偏差 - std::cout << "Offsetangle=" << offsetAngle << std::endl; // 1027-add - - m_CheckResult_shareP->CenterOffsetX = CenterOffsetP.x; // 最终结果输出 - m_CheckResult_shareP->CenterOffsetY = CenterOffsetP.y; // 最终结果输出 - m_CheckResult_shareP->OffsetAngle = offsetAngle; // 最终结果输出 -此时取绝对值,到下面来纠正正负1105 - if (0 != re) - { - // 1013-添加画ERROR-- - if (bwriteImg) - { - std::string str = "1after_DetImgInfo_shareP-img.png"; - cv::imwrite(str, DetImgInfo_shareP->img); - } - // GetShowSrcImg(detimg, m_CheckResult_shareP->resultImg); //这样结果图在打开存图开关时会有红色矩形框 - GetShowSrcImg(DetImgInfo_shareP->img, m_CheckResult_shareP->resultImg); // 这样也有 - // 这里可以根据返回的int数字来决定返回的是"ERROR"还是"Param_ERROR"还是"Image_mohu"---- - AddResultErrorImg(m_CheckResult_shareP->resultImg); // 画ERROR -1013-add 拿到外面来 - // AddResultErrorImg(m_CheckResult_shareP->resultImg,"ERROR"); //1014-add - if (bwriteImg) - { - std::string str = "2after_DetImgInfo_shareP-img2.png"; - cv::imwrite(str, DetImgInfo_shareP->img); - } - std::cout << "AddResultError-----------------Img------ERROR" << std::endl; // 1013-add - return re; - } - - // cv::Point s2offsetPoint = LeftDownP - s2_LabelLineP1; - // cv::Point s2LabelOffsetRightDownP = s2_LabelLineP2 + s2offsetPoint; // 标记的点-相对右边偏移后的点 - - // // 此时标记的底边线段1和求得的底边线段2在左下角重合形成角度,可以根据两线段右端点纵坐标Y的值来判断角度正负-1105 - // // 如果s2RightDownP_out.yOffsetAngle = -offsetAngle; // 负角度 顺时针 - // std::cout << "up--------------------------------up" << std::endl; - // //std::cout << "m_CheckResult_shareP->Angle=" << m_CheckResult_shareP->Angle << std::endl; - // } - // else if (RightDownP.y > s2LabelOffsetRightDownP.y) - // { - // // m_CheckResult_shareP->Angle = offsetAngle - 90; - // m_CheckResult_shareP->OffsetAngle = offsetAngle; // 正角度 逆时针 - // std::cout << "down--------------------------------down" << std::endl; - // //std::cout << "m_CheckResult_shareP->Angle=" << m_CheckResult_shareP->Angle << std::endl; - // } - - bool drawLabelLineFlag = false; - re = Draw3(m_resultImg, m_CheckResult_shareP->resultImg, s2StartP, CenterP, - LabelCenterP, s2_LabelLineP1, s2_LabelLineP2, LeftDownP, RightDownP, drawLabelLineFlag); + double x_coeff = pdetConfig->calibration_coeff_x; // 1107-add + double y_coeff = pdetConfig->calibration_coeff_y; // 1107-add + m_CheckResult_shareP->CenterOffsetX = CenterOffsetP.x * x_coeff; // 最终结果输出 + m_CheckResult_shareP->CenterOffsetY = CenterOffsetP.y * y_coeff; // 最终结果输出 + m_CheckResult_shareP->OffsetAngle = offsetAngle; + + std::cout << "OffsetXOut=" << CenterOffsetP.x << " resultMove" << m_CheckResult_shareP->CenterOffsetX << std::endl; + std::cout << "OffsetYOut=" << CenterOffsetP.y << " resultMove" << m_CheckResult_shareP->CenterOffsetY << std::endl; + std::cout << "Offsetangle=" << offsetAngle << std::endl; - if (0 != re) - { - // 这里其实没有返回由于画图错误导致的图像异常-返回的是ChipRoiImg -1014-add - return re; - } t2 = CheckUtil::getcurTime(); m_CheckResult_shareP->UseTimeMS = t2 - t1; // printf("Check time %ld \n", t2 - t1); @@ -767,7 +714,7 @@ int Down_Angle_Detect::AI_Run(const cv::Mat &img, cv::Point s2StartP, double Lab { continue; } - //二次定位 + // 二次定位 const int h = 360; cv::Point start{MaxRoi.x, MaxRoi.y + MaxRoi.height - h / 2}; cv::Rect SecondAlignRoi{start.x, start.y, MaxRoi.width, h}; @@ -827,7 +774,7 @@ int Down_Angle_Detect::AI_Run(const cv::Mat &img, cv::Point s2StartP, double Lab cv::imwrite(str1, src_mask); } - //取中间300宽度搜边 + // 取中间300宽度搜边 const int w = 300; cv::Rect roiRect{(outimg.cols - 300) / 2, 0, w, outimg.rows}; cv::Mat Roi_mask = outimg(roiRect); @@ -1067,65 +1014,73 @@ int Down_Angle_Detect::Draw3(const cv::Mat &img, cv::Mat &resultimg, cv::Point s } // 计算二值图像中分割线的角度 -double Down_Angle_Detect::calculateSplitLineAngle(const cv::Mat& binaryImage) { +double Down_Angle_Detect::calculateSplitLineAngle(const cv::Mat &binaryImage) +{ // 检查图像是否有效 - if (binaryImage.empty()) { + if (binaryImage.empty()) + { cerr << "img is empty!" << endl; return 0.0; } - + // 获取图像尺寸 int height = binaryImage.rows; int width = binaryImage.cols; - + // 存储边界点 vector boundaryPoints; - + // 遍历每一列,找到白黑边界 - for (int x = 0; x < width; x++) { - for (int y = 0; y < height - 1; y++) { + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height - 1; y++) + { // 检查当前像素是白色(255)且下一个像素是黑色(0) - if (binaryImage.at(y, x) == 255 && - binaryImage.at(y + 1, x) == 0) { + if (binaryImage.at(y, x) == 255 && + binaryImage.at(y + 1, x) == 0) + { boundaryPoints.push_back(Point(x, y)); break; // 找到该列的边界点后跳出内层循环 } } } - + // 检查是否找到足够的边界点 - if (boundaryPoints.size() < 2) { + if (boundaryPoints.size() < 2) + { cerr << "edge point not Enough" << endl; return 0.0; } - + // 使用最小二乘法拟合直线 y = mx + b double sumX = 0.0, sumY = 0.0, sumXY = 0.0, sumX2 = 0.0; int n = boundaryPoints.size(); - - for (const auto& point : boundaryPoints) { + + for (const auto &point : boundaryPoints) + { double x = point.x; double y = point.y; - + sumX += x; sumY += y; sumXY += x * y; sumX2 += x * x; } - + // 计算斜率 m 和截距 b double denominator = n * sumX2 - sumX * sumX; - if (fabs(denominator) < 1e-10) { + if (fabs(denominator) < 1e-10) + { // 垂直线情况 return 90.0; } - + double m = (n * sumXY - sumX * sumY) / denominator; double b = (sumY - m * sumX) / n; - + // 计算角度(弧度转角度) double angleRad = atan(m); double angleDeg = angleRad * 180.0 / CV_PI; - + return angleDeg; } \ No newline at end of file diff --git a/Down_Det/include/Down_Detect.hpp b/Down_Det/include/Down_Detect.hpp index e2a9ad9..e364260 100644 --- a/Down_Det/include/Down_Detect.hpp +++ b/Down_Det/include/Down_Detect.hpp @@ -39,6 +39,8 @@ private: int DetectImg(const cv::Mat &img); + std::tuple templateMatchBasic(const cv::Mat& src, const cv::Mat& templ, int method = cv::TM_CCOEFF_NORMED); + private: int m_nErrorCode; // 错误代码 std::shared_ptr DetImgInfo_shareP; diff --git a/Down_Det/src/Down_Detect.cpp b/Down_Det/src/Down_Detect.cpp index b50ecef..2184251 100644 --- a/Down_Det/src/Down_Detect.cpp +++ b/Down_Det/src/Down_Detect.cpp @@ -505,23 +505,41 @@ int Down_Detect::ImgAlinRotate(const cv::Mat &img, cv::Mat &alignImg) return 1; } - DetRotateType ratio = m_CheckBaseConfig->baseCheckFunction.detconfig.rotate; - std::cout << "rotate ratio : " << ratio << std::endl; - if (ratio == Ratio_0) - { - } - else if (ratio == Ratio_90) - { - cv::rotate(alignImg, alignImg, cv::ROTATE_90_COUNTERCLOCKWISE); - } - else if (ratio == Ratio_180) - { - cv::rotate(alignImg, alignImg, cv::ROTATE_180); - } - else if (ratio == Ratio_270) - { - cv::rotate(alignImg, alignImg, cv::ROTATE_90_CLOCKWISE); // 270° 逆时针 == 90° 顺时针 - } + // DetRotateType ratio = m_CheckBaseConfig->baseCheckFunction.detconfig.rotate; + // std::cout << "rotate ratio : " << ratio << std::endl; + // if (ratio == Ratio_0) + // { + // } + // else if (ratio == Ratio_90) + // { + // cv::rotate(alignImg, alignImg, cv::ROTATE_90_COUNTERCLOCKWISE); + // } + // else if (ratio == Ratio_180) + // { + // cv::rotate(alignImg, alignImg, cv::ROTATE_180); + // } + // else if (ratio == Ratio_270) + // { + // cv::rotate(alignImg, alignImg, cv::ROTATE_90_CLOCKWISE); // 270° 逆时针 == 90° 顺时针 + // } + + // // 模板匹配定位 + // cv::Mat alignImg_copy = alignImg.clone(); + // cv::resize(alignImg_copy, alignImg_copy, cv::Size(800, 600)); + // cv::imwrite("alignImg_copy.png", alignImg_copy); + // cv::Mat templ1 = cv::imread("/home/aidlux/zhangzhi/ZYWL/AJX-ZYWL/data/Down_Det/dt1.png", cv::IMREAD_COLOR);//正 + // cv::Mat templ2 = cv::imread("/home/aidlux/zhangzhi/ZYWL/AJX-ZYWL/data/Down_Det/dt2.png", cv::IMREAD_COLOR);//倒 + // auto [maxVal1, matchPoint1] = templateMatchBasic(alignImg_copy, templ1, cv::TM_CCOEFF_NORMED); + // auto [maxVal2, matchPoint2] = templateMatchBasic(alignImg_copy, templ2, cv::TM_CCOEFF_NORMED); + // // cv::rectangle(alignImg_copy, matchPoint1, + // // cv::Point(matchPoint1.x + templ1.cols, matchPoint1.y + templ1.rows), + // // cv::Scalar(0, 255, 0), 2); // 绿色矩形 + // // cv::imwrite("alignImg_temMatch.png", alignImg_copy); + // if (maxVal2 > maxVal1) + // { + // // 需要旋转 + // cv::rotate(alignImg, alignImg, cv::ROTATE_180); + // } return 0; } @@ -739,3 +757,35 @@ int Down_Detect::DetectImg(const cv::Mat &img) // getchar(); return 0; } + +std::tuple Down_Detect::templateMatchBasic(const Mat &src, const Mat &templ, int method) +{ + Mat result; + + // 检查图像和模板大小 + if (src.cols < templ.cols || src.rows < templ.rows) + { + cerr << "template size > src size" << endl; + return std::make_tuple(0, cv::Point(-1, -1)); + } + + // 执行模板匹配 + matchTemplate(src, templ, result, method); + + // 寻找最佳匹配位置 + double minVal, maxVal; + Point minLoc, maxLoc; + minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc); + + // 根据匹配方法返回最佳位置 + Point bestMatch; + if (method == TM_SQDIFF || method == TM_SQDIFF_NORMED) + { + bestMatch = minLoc; + } + else + { + bestMatch = maxLoc; + } + return std::make_tuple(maxVal, bestMatch); +} \ No newline at end of file diff --git a/TOP_Det/include/Top_Detect.hpp b/TOP_Det/include/Top_Detect.hpp index fbe82ab..5f709fa 100644 --- a/TOP_Det/include/Top_Detect.hpp +++ b/TOP_Det/include/Top_Detect.hpp @@ -20,7 +20,6 @@ public: // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 int UpdateConfig(void *pconfig, int nConfigType); -public: private: // 检测 int CheckRun(); diff --git a/TOP_Det/src/Top_Detect.cpp b/TOP_Det/src/Top_Detect.cpp index 2e1a0d6..31a4bef 100644 --- a/TOP_Det/src/Top_Detect.cpp +++ b/TOP_Det/src/Top_Detect.cpp @@ -492,34 +492,151 @@ int Top_Detect::ImgAlinRotate(const cv::Mat &img, cv::Mat &alignImg) } // 判断尺寸 - int w = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_width_mm / m_CheckBaseConfig->imageScaleParam.fScale_X; - int h = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_height_mm / m_CheckBaseConfig->imageScaleParam.fScale_Y; - auto w_offset = std::abs(w - m_AlignMaxRoi.width); - auto h_offset = std::abs(h - m_AlignMaxRoi.height); - int param_w_offset = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_width_offset_mm / m_CheckBaseConfig->imageScaleParam.fScale_X; - int param_h_offset = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_height_offset_mm / m_CheckBaseConfig->imageScaleParam.fScale_Y; - if (w_offset > param_w_offset || h_offset > param_h_offset) - { - printf("Align error, no product\n"); - return 1; - } - - DetRotateType ratio = m_CheckBaseConfig->baseCheckFunction.detconfig.rotate; - std::cout << "rotate ratio : " << ratio << std::endl; - if (ratio == Ratio_0) - { + int w = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_width_mm / m_CheckBaseConfig->imageScaleParam.fScale_X; + int h = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_height_mm / m_CheckBaseConfig->imageScaleParam.fScale_Y; + auto w_offset = std::abs(w - m_AlignMaxRoi.width); + auto h_offset = std::abs(h - m_AlignMaxRoi.height); + int param_w_offset = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_width_offset_mm / m_CheckBaseConfig->imageScaleParam.fScale_X; + int param_h_offset = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_height_offset_mm / m_CheckBaseConfig->imageScaleParam.fScale_Y; + if (w_offset > param_w_offset || h_offset > param_h_offset) + { + printf("Align error, no product\n"); + return 1; } - else if (ratio == Ratio_90) + + // DetRotateType ratio = m_CheckBaseConfig->baseCheckFunction.detconfig.rotate; + // std::cout << "rotate ratio : " << ratio << std::endl; + // if (ratio == Ratio_0) + // { + // } + // else if (ratio == Ratio_90) + // { + // cv::rotate(alignImg, alignImg, cv::ROTATE_90_COUNTERCLOCKWISE); + // } + // else if (ratio == Ratio_180) + // { + // cv::rotate(alignImg, alignImg, cv::ROTATE_180); + // } + // else if (ratio == Ratio_270) + // { + // cv::rotate(alignImg, alignImg, cv::ROTATE_90_CLOCKWISE); // 270° 逆时针 == 90° 顺时针 + // } + + // 二维码定位处理 + long t12, t13; + t12 = CheckUtil::getcurTime(); + cv::Mat ColorCodeImg; + if (alignImg.channels() == 1) { - cv::rotate(alignImg, alignImg, cv::ROTATE_90_COUNTERCLOCKWISE); + cv::cvtColor(alignImg, ColorCodeImg, cv::COLOR_GRAY2BGR); } - else if (ratio == Ratio_180) + else { - cv::rotate(alignImg, alignImg, cv::ROTATE_180); + ColorCodeImg = alignImg; } - else if (ratio == Ratio_270) + + for (int i = 0; i < m_AIModelConfigList->AIModelConfigList.size(); i++) { - cv::rotate(alignImg, alignImg, cv::ROTATE_90_CLOCKWISE); // 270° 逆时针 == 90° 顺时针 + AI_Model_Param *p = &m_AIModelConfigList->AIModelConfigList.at(i); + + std::cout << "p->name=" << p->strAIModelName << std::endl; // 0924-add + std::cout << "p->strModelPath=" << p->strModelPath << std::endl; // 0924-add + std::cout << "p->type=" << p->type << std::endl; // 1015-add + // getchar();//0924-add + + // 定位类型 + if (p->type != AI_Model_Type_CodeAlign) + { + 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 temimg2; + cv::resize(ColorCodeImg, temimg2, sz); + AlignToSrc.setResize(ColorCodeImg, temimg2); + if (bwriteImg) + { + std::string str = p->strAIModelName + "_AI_in.png"; + cv::imwrite(str, temimg2); + } + + cv::Mat outimg; + if ((p->pdetect->run(temimg2, outimg, false)) == 0) // 加载加密后的.bin.aidem文件 + { + std::cout << "CodeAlign----p->pdetect->run--success---" << std::endl; + } + else + { + std::cout << "CodeAlign----p->pdetect->run--failed--- return 5" << std::endl; + return 5; // 返回5 + } + t2 = CheckUtil::getcurTime(); + std::cout << "1.2 codeLoc model-run-----time cost -----------" << t2 - t1 << "ms" << std::endl; + + if (bwriteImg) + { + std::string str = p->strAIModelName + "_AI_out.png"; + cv::imwrite(str, outimg); + } + + cv::Mat src_mask; + cv::resize(outimg, src_mask, cv::Size(ColorCodeImg.cols, ColorCodeImg.rows)); + if (bwriteImg) + { + std::string str = p->strAIModelName + "_AI_mask.png"; + cv::imwrite(str, src_mask); + } + // 求取二维码位置 + cv::Rect codeLocRoi = CheckUtil::findMaxBoundingBox(outimg); // 直接在输入模型图像上找-更节省时间 + if (codeLocRoi.empty()) + { + std::cout << "CodeAlign---no--Product" << std::endl; + return 6; // 返回6 + } + + if (bwriteImg) + { + cv::Mat codeLocShowImg; + if (1 == outimg.channels()) + { + cvtColor(outimg, codeLocShowImg, cv::COLOR_GRAY2BGR); + } + else if (3 == outimg.channels()) + { + codeLocShowImg = outimg.clone(); + } + cv::rectangle(codeLocShowImg, codeLocRoi, cv::Scalar(0, 0, 255), 2, 8); + std::string str = p->strAIModelName + "_CodeLocShow.png"; + cv::imwrite(str, codeLocShowImg); + } + cv::Point codeCenterPt = CheckUtil::getCenterPoint(codeLocRoi); // CheckUtil::getCenterPoint + + if (m_pRunConfig.flag0 == CAMERA_TOP_1) + { + if (codeCenterPt.x < outimg.cols / 2) + { + // 二维码在左侧则旋转90°逆时针 + cv::rotate(alignImg, alignImg, cv::ROTATE_90_COUNTERCLOCKWISE); + } + else if(codeCenterPt.x > outimg.cols / 2) + { + // 二维码在右侧则旋转90°顺时针 + cv::rotate(alignImg, alignImg, cv::ROTATE_90_CLOCKWISE); + } + } + else if (m_pRunConfig.flag0 == CAMERA_TOP_2) + { + // 二维码在上方则旋转180° + if (codeCenterPt.y < outimg.rows / 2) + { + cv::rotate(alignImg, alignImg, cv::ROTATE_180); + } + } } return 0; @@ -739,3 +856,4 @@ int Top_Detect::DetectImg(const cv::Mat &img) // getchar(); return 0; } +