#include "AI_Edge_Algin.h" #include "CheckErrorCodeDefine.hpp" #include "AI_Second_Det.h" AI_SecondDet::AI_SecondDet() { m_bModelSucc_AD = false; m_bModelSucc_POL = false; CheckUtil::CreateDir("/home/aidlux/BOE/FOG/Second/POL/"); CheckUtil::CreateDir("/home/aidlux/BOE/FOG/Second/AD/"); m_pImageStorage = ImageStorage::getInstance(); m_Show_Area = 0; m_Show_Len = 0; m_Len_P1 = cv::Point(0, 0); m_Len_P2 = cv::Point(0, 0); AI_Factory = AIFactory::GetInstance(); } AI_SecondDet::~AI_SecondDet() { } int AI_SecondDet::Detect(const cv::Mat &img, const cv::Mat &mask, DetConfigResult *pDetConfig) { m_pdetlog = pDetConfig->pdetlog; // 二次求面积长度 功能关闭 if (!pDetConfig->pfunction_secondDet->bOpen) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "function colse"); return 1; } // cv::Mat temimg = mask.clone(); // cv::rectangle(temimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); cv::Rect AIroi = GetCutRoi(pDetConfig->qx_roi, img); if (AIroi.width <= 0 || AIroi.height <= 0) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error Size"); return 1; } if (!CheckUtil::RoiInImg(AIroi, img)) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error ROI"); return 1; } float min_set_param_area = 0; float max_set_param_area = 9999; if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) { min_set_param_area = pDetConfig->pfunction_secondDet->pol_area_min; max_set_param_area = pDetConfig->pfunction_secondDet->pol_area_max; } if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) { min_set_param_area = pDetConfig->pfunction_secondDet->andian_area_min; max_set_param_area = pDetConfig->pfunction_secondDet->andian_area_max; } float oldarea_mm2 = pDetConfig->old_Area * pDetConfig->fImgage_Scale_X * pDetConfig->fImgage_Scale_Y; if (oldarea_mm2 < min_set_param_area || oldarea_mm2 > max_set_param_area) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "error Area %0.2f out[%0.2f %0.2f] ", oldarea_mm2, min_set_param_area, max_set_param_area); return 1; } if (oldarea_mm2 < pDetConfig->min_DetArea) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error Area %0.2f < det param %0.2f ", oldarea_mm2, pDetConfig->min_DetArea); return 1; } { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "succ Area %0.2f >= min det param %0.2f and in [%0.2f %0.2f] ", oldarea_mm2, pDetConfig->min_DetArea, min_set_param_area, max_set_param_area); } cv::Mat detimg = img(AIroi).clone(); cv::Mat outimg; int re12 = 0; // if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) { if (pDetConfig->pfunction_secondDet->pol_saveProcessImg) { // printf("mask %d %d \n", mask.cols, mask.rows); // printf("AIroi %d %d %d %d\n", AIroi.x, AIroi.y, AIroi.width, AIroi.height); detimg123 = mask(AIroi).clone(); // printf("1111mask %d %d \n", mask.cols, mask.rows); } re12 = Det_Pol(detimg, pDetConfig); } if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) { if (pDetConfig->pfunction_secondDet->andian_saveProcessImg) { // printf("mask %d %d \n", mask.cols, mask.rows); // printf("AIroi %d %d %d %d\n", AIroi.x, AIroi.y, AIroi.width, AIroi.height); detimg123 = mask(AIroi).clone(); // printf("2222mask %d %d \n", mask.cols, mask.rows); } re12 = Det_AD(detimg, pDetConfig); } if (re12 != 0) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE_POL /AD", "Error "); return 1; } return 0; } cv::Rect AI_SecondDet::GetCutRoi(cv::Rect &roi, const cv::Mat &img) { std::shared_ptr pAI_Model = AI_Factory->AI_defect_RE_POL; cv::Size sz; sz.width = pAI_Model->input_0.width; sz.height = pAI_Model->input_0.height; int Dst_Width = sz.width; int Dst_Height = sz.height; cv::Rect cutroi = cv::Rect(0, 0, 0, 0); if (Dst_Width >= img.cols || Dst_Height >= img.rows) { return cutroi; } if (roi.width >= Dst_Width || roi.height >= Dst_Height) { return cutroi; } int centerX = roi.x + roi.width / 2; int centerY = roi.y + roi.height / 2; // 构造一个以中心为中心的 128x128 矩形 int halfSize = Dst_Width / 2; // 128 / 2 int newX = centerX - halfSize; int newY = centerY - halfSize; int newWidth = Dst_Width; int newHeight = Dst_Height; // 检查矩形是否越界 if (newX < 0) { newX = 0; } if (newY < 0) { newY = 0; } if (newX + newWidth > img.cols) { newX = img.cols - newWidth; } if (newY + newHeight > img.rows) { newY = img.rows - newHeight; } // 创建新的矩形 cv::Rect newRect(newX, newY, newWidth, newHeight); int add = 3; // 重新计算 roi 在新的矩形中的位置 int newRoiX = roi.x - newRect.x - add; int newRoiY = roi.y - newRect.y - add; int newRoiWidth = roi.width + 2 * add; int newRoiHeight = roi.height + 2 * add; // 确保新的 roi 在新的矩形内 if (newRoiX < 0) { newRoiX = 0; } if (newRoiY < 0) { newRoiY = 0; } if (newRoiX + newRoiWidth > newRect.width) { newRoiWidth = newRect.width - newRoiX; } if (newRoiY + newRoiHeight > newRect.height) { newRoiHeight = newRect.height - newRoiY; } // 更新 roi roi = cv::Rect(newRoiX, newRoiY, newRoiWidth, newRoiHeight); // 返回新的矩形 return newRect; } int AI_SecondDet::Det_Pol(const cv::Mat &img, DetConfigResult *pDetConfig) { std::shared_ptr pAI_Model = AI_Factory->AI_defect_RE_POL; int re = 0; cv::Mat outimg; m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " POL start"); re = pAI_Model->AIDet(img, outimg); if (re != 0) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error POL AI Model Error"); return 1; } if (outimg.empty()) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error POL AI Error"); return 1; } cv::Mat AnalysisyImg = outimg(pDetConfig->qx_roi).clone(); m_Show_Area = pDetConfig->old_Area; m_Show_Len = pDetConfig->old_len; // 开始分析mask; re = Analysisy(AnalysisyImg, pDetConfig); m_Len_P1.x += pDetConfig->qx_roi.x; m_Len_P1.y += pDetConfig->qx_roi.y; m_Len_P2.x += pDetConfig->qx_roi.x; m_Len_P2.y += pDetConfig->qx_roi.y; // 存储中间过程图片 if (pDetConfig->pfunction_secondDet->pol_saveProcessImg) { if (true) { cv::rectangle(outimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); cv::rectangle(detimg123, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); cv::line(outimg, m_Len_P1, m_Len_P2, cv::Scalar(128, 0, 0)); { char buffer[128]; sprintf(buffer, " oA %d -> nA %d ", pDetConfig->old_Area, m_Show_Area); std::string st1 = buffer; cv::Point p(0, 10); cv::putText(outimg, st1, p, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); sprintf(buffer, " oL %0.2f -> nL %0.2f ", pDetConfig->old_len, m_Show_Len); st1 = buffer; cv::Point p2(0, 20); cv::putText(outimg, st1, p2, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); } } SaveProcessImg(img, outimg, detimg123, pDetConfig); } return re; } int AI_SecondDet::Det_AD(const cv::Mat &img, DetConfigResult *pDetConfig) { std::shared_ptr pAI_Model = AI_Factory->AI_defect_RE_AD; int re = 0; cv::Mat outimg; m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " AD start"); re = pAI_Model->AIDet(img, outimg); if (re != 0) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error AD AI Model Error"); return 1; } if (outimg.empty()) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error AD AI Error"); return 1; } if (!CheckUtil::RoiInImg(pDetConfig->qx_roi, outimg)) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "qx roi Error"); return 1; } cv::Mat AnalysisyImg = outimg(pDetConfig->qx_roi).clone(); m_Show_Area = pDetConfig->old_Area; m_Show_Len = pDetConfig->old_len; // 开始分析mask; re = Analysisy(AnalysisyImg, pDetConfig); m_Len_P1.x += pDetConfig->qx_roi.x; m_Len_P1.y += pDetConfig->qx_roi.y; m_Len_P2.x += pDetConfig->qx_roi.x; m_Len_P2.y += pDetConfig->qx_roi.y; if (pDetConfig->pfunction_secondDet->andian_saveProcessImg) { if (true) { cv::rectangle(outimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); cv::rectangle(detimg123, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); cv::line(outimg, m_Len_P1, m_Len_P2, cv::Scalar(128, 0, 0)); { char buffer[128]; sprintf(buffer, " oA %d -> nA %d ", pDetConfig->old_Area, m_Show_Area); std::string st1 = buffer; cv::Point p(0, 10); cv::putText(outimg, st1, p, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); sprintf(buffer, " oL %0.2f -> nL %0.2f ", pDetConfig->old_len, m_Show_Len); st1 = buffer; cv::Point p2(0, 20); cv::putText(outimg, st1, p2, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); } } SaveProcessImg(img, outimg, detimg123, pDetConfig); } return re; } int AI_SecondDet::Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig) { // 存储轮廓 std::vector> contours; // 存储每个轮廓的层级 std::vector hierarchy; // 寻找轮廓 cv::findContours(maskImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); double maxArea = 0; int maxIndex = -1; // 遍历每个轮廓,计算面积并找出最大的面积 for (size_t i = 0; i < contours.size(); i++) { double area = cv::contourArea(contours[i]); if (area > maxArea) { maxArea = area; maxIndex = i; } } if (maxIndex < 0) { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "second mask is error"); return 1; /* code */ } bool barea = false; bool blen = false; int oldArea = pDetConfig->old_Area; float oldLen = pDetConfig->old_len; if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) { barea = pDetConfig->pfunction_secondDet->pol_Open_area; blen = pDetConfig->pfunction_secondDet->pol_Open_len; } if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) { barea = pDetConfig->pfunction_secondDet->andian_Open_area; blen = pDetConfig->pfunction_secondDet->andian_Open_len; } // 计算面积 // if (barea) { int maxContourPixelCount = 0; if (maxIndex >= 0) { cv::Mat mask = cv::Mat::zeros(maskImg.size(), CV_8UC1); cv::drawContours(mask, contours, maxIndex, cv::Scalar(255), cv::FILLED); // 绘制轮廓填充区域 maxContourPixelCount = cv::countNonZero(mask); // 计算填充区域的像素个数 } m_Show_Area = maxContourPixelCount; if (barea) { if (maxContourPixelCount > 0 && maxContourPixelCount < oldArea) { pDetConfig->new_Area = maxContourPixelCount; } m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Use New Area :old area %d (pixel) new %d", oldArea, pDetConfig->new_Area); } else { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " Not Use Area :old area %d (pixel) new %d", oldArea, maxContourPixelCount); } } // else // { // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Cal Area is Close"); // } // 计算长度 // if (blen) { cv::RotatedRect rect = cv::minAreaRect(contours[maxIndex]); // 获取最小外接矩形的尺寸 float width = rect.size.width; float height = rect.size.height; Point2f vertices[4]; rect.points(vertices); if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) { float len1 = sqrt((vertices[0].x - vertices[1].x) * (vertices[0].x - vertices[1].x) + (vertices[0].y - vertices[1].y) * (vertices[0].y - vertices[1].y)); float len2 = sqrt((vertices[2].x - vertices[1].x) * (vertices[2].x - vertices[1].x) + (vertices[2].y - vertices[1].y) * (vertices[2].y - vertices[1].y)); if (len1 > len2) { m_Len_P1.x = vertices[0].x; m_Len_P1.y = vertices[0].y; m_Len_P2.x = vertices[1].x; m_Len_P2.y = vertices[1].y; } else { m_Len_P1.x = vertices[2].x; m_Len_P1.y = vertices[2].y; m_Len_P2.x = vertices[1].x; m_Len_P2.y = vertices[1].y; } } else { m_Len_P1.x = vertices[2].x; m_Len_P1.y = vertices[2].y; m_Len_P2.x = vertices[0].x; m_Len_P2.y = vertices[0].y; } vector newcont; for (int i = 0; i < 4; ++i) { Point2f p; p.x = vertices[i].x * pDetConfig->fImgage_Scale_X; p.y = vertices[i].y * pDetConfig->fImgage_Scale_Y; newcont.push_back(p); } vector> contours_New; contours_New.push_back(newcont); // Recreate the rotated rectangle with scaled vertices RotatedRect scaledRect = minAreaRect(contours_New[0]); // Calculate scaled width and height width = scaledRect.size.width; height = scaledRect.size.height; float new_len = width; if (width > 0 && height > 0) { if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) { if (width > height) { new_len = width; } else { new_len = height; } } else { new_len = sqrt(width * width + height * height); } } else { if (width > height) { new_len = width; } else { new_len = height; } } // printf("oldLen %f new_len %f \n", oldLen, new_len); m_Show_Len = new_len; if (blen) { if (new_len > 0 && new_len < oldLen) { pDetConfig->new_len = new_len; } m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", "Use New Len :old Len %f (mm) new %f", oldLen, pDetConfig->new_len); } else { m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", " Not Use Len :old Len %f (mm) new %f", oldLen, new_len); } } // else // { // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", "Cal Len is Close"); // } return 0; } int AI_SecondDet::SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig) { if (inImg.empty() || outImg.empty()) { return 1; } static int saveimgIdx_pol = 0; static int saveimgIdx_ad = 0; // 循环存储 std::string str_Root = "/home/aidlux/BOE/FOG/Second/"; if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) { saveimgIdx_pol++; if (saveimgIdx_pol > 1000) { saveimgIdx_pol = 0; } str_Root += "POL/POl_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_pol); } if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) { saveimgIdx_ad++; if (saveimgIdx_ad > 1000) { saveimgIdx_ad = 0; } str_Root += "AD/AD_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_ad); } std::string strIn = str_Root + +"_in.png"; int re = 0; if (!inImg.empty()) { re = m_pImageStorage->addImage(strIn, inImg); } if (re == 0) { std::string strmask = str_Root + "_in_mask.png"; if (!outImg.empty()) { m_pImageStorage->addImage(strmask, outImg, true); // 强制 存储 } std::string stroldmask = str_Root + "_old_mask.png"; if (!oldmask.empty()) { m_pImageStorage->addImage(stroldmask, oldmask, true); // 强制 存储 } } return 0; }