You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
BOE_FOG_DETECT/AlgorithmModule/src/AI_Second_Det.cpp

565 lines
17 KiB

#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<AIModel_Base> 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<AIModel_Base> 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<AIModel_Base> 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<std::vector<cv::Point>> contours;
// 存储每个轮廓的层级
std::vector<cv::Vec4i> 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<Point2f> 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<vector<Point2f>> 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;
}