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;
t1 = CheckUtil::getcurTime();
SmallRoiList.clear();
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)
if (img.empty())
{
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");
return re;
/* 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);
return 1;
}
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);
}
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();
// 依次用多个模型做检测,所有模型输出的 mask 取并集作为最终 outmask
// 模型实际输入图(整图 resize 到模型输入大小)缓存一份,供结果记录使用
cv::Mat firstModelInput;
// 依次用多个模型做检测:整图 resize 到模型输入大小 -> 推理 -> 输出 mask resize 回原图大小,
// 所有模型输出的 mask 取并集作为最终 outmask
for (size_t m = 0; m < pAIDetList.size(); m++)
{
std::shared_ptr<AIModel_Base> pAIDet = pAIDetList[m];
int submitted = 0;
int completed = 0;
while (completed < totalTasks)
{
// 如果任务还没提交完,且当前处理任务数 < 10,提交新任务
if (submitted < totalTasks && runner->GetProcessingCount() < 10)
std::string strModelName = (m < pAIDetNameList.size()) ? pAIDetNameList[m] : std::string(AI_DET_MODEL_NAME_UnKnown);
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)
{
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);
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>();
task->id = submitted;
task->roi = SmallRoiList.at(submitted);
task->input = img(SmallRoiList.at(submitted)).clone();
task->output = std::make_shared<cv::Mat>();
task->engine = pAIDet;
// 1、整图 resize 到模型输入大小
cv::Mat detInputImg;
cv::resize(img, detInputImg, cv::Size(deal_image_width, deal_image_height));
// 模型输入要求单通道;原图为彩色时按 BGR 顺序转灰度(与 imread(path,0) 的亮度一致)
if (detInputImg.channels() == 3)
{
cv::cvtColor(detInputImg, detInputImg, cv::COLOR_BGR2GRAY);
}
else if (detInputImg.channels() == 4)
{
cv::cvtColor(detInputImg, detInputImg, cv::COLOR_BGRA2GRAY);
}
runner->SubmitTask(task);
submitted++;
if (m == 0)
{
firstModelInput = detInputImg;
}
// 尝试取结果
std::shared_ptr<AIMulThreadRunBase::AITask> result;
if (runner->PopResult(result))
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " %s input img [%d*%d] -> model [%d*%d]",
strModelName.c_str(), img.cols, img.rows, deal_image_width, deal_image_height);
// 临时存图:保存模型实际输入图
if (DetImgInfo_shareP->bsaveProcessImg)
{
cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_Det_" + strModelName + "_in.jpg", detInputImg);
}
// 2、整图推理
cv::Mat modelMask;
int re = pAIDet->AIDet(detInputImg, modelMask);
if (re != 0)
{
std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue);
m_AIMaskImgBLobQueue.push(result);
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;
}
cv::Mat &outimg = *(result->output);
if (!outimg.empty())
// 3、输出 mask resize 回原图大小(最近邻,保证 mask 像素值不被插值改变)
cv::Mat modelMaskFull;
if (!modelMask.empty())
{
// 多个模型的结果取并集
cv::Mat roiMat = ResultImg(result->roi);
cv::bitwise_or(roiMat, outimg, roiMat);
cv::resize(modelMask, modelMaskFull, img.size(), 0, 0, cv::INTER_NEAREST);
// 多个模型的 mask 取并集
cv::bitwise_or(ResultImg, modelMaskFull, ResultImg);
// 当前模型自己的 mask 单独记录一份
if (m < modelMaskList.size() && !modelMaskList[m].empty())
{
cv::Mat modelRoiMat = modelMaskList[m](result->roi);
cv::bitwise_or(modelRoiMat, outimg, modelRoiMat);
cv::bitwise_or(modelMaskList[m], modelMaskFull, modelMaskList[m]);
}
// AI 检测残点图存图:每个模型的结果都存,并增加一级 模型名称 目录,
// 用以区分该残点是由哪个模型检出的
// 目录结构:/home/aidlux/BOE/ZB_SOCKET/AI_Detect/<模型名称>/<产品ID>/
if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg)
if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg && !modelMaskFull.empty())
{
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);
}
std::string strSavePath_in = strSaveDir + m_strCurDetChannel + "_in.png";
std::string strSavePath_out = strSaveDir + m_strCurDetChannel + "_out.png";
cv::imwrite(strSavePath_in, detInputImg);
cv::imwrite(strSavePath_out, modelMaskFull);
}
// 同一 roi 的多个模型结果取并集后存入 AI_Qx_MaskList
bool bFind = false;
for (auto &item : m_pImageAllResult->AI_Qx_MaskList)
{
if (item->roi == result->roi)
{
cv::bitwise_or(item->AI_mask, outimg, 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 = result->roi;
temAIresult->AI_inImg = result->input;
temAIresult->AI_mask = outimg.clone();
m_pImageAllResult->AI_Qx_MaskList.push_back(temAIresult);
}
completed++;
}
else
// 4、mask 结果放入队列,用于 AIMaskDet 加速 blob 计算(整图 ROI)
if (!modelMaskFull.empty())
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::shared_ptr<AIMulThreadRunBase::AITask> maskTask = std::make_shared<AIMulThreadRunBase::AITask>();
maskTask->id = static_cast<int>(m);
maskTask->roi = fullRoi;
maskTask->output = std::make_shared<cv::Mat>(modelMaskFull);
std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue);
m_AIMaskImgBLobQueue.push(maskTask);
}
}
t3 = CheckUtil::getcurTime();
float mean_AI = (t3 - t2) / (SmallRoiList.size() * 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);
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 Full Img %f", t3 - t1, t2 - t1, t3 - t2, mean_AI);
// 保存各模型的 全图 mask,并输出各模型检出的残点像素数量,便于追溯
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));
}
// 整图检测模式下所有模型共用同一个 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");
// 临时存图

Loading…
Cancel
Save