update 修改AI检测流程

dev_lsy
liusiyang 3 weeks ago
parent ba394569ec
commit 871d14adb6

@ -1378,38 +1378,11 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
long t1, t2, t3; long t1, t2, t3;
t1 = CheckUtil::getcurTime(); t1 = CheckUtil::getcurTime();
SmallRoiList.clear(); if (img.empty())
SmallRoiList.erase(SmallRoiList.begin(), SmallRoiList.end());
cv::Rect cutRoi;
cutRoi.x = 0;
cutRoi.y = 0;
cutRoi.width = img.cols - 0;
cutRoi.height = img.rows - 0;
int deal_image_width = pAIDetList[0]->input_0.width;
int deal_image_height = pAIDetList[0]->input_0.height;
int re = CheckUtil::cutSmallImg(img, SmallRoiList, cutRoi, deal_image_width, deal_image_height, 0, 0);
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " cutSmallImg Num %d", SmallRoiList.size());
if (re != 0 || SmallRoiList.size() <= 0)
{ {
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " cutSmallImg error %d", re); m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " input img empty error");
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End"); m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
return re; return 1;
/* code */
}
// 临时存图
if (DetImgInfo_shareP->bsaveProcessImg)
{
cv::Mat imshow = img.clone(); // 保持输入通道,不再灰度转假彩
for (int i = 0; i < SmallRoiList.size(); i++)
{
cv::rectangle(imshow, SmallRoiList.at(i), CheckUtil::GetDrawColor(imshow, cv::Scalar(0, 0, 255)), 3);
}
cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_Det_ROI.jpg", imshow);
} }
ResultImg = cv::Mat::zeros(img.size(), CV_8UC1); ResultImg = cv::Mat::zeros(img.size(), CV_8UC1);
@ -1422,105 +1395,108 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
modelMaskList[m] = cv::Mat::zeros(img.size(), CV_8UC1); modelMaskList[m] = cv::Mat::zeros(img.size(), CV_8UC1);
} }
const int totalTasks = SmallRoiList.size(); // 整图检测模式下,所有模型的 ROI 都是整幅检测图
const cv::Rect fullRoi(0, 0, img.cols, img.rows);
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
t2 = CheckUtil::getcurTime(); t2 = CheckUtil::getcurTime();
// 依次用多个模型做检测,所有模型输出的 mask 取并集作为最终 outmask // 模型实际输入图(整图 resize 到模型输入大小)缓存一份,供结果记录使用
cv::Mat firstModelInput;
// 依次用多个模型做检测:整图 resize 到模型输入大小 -> 推理 -> 输出 mask resize 回原图大小,
// 所有模型输出的 mask 取并集作为最终 outmask
for (size_t m = 0; m < pAIDetList.size(); m++) for (size_t m = 0; m < pAIDetList.size(); m++)
{ {
std::shared_ptr<AIModel_Base> pAIDet = pAIDetList[m]; std::shared_ptr<AIModel_Base> pAIDet = pAIDetList[m];
int submitted = 0; std::string strModelName = (m < pAIDetNameList.size()) ? pAIDetNameList[m] : std::string(AI_DET_MODEL_NAME_UnKnown);
int completed = 0;
while (completed < totalTasks) int deal_image_width = pAIDet->input_0.width;
int deal_image_height = pAIDet->input_0.height;
if (deal_image_width <= 0 || deal_image_height <= 0)
{ {
// 如果任务还没提交完,且当前处理任务数 < 10,提交新任务 m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " %s model input size error [%d %d]", strModelName.c_str(), deal_image_width, deal_image_height);
if (submitted < totalTasks && runner->GetProcessingCount() < 10) m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
{ return 2;
}
std::shared_ptr<AIMulThreadRunBase::AITask> task = std::make_shared<AIMulThreadRunBase::AITask>(); // 1、整图 resize 到模型输入大小
task->id = submitted; cv::Mat detInputImg;
task->roi = SmallRoiList.at(submitted); cv::resize(img, detInputImg, cv::Size(deal_image_width, deal_image_height));
task->input = img(SmallRoiList.at(submitted)).clone(); // 模型输入要求单通道;原图为彩色时按 BGR 顺序转灰度(与 imread(path,0) 的亮度一致)
task->output = std::make_shared<cv::Mat>(); if (detInputImg.channels() == 3)
task->engine = pAIDet; {
cv::cvtColor(detInputImg, detInputImg, cv::COLOR_BGR2GRAY);
}
else if (detInputImg.channels() == 4)
{
cv::cvtColor(detInputImg, detInputImg, cv::COLOR_BGRA2GRAY);
}
runner->SubmitTask(task); if (m == 0)
submitted++; {
} firstModelInput = detInputImg;
}
// 尝试取结果 m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " %s input img [%d*%d] -> model [%d*%d]",
std::shared_ptr<AIMulThreadRunBase::AITask> result; strModelName.c_str(), img.cols, img.rows, deal_image_width, deal_image_height);
if (runner->PopResult(result))
{
{ // 临时存图:保存模型实际输入图
std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue); if (DetImgInfo_shareP->bsaveProcessImg)
m_AIMaskImgBLobQueue.push(result); {
} cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_Det_" + strModelName + "_in.jpg", detInputImg);
}
cv::Mat &outimg = *(result->output); // 2、整图推理
if (!outimg.empty()) cv::Mat modelMask;
{ int re = pAIDet->AIDet(detInputImg, modelMask);
// 多个模型的结果取并集 if (re != 0)
cv::Mat roiMat = ResultImg(result->roi); {
cv::bitwise_or(roiMat, outimg, roiMat); m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " %s AIDet error %d", strModelName.c_str(), re);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
return re;
}
// 当前模型自己的 mask 单独记录一份 // 3、输出 mask resize 回原图大小(最近邻,保证 mask 像素值不被插值改变)
if (m < modelMaskList.size() && !modelMaskList[m].empty()) cv::Mat modelMaskFull;
{ if (!modelMask.empty())
cv::Mat modelRoiMat = modelMaskList[m](result->roi); {
cv::bitwise_or(modelRoiMat, outimg, modelRoiMat); cv::resize(modelMask, modelMaskFull, img.size(), 0, 0, cv::INTER_NEAREST);
}
// AI 检测残点图存图:每个模型的结果都存,并增加一级 模型名称 目录, // 多个模型的 mask 取并集
// 用以区分该残点是由哪个模型检出的 cv::bitwise_or(ResultImg, modelMaskFull, ResultImg);
// 目录结构:/home/aidlux/BOE/ZB_SOCKET/AI_Detect/<模型名称>/<产品ID>/
if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg)
{
std::string strModelName = (m < pAIDetNameList.size()) ? pAIDetNameList[m] : std::string(AI_DET_MODEL_NAME_UnKnown);
std::string roi_ext = "[" + std::to_string(result->roi.x) + "," + std::to_string(result->roi.y) + "]";
std::string strSaveDir = "/home/aidlux/BOE/ZB_SOCKET/AI_Detect/" + strModelName + "/" + DetImgInfo_shareP->strImgProductID + "/";
CheckUtil::CreateDir(strSaveDir);
std::string strSavePath_in = strSaveDir + m_strCurDetChannel + "_" + roi_ext + "_in.png";
std::string strSavePath_out = strSaveDir + m_strCurDetChannel + "_" + roi_ext + "_out.png";
cv::imwrite(strSavePath_in, result->input);
cv::imwrite(strSavePath_out, outimg);
}
}
// 同一 roi 的多个模型结果取并集后存入 AI_Qx_MaskList // 当前模型自己的 mask 单独记录一份
bool bFind = false; cv::bitwise_or(modelMaskList[m], modelMaskFull, modelMaskList[m]);
for (auto &item : m_pImageAllResult->AI_Qx_MaskList) }
{
if (item->roi == result->roi) // AI 检测残点图存图:每个模型的结果都存,并增加一级 模型名称 目录,
{ // 用以区分该残点是由哪个模型检出的
cv::bitwise_or(item->AI_mask, outimg, item->AI_mask); // 目录结构:/home/aidlux/BOE/ZB_SOCKET/AI_Detect/<模型名称>/<产品ID>/
bFind = true; if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg && !modelMaskFull.empty())
break; {
} std::string strSaveDir = "/home/aidlux/BOE/ZB_SOCKET/AI_Detect/" + strModelName + "/" + DetImgInfo_shareP->strImgProductID + "/";
} CheckUtil::CreateDir(strSaveDir);
if (!bFind) std::string strSavePath_in = strSaveDir + m_strCurDetChannel + "_in.png";
{ std::string strSavePath_out = strSaveDir + m_strCurDetChannel + "_out.png";
std::shared_ptr<ImageAllResult::AI_Det_MaskImg> temAIresult = std::make_shared<ImageAllResult::AI_Det_MaskImg>(); cv::imwrite(strSavePath_in, detInputImg);
temAIresult->roi = result->roi; cv::imwrite(strSavePath_out, modelMaskFull);
temAIresult->AI_inImg = result->input; }
temAIresult->AI_mask = outimg.clone();
m_pImageAllResult->AI_Qx_MaskList.push_back(temAIresult); // 4、mask 结果放入队列,用于 AIMaskDet 加速 blob 计算(整图 ROI)
} if (!modelMaskFull.empty())
completed++; {
} std::shared_ptr<AIMulThreadRunBase::AITask> maskTask = std::make_shared<AIMulThreadRunBase::AITask>();
else maskTask->id = static_cast<int>(m);
{ maskTask->roi = fullRoi;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); maskTask->output = std::make_shared<cv::Mat>(modelMaskFull);
} std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue);
m_AIMaskImgBLobQueue.push(maskTask);
} }
} }
t3 = CheckUtil::getcurTime(); t3 = CheckUtil::getcurTime();
float mean_AI = (t3 - t2) / (SmallRoiList.size() * pAIDetList.size()); float mean_AI = (t3 - t2) / (float)pAIDetList.size();
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run Time: sum %ld pre %ld Run %ld mean One Small Img %f", t3 - t1, t2 - t1, t3 - t2, mean_AI); m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run Time: sum %ld pre %ld Run %ld mean One Full Img %f", t3 - t1, t2 - t1, t3 - t2, mean_AI);
// 保存各模型的 全图 mask,并输出各模型检出的残点像素数量,便于追溯 // 保存各模型的 全图 mask,并输出各模型检出的残点像素数量,便于追溯
for (size_t m = 0; m < modelMaskList.size(); m++) for (size_t m = 0; m < modelMaskList.size(); m++)
@ -1534,6 +1510,27 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
temModelMask->strModelName.c_str(), cv::countNonZero(temModelMask->ModelMask)); temModelMask->strModelName.c_str(), cv::countNonZero(temModelMask->ModelMask));
} }
// 整图检测模式下所有模型共用同一个 ROI(整幅检测图),多个模型的 mask 已取并集,
// 按整图 ROI 记录一条 AI 检测结果,供 GetAIDetImg 按缺陷中心点取到 AI 输入图与并集 mask
bool bFind = false;
for (auto &item : m_pImageAllResult->AI_Qx_MaskList)
{
if (item->roi == fullRoi)
{
cv::bitwise_or(item->AI_mask, ResultImg, item->AI_mask);
bFind = true;
break;
}
}
if (!bFind)
{
std::shared_ptr<ImageAllResult::AI_Det_MaskImg> temAIresult = std::make_shared<ImageAllResult::AI_Det_MaskImg>();
temAIresult->roi = fullRoi;
temAIresult->AI_inImg = firstModelInput;
temAIresult->AI_mask = ResultImg.clone();
m_pImageAllResult->AI_Qx_MaskList.push_back(temAIresult);
}
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End"); m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
// 临时存图 // 临时存图

Loading…
Cancel
Save