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.

2159 lines
61 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-23 11:34:53
* @LastEditors: xiewenji 527774126@qq.com
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp
*/
#include "ImgCheckAnalysisy.hpp"
#include "CheckUtil.hpp"
#include "Define.h"
#include <omp.h>
#include "AICommonDefine.h"
// 用于排序轮廓的比较函数
static bool compareContourAreas(const vector<Point> &contour1, const vector<Point> &contour2)
{
double i = contourArea(contour1);
double j = contourArea(contour2);
return (i > j);
}
ImgCheckAnalysisy::ImgCheckAnalysisy()
: m_pAI_Edge_Algin(m_pdetlog)
, m_Pin_QX_Det(m_pdetlog)
{
m_nErrorCode = CHECK_OK;
m_nThreadIdx = -1;
m_bInitSucc = false;
m_bExit = false;
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
m_fImgage_Scale_X = 0.03f;
m_fImgage_Scale_Y = 0.03f;
m_pBasicConfig = NULL;
m_strCurDetChannel = "";
m_bupdateconfig = false;
m_pbaseCheckFunction = &m_AnalysisyConfig.baseFunction;
m_strLastDate = "";
m_strRootPath_TA_cls = "/home/aidlux/BOE/Cls/TA/";
m_strRootPath_CA_cls = "/home/aidlux/BOE/Cls/CA/";
creatsavedir();
m_pImageStorage = ImageStorage::getInstance();
m_nConfigIdx = -1;
m_ImgBlobHFlagData = NULL;
}
ImgCheckAnalysisy::~ImgCheckAnalysisy()
{
ExitSystem();
if (m_ImgBlobHFlagData)
{
delete[] m_ImgBlobHFlagData;
m_ImgBlobHFlagData = NULL;
}
}
int ImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType)
{
int re = 0;
switch (nConfigType)
{
case CHECK_CONFIG_Run:
re = LoadRunConfig(pconfig);
if (re == 0)
{
// printf("---> LoadRunConfig Succ\n");
}
else
{
printf("---> LoadRunConfig Fail\n");
}
break;
case CHECK_CONFIG_Module:
re = LoadCheckConfig(pconfig);
if (re == 0)
{
// printf("---> LoadAnalysisConfig Succ\n");
}
else
{
printf("---> LoadAnalysisConfig Fail\n");
}
break;
default:
break;
}
return re;
}
int ImgCheckAnalysisy::RunStart(void *pconfig1)
{
// 1 、更新参数 并判断参数是否合法
int re = CHECK_OK;
re = SetNewConfig();
if (CHECK_OK != re)
{
m_nErrorCode = re;
return m_nErrorCode;
}
// printf("---> RunStart Start m_RunConfig.nThreadIdx %d \n", m_RunConfig.nThreadIdx);
m_nThreadIdx = m_RunConfig.nThreadIdx;
re = InitRun(m_RunConfig.nCpu_start_Idx);
if (CHECK_OK != re)
{
m_nErrorCode = re;
return m_nErrorCode;
}
runner = std::make_shared<AIMulThreadRunBase>();
runner->Start();
m_nErrorCode = CHECK_OK;
// printf("ImgCheckAnalysisy >>>> ImgCheckThread %d Start Succ \n", m_nThreadIdx);
return m_nErrorCode;
}
int ImgCheckAnalysisy::SetDataRun_SharePtr(std::shared_ptr<ImageAllResult> p)
{
// 设置正在检测
m_pImageAllResult = p;
DetImgInfo_shareP = p->result->in_shareImage;
m_CheckResult_shareP = p->result;
m_pImageAllResult->setStep(ImageAllResult::DetStep_Deting);
m_pdetlog = p->detlog;
m_pDetResult = p->pDetResult;
StartCheck();
m_nErrorCode = CHECK_OK;
return m_nErrorCode;
}
int ImgCheckAnalysisy::GetCheckReuslt(std::shared_ptr<ImageDetResult> &pResult)
{
m_CheckResult_shareP.reset();
DetImgInfo_shareP.reset();
SetIDLE();
// m_nErrorCode = CHECK_OK;
// printf("4 DetImgInfo_shareP count %ld m_nCheckResultErrorCode %d \n", DetImgInfo_shareP.use_count(), m_nCheckResultErrorCode);
return m_nCheckResultErrorCode;
}
int ImgCheckAnalysisy::CheckImg(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult)
{
return 0;
}
int ImgCheckAnalysisy::ReJsonResul(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult)
{
return 0;
}
int ImgCheckAnalysisy::InitRun(int nId)
{
int re = CHECK_OK;
if (m_bInitSucc)
{
return CHECK_OK;
}
InitModel();
AI_Factory = AIFactory::GetInstance();
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
re = StartThread(nId);
if (CHECK_OK != re)
{
return re;
}
m_bInitSucc = true;
return re;
}
int ImgCheckAnalysisy::GetStatus()
{
return m_nRun_Status;
}
std::string ImgCheckAnalysisy::GetVersion()
{
return std::string("BOE_1.7.91");
}
std::string ImgCheckAnalysisy::GetErrorInfo()
{
std::string str = GetErrorCodeInfo(m_nErrorCode);
printf("%s\n", str.c_str());
return str;
}
int ImgCheckAnalysisy::creatsavedir()
{
std::string curDate = CheckUtil::getCurrentDate();
if (curDate == m_strLastDate)
{
return 0;
}
m_strLastDate = curDate;
m_strRootPath_TA_cls += m_strLastDate + "/";
m_strRootPath_CA_cls += m_strLastDate + "/";
for (int i = 0; i < AI_CLass_QX_NAME_count; i++)
{
CheckUtil::CreateDir(m_strRootPath_TA_cls + std::to_string(i) + "/");
CheckUtil::CreateDir(m_strRootPath_CA_cls + std::to_string(i) + "/");
}
return 0;
}
void ImgCheckAnalysisy::SetTplInfo(const cv::RotatedRect &outerRect,
const std::vector<std::vector<cv::Point>> &pinContours)
{
m_tplOuterRect = outerRect;
m_tplPinContours = pinContours;
}
int ImgCheckAnalysisy::LoadRunConfig(void *p)
{
if (p == NULL)
{
m_nErrorCode = CHECK_ERROR_Config_Null;
return m_nErrorCode;
}
RunInfoST *pconfig = (RunInfoST *)p;
m_RunConfig.copy(*pconfig);
return CHECK_OK;
}
int ImgCheckAnalysisy::LoadCheckConfig(void *p)
{
if (p == NULL)
{
m_nErrorCode = CHECK_ERROR_Config_Null;
return m_nErrorCode;
}
m_pConfig = (ConfigBase *)p;
m_nConfigIdx = m_pConfig->GetConfigIdx();
m_nErrorCode = CHECK_OK;
return m_nErrorCode;
}
// 开启检测
int ImgCheckAnalysisy::StartCheck()
{
m_nRun_Status = CHECK_THREAD_STATUS_READY;
return 0;
}
int ImgCheckAnalysisy::SetIDLE()
{
// 更新参数
SetNewConfig();
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
return 0;
}
int ImgCheckAnalysisy::StartThread(int nId)
{
// 开启检测线程
ptr_thread_Run = std::make_shared<std::thread>(std::bind(&ImgCheckAnalysisy::Run, this, nId));
if (!m_RunConfig.bRetest)
{
ptr_thread_AI = std::make_shared<std::thread>(std::bind(&ImgCheckAnalysisy::ThreadTask, this, nId + 1));
}
return 0;
}
int ImgCheckAnalysisy::StopThread()
{
m_bExit = true;
if (ptr_thread_Run != nullptr)
{
if (ptr_thread_Run->joinable())
{
ptr_thread_Run->join();
}
}
if (ptr_thread_AI != nullptr)
{
if (ptr_thread_AI->joinable())
{
ptr_thread_AI->join();
}
}
return 0;
}
int ImgCheckAnalysisy::ExitSystem()
{
StopThread();
return 0;
}
int ImgCheckAnalysisy::InitModel()
{
// 获取当前gpu号确定的 AI处理线程
m_OtherDet_Config.nDeviceId = m_RunConfig.nDeviceId;
m_pAI_Edge_Algin.Init(&m_OtherDet_Config);
m_pAI_Edge_Algin.InitModel_ALL();
return 0;
}
cv::Scalar ImgCheckAnalysisy::calc_blob_info_withstats(cv::Mat &img, const cv::Mat &mask, cv::Rect &stats, cv::Size k_size, int expand, double threshold)
{
// 解包 statsx, y, w, h, area
int x = stats.x, y = stats.y, w = stats.width, h = stats.height;
// 将图像转换为灰度图像
// 计算感兴趣区域 (ROI)
cv::Rect roi(x - expand, y - expand, w + 2 * expand, h + 2 * expand);
roi &= cv::Rect(0, 0, img.cols, img.rows); // 确保ROI在图像内
cv::Mat cimg = img(roi);
// cv::cvtColor(cimg, cimg, cv::COLOR_BGR2GRAY);
// return cv::Scalar(0, 0, 0);
cv::Mat cmask = mask(roi);
// getchar();
// 扩张掩膜
cv::Scalar mean_bk = cv::mean(cimg, ~cmask);
double fbk = mean_bk[0];
cv::Scalar mean_det = cv::mean(cimg, cmask);
double fdet = mean_det[0];
// 计算差异图像
cv::Mat diff = cv::abs(cimg - fbk);
// cv::imwrite("cimg.png",cimg);
// cv::imwrite("cmask.png",cmask);
// printf("%f %f - %f \n",fbk,fdet,fbk-fdet);
// getchar();
// diff = diff.mul(cmask > 0);
cv::Mat masked_image;
diff.copyTo(masked_image, cmask);
// 计算能量
double energy = cv::sum(masked_image)[0];
// 计算 hj差异图像大于0的像素均值
// double hj = std::abs(fbk - fdet);
// double hj = CheckUtil::CalHj(cimg, cmask, mean_bk.val[0]);
double hj = CheckUtil::CalHjWeighted(cimg, cmask, mean_bk.val[0], 2.0f);
int worb = 0;
if (fdet >= fbk)
{
worb = 1;
}
// cv::imwrite("cimg.png", cimg);
// cv::imwrite("cmask.png", cmask);
// cv::imwrite("diff.png", diff);
// cv::imwrite("masked_image.png", masked_image);
// printf("fbk %f fdet %f energy %f\n", fbk, fdet, energy);
// getchar();
return cv::Scalar(worb, energy, hj);
}
int ImgCheckAnalysisy::Adapt_Config(RotatedRect tplOuterRect, RotatedRect curOuterRect, Mat& det_img){
vector<cv::Point2f> cur_vertices = CheckUtil::sort_vertices(curOuterRect);
vector<cv::Point2f> tpl_vertices = CheckUtil::sort_vertices(tplOuterRect);
cv::Point2f src_pts[3] = {
cur_vertices[0], // 对应左上
cur_vertices[1], // 对应右上
cur_vertices[2] // 对应左下
};
cv::Point2f dst_pts[3] = {
tpl_vertices[0], // 左上
tpl_vertices[1], // 右上
tpl_vertices[2] // 左下
};
cv::Mat affine_mat = cv::getAffineTransform(src_pts, dst_pts);
// 仿射变换
cv::warpAffine(det_img, det_img, affine_mat, det_img.size());
// 将m_outer_rroi和m_inner_rroi变换到模板图像坐标系下
auto transformRotatedRect = [&affine_mat](cv::RotatedRect &rrect)
{
const double *M = affine_mat.ptr<double>(0);
cv::Point2f pts[4];
rrect.points(pts);
std::vector<cv::Point2f> transformed_pts(4);
for (int i = 0; i < 4; i++)
{
float x = static_cast<float>(M[0] * pts[i].x + M[1] * pts[i].y + M[2]);
float y = static_cast<float>(M[3] * pts[i].x + M[4] * pts[i].y + M[5]);
transformed_pts[i] = cv::Point2f(x, y);
}
rrect = cv::minAreaRect(transformed_pts);
};
transformRotatedRect(m_outer_rroi);
transformRotatedRect(m_inner_rroi);
return 0;
}
int ImgCheckAnalysisy::CheckRun()
{
// printf(">>>%s ================start \n", m_pImageAllResult->strBaseInfo.c_str());
long t1, t2, t3, t4, t5, t6, t7;
SetNewConfig();
t1 = CheckUtil::getcurTime();
CheckImgInit();
if (DetImgInfo_shareP->bsaveProcessImg)
{
m_pdetlog->bPrintStr = true;
}
m_pdetlog->bPrintStr = true;
m_pdetlog->AddCheckstr(PrintLevel_0, "1、basic Info", "---------------------------1、basic Info---------------------------------");
m_pdetlog->AddCheckstr(PrintLevel_0, "Version", "%s", GetVersion().c_str());
m_pdetlog->AddCheckstr(PrintLevel_0, "Updateconfig", "%d", m_bupdateconfig);
m_pdetlog->AddCheckstr(PrintLevel_0, "Start", "%s", m_pImageAllResult->strBaseInfo.c_str());
m_pdetlog->AddCheckstr(PrintLevel_0, "ImgageScale", "Scale_X = %f Scale_Y = %f", m_fImgage_Scale_X, m_fImgage_Scale_Y);
m_bupdateconfig = false;
// 返回结果状态初始化
m_CheckResult_shareP->checkStatus = 1;
m_CheckResult_shareP->nresult = -1;
m_CheckResult_shareP->basicResult.img_id = m_CheckResult_shareP->in_shareImage->img_id;
m_CheckResult_shareP->basicResult.imgtype = m_CheckResult_shareP->in_shareImage->imgtype;
m_CheckResult_shareP->basicResult.imgstr = m_CheckResult_shareP->in_shareImage->imgstr;
m_CheckResult_shareP->basicResult.strChannel = m_CheckResult_shareP->in_shareImage->strChannel;
m_strCurDetChannel = m_CheckResult_shareP->basicResult.strChannel;
/*参数检查*/
int rec = ConfigCheck(DetImgInfo_shareP->img);
if (rec != CHECK_OK)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Error", "ConfigCheck is error type = %d", rec);
m_nErrorCode = rec;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
long time_edge_s = CheckUtil::getcurTime();
/*AI 边缘定位(内外边缘)*/
// 模型定位内外边缘
int reedge = AI_Edge(m_CheckResult_shareP->in_shareImage->img, m_outer_rroi, m_inner_rroi);
if (reedge != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Error", "AI_Edge is error type = %d", reedge);
m_nErrorCode = reedge;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
long time_edge_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "2、pre detect", "-------------------------AI_Edge------------succ---time %ld----\n", time_edge_e - time_edge_s);
// 计算内外边缘夹角
float aouter = CheckUtil::getLongAxisAngle(m_outer_rroi);
float ainner = CheckUtil::getLongAxisAngle(m_inner_rroi);
float diff_align = std::fabs(aouter - ainner);
diff_align = std::fmod(diff_align, 180.0f); // 模 180 度
// 两条直线的夹角取锐角min(diff, 180 - diff)
if (diff_align > 90.0f)
{
diff_align = 180.0f - diff_align;
}
// 如果diff_align大于10则添加到缺陷列表
if (diff_align > 10.0f)
{
QX_ERROR_INFO_ alignErr;
alignErr.Idx = static_cast<int>(m_pDetResult->pQx_ErrorList->size());
// roi 用整张检测图区域detImg 坐标系)
cv::Rect tplRect = m_tplOuterRect.boundingRect();
alignErr.roi = cv::Rect(0, 0, tplRect.width, tplRect.height);
alignErr.area = alignErr.roi.width * alignErr.roi.height;
alignErr.JudgArea = alignErr.area * m_fImgage_Scale_X * m_fImgage_Scale_Y;
alignErr.flen = tplRect.width * m_fImgage_Scale_X;
alignErr.fbreadth = tplRect.height * m_fImgage_Scale_Y;
alignErr.nconfig_qx_type = CONFIG_QX_NAME_cell_zangwu;
alignErr.qx_name = CONFIG_QX_NAME_Names[CONFIG_QX_NAME_cell_zangwu];
alignErr.grayDis = diff_align; // 记录内外边缘夹角(度)
alignErr.detRegionidxList.push_back(0);
alignErr.detlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Align Check",
"outer-inner angle diff %.2f deg", diff_align);
m_pDetResult->pQx_ErrorList->push_back(alignErr);
m_pdetlog->AddCheckstr(PrintLevel_0, "Align Check", "angle diff %.2f deg > 10", diff_align);
}
/*投影对齐模板*/
Adapt_Config(m_tplOuterRect, m_outer_rroi, m_CheckResult_shareP->in_shareImage->img);
m_outer_roi = m_tplOuterRect.boundingRect();
m_Crop_Roi_paramImg = m_outer_roi;
m_pImageAllResult->pDetResult->CutRoi = m_outer_roi;
m_pImageAllResult->pDetResult->Param_CropRoi = m_Crop_Roi_paramImg;
long time_calan_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "2.1、pre detect", "-------------------------CalAndAffine------------succ---time %ld----\n", time_calan_e - time_edge_s);
/*生成 检测的图片*/
cv::Mat image;
image = m_CheckResult_shareP->in_shareImage->img;
if (image.channels() == 3)
{
cv::cvtColor(image(m_outer_roi), m_pImageAllResult->detImg, cv::COLOR_RGB2GRAY);
}
else
{
m_pImageAllResult->detImg = image(m_outer_roi).clone();
}
/*多线程开启 AI 推理检测*/
long time_AI_s = CheckUtil::getcurTime();
m_AItask = std::make_shared<TaskInfo>();
m_AItask->taskname = Task_AI;
m_task.sendTask(m_AItask);
ImgPreDet();
/*更新检测区域*/
// Update_DetRoiList();
m_pdetlog->AddCheckstr(PrintLevel_0, "3、pre detect", "-------------------------pre Det--------------- \n");
/*实现PIN脚检测*/
{
long t41 = CheckUtil::getcurTime();
int reedge1111 = Pin_Qx_Det(m_pImageAllResult->detImg);
long t42 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "4、detect", "-------------------------1、Pin_Qx_Det--------%ld-------\n", t42 - t41);
}
m_CheckResult_shareP->nresult = 0;
/*把临时可以绘制的结果都绘制出来。*/
DrawResult_Step_1();
long time_AI_e;
/*AI 推理生成*/
{
long t211 = CheckUtil::getcurTime();
// 对AI的结果进行 处理,等待 AI 推理全部完成。
rec = AIMaskDet();
if (rec != CHECK_OK)
{
m_nErrorCode = rec;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
time_AI_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "4、detect", "-------------------------2、AI Detect--------%ld wait AI complate %ld-------\n", time_AI_e - time_AI_s, time_AI_e - t211);
m_CheckResult_shareP->resultMaskImg = m_pImageAllResult->AIMaskImg;
}
{
t4 = CheckUtil::getcurTime();
rec = GetCheckResultBLob();
if (rec != CHECK_OK)
{
m_nErrorCode = rec;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
t5 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "5、BLob ", "------------------------ --------%ld -------\n", t5 - t4);
}
// m_pdetlog->printLog(m_strCurDetChannel);
long te = CheckUtil::getcurTime();
m_pdetlog->bPrintStr = true;
m_pdetlog->AddCheckstr(PrintLevel_1, "result", " ALL use Time %ld edge %ld AI %ld blob %ld",
te - t1, time_edge_e - time_edge_s, time_AI_e - time_AI_s, t5 - t4);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "End", " Check Run");
return 0;
}
int ImgCheckAnalysisy::SetNewConfig()
{
if (m_nConfigIdx < 0)
{
return 1;
/* code */
}
if (m_pConfig->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, m_nConfigIdx))
{
m_bupdateconfig = true;
// printf("************** ImgCheckAnalysisy::SetNewConfig m_nConfigIdx %d\n", m_nConfigIdx);
m_old_productROI = cv::Rect(0, 0, 0, 0);
m_pConfig->GetConfig(ConfigType_Analysisy_Common_XL, &m_AnalysisyConfig);
if (m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.size() > 0)
{
m_pCommonAnalysisyConfig = &m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(0);
m_pBasicConfig = &m_AnalysisyConfig.commonCheckConfig.baseConfig;
m_pRegionAnalysisyParam = &m_pCommonAnalysisyConfig->regionConfigArr.at(0);
UpdateImgageScale();
if (false)
{
printf("SetNewConfig m_nConfigIdx %d m_CheckConfig.strSkuName %s \n", m_nConfigIdx, m_AnalysisyConfig.strSkuName.c_str());
}
}
else
{
printf("m_AnalysisyConfig.commonCheckConfig.nodeConfigArr == 0 \n");
}
}
else
{
// printf("ConfigType_Analysisy_Common_XL no Update \n");
}
m_nErrorCode = CHECK_OK;
return CHECK_OK;
}
ChannelCheckFunction *ImgCheckAnalysisy::GetChannelFuntion(std::string strChannelName)
{
ChannelCheckFunction *p = NULL;
for (int i = 0; i < m_AnalysisyConfig.checkFunction.channelFunctionArr.size(); i++)
{
if (CheckUtil::compareIgnoreCase(m_AnalysisyConfig.checkFunction.channelFunctionArr[i].strChannelName, strChannelName))
{
p = &m_AnalysisyConfig.checkFunction.channelFunctionArr[i];
}
}
return p;
}
int ImgCheckAnalysisy::Run(int nId)
{
std::vector<int> vi;
vi.push_back(nId);
auto nRet = set_cpu_id(vi);
// printf("Check So %d bind cpu ret %d, %d\n", m_nThreadIdx, nRet, nId);
while (!m_bExit)
{
// 数据准备完成,开启检测
if (m_nRun_Status == CHECK_THREAD_STATUS_READY)
{
m_nRun_Status = CHECK_THREAD_STATUS_BUSY;
/* 检测 */
CheckRun();
m_nRun_Status = CHECK_THREAD_STATUS_COMPLETE;
m_pImageAllResult->setStep(ImageAllResult::DetStep_Complet);
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
// printf("*--------%d\n", m_nRun_Status);
}
else
{
usleep(1000);
}
// printf("*-");
usleep(1000);
}
return 0;
}
int ImgCheckAnalysisy::set_cpu_id(const std::vector<int> &cpu_set_vec)
{
// for cpu affinity
int nRet = 0;
#ifdef __linux
cpu_set_t _cur_cpu_set;
CPU_ZERO(&_cur_cpu_set);
for (auto _id : cpu_set_vec)
{
CPU_SET(_id, &_cur_cpu_set);
}
if (0 > pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cur_cpu_set))
{
perror("set cpu affinity failed: ");
printf("Warning: set cpu affinity failed ... ...\n");
nRet = -1;
}
#endif //__linux
return nRet;
}
int ImgCheckAnalysisy::CalBlob_Other()
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "CalBlob_Other", " Start");
float fs_x = m_fImgage_Scale_X;
float fs_y = m_fImgage_Scale_Y;
float fs_resize_x = m_pImageAllResult->fscale_detToresult_x;
float fs_resize_y = m_pImageAllResult->fscale_detToresult_y;
// 遍历每个检测blob
for (int i = 0; i < blobs.blobCount; i++)
{
// m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Blob", "%d/%d start", i, blobs.blobCount);
cv::Rect roi;
roi.x = blobs.blobTab[i].minx;
roi.y = blobs.blobTab[i].miny;
roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1;
roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1;
cv::Scalar result = calc_blob_info_withstats(m_pImageAllResult->detImg, m_pImageAllResult->AIMaskImg, roi);
int QX_whiteBLACK = CONFIG_QX_BLACK;
if (result[0] > 0)
{
QX_whiteBLACK = CONFIG_QX_WHITE;
}
double hj = result[2];
double energe = result[1];
blobs.blobTab[i].energy = energe;
blobs.blobTab[i].grayDis = hj;
float JudgArea = blobs.blobTab[i].area * fs_x * fs_y;
blobs.blobTab[i].JudgArea = JudgArea;
float flen = roi.width * fs_x;
float fwid = roi.height * fs_x;
if (roi.height * fs_y > flen)
{
flen = roi.height * fs_y;
fwid = roi.width * fs_y;
}
blobs.blobTab[i].len = flen;
blobs.blobTab[i].breadth = fwid;
int nerrortype = 0;
int checkFlage = 0;
float fmaxScore = 0;
int config_qx_type = 0;
if (blobs.blobTab[i].ErrType == ERR_TYPE_2)
{
QX_whiteBLACK = CONFIG_QX_BLACK; // 强制为 黑色
}
blobs.blobTab[i].whiteOrblack = QX_whiteBLACK;
// 精确计算长度
vector<float> re_len = Cal_QXLen(m_pImageAllResult->detImg(roi), config_qx_type, fs_x, fs_y);
if (re_len.size() > 2)
{
if(re_len[0] >= 0){
flen = re_len[0];
blobs.blobTab[i].len = flen;
}
if(re_len[1] >= 0){
fwid = re_len[1];
blobs.blobTab[i].breadth = fwid;
}
}
}
return 0;
}
int ImgCheckAnalysisy::GetClassImg(const cv::Mat &img, cv::Mat &AIdetImg, cv::Rect qx_roi, int detwidth, int detheight)
{
cv::Rect cutroi;
cv::Rect roi = qx_roi;
bool bresize = false;
{
int pc_x = roi.x + roi.width * 0.5;
int pc_y = roi.y + roi.height * 0.5;
if (roi.width < detwidth && roi.height < detheight)
{
cutroi.width = detwidth;
cutroi.x = pc_x - detwidth * 0.5;
cutroi.height = detheight;
cutroi.y = pc_y - detheight * 0.5;
}
else
{
// 宽 高
if (roi.width > roi.height)
{
cutroi.width = roi.width + 20;
cutroi.x = roi.x - 10;
float fsx = detheight * 1.0f / detwidth;
cutroi.height = cutroi.width * fsx;
cutroi.y = pc_y - cutroi.height * 0.5;
}
else
{
cutroi.height = roi.height + 20;
cutroi.y = roi.y - 10;
float fsy = detwidth * 1.0f / detheight;
cutroi.width = cutroi.height * fsy;
cutroi.x = pc_x - cutroi.width * 0.5;
}
bresize = true;
}
if (cutroi.x < 0)
{
cutroi.x = 0;
}
if (cutroi.y < 0)
{
cutroi.y = 0;
}
if (cutroi.x + cutroi.width >= img.cols)
{
cutroi.x = img.cols - cutroi.width;
if (cutroi.x < 0)
{
cutroi.x = 0;
if (cutroi.x + cutroi.width >= img.cols)
{
cutroi.width = img.cols;
}
}
}
if (cutroi.y + cutroi.height >= img.rows)
{
cutroi.y = img.rows - cutroi.height;
if (cutroi.y < 0)
{
cutroi.y = 0;
if (cutroi.y + cutroi.height >= img.rows)
{
cutroi.height = img.rows;
}
}
}
}
if (!CheckUtil::RoiInImg(cutroi, img))
{
return 1;
}
cv::Size sz;
sz.width = detwidth;
sz.height = detheight;
if (cutroi.width != sz.width || cutroi.height != sz.height)
{
cv::resize(img(cutroi), AIdetImg, sz);
}
else
{
AIdetImg = img(cutroi).clone();
}
if (1 != AIdetImg.channels())
{
cv::cvtColor(AIdetImg, AIdetImg, cv::COLOR_BGR2GRAY);
}
return 0;
}
vector<float> ImgCheckAnalysisy::Cal_QXLen(cv::Mat qx_maskImg, int qx_type, float fsc_x, float fsc_y)
{
vector<float> resLen(3);
float nlen = -1;
cv::Mat detimg = qx_maskImg;
resLen[0] = nlen;
// 寻找轮廓
vector<vector<Point>> contours;
cv::findContours(detimg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 找到最大面积的轮廓
double maxArea = -1;
int maxAreaIdx = -1;
for (size_t i = 0; i < contours.size(); ++i)
{
double area = contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxAreaIdx = i;
}
}
// 如果找到了最大面积的轮廓
if (maxAreaIdx >= 0)
{
// 使用minAreaRect找到最小外接矩形
cv::RotatedRect rect = cv::minAreaRect(contours[maxAreaIdx]);
// // 绘制最小外接矩形
// Point2f vertices[4];
// rect.points(vertices);
// for (int i = 0; i < 4; ++i)
// {
// line(detimg, vertices[i], vertices[(i + 1) % 4], Scalar(128, 255, 0), 2); // 绿色线
// }
// 输出结果
// 获取最小外接矩形的尺寸
float width = rect.size.width;
float height = rect.size.height;
// std::cout << "1 Width: " << width << ", Height: " << height << std::endl;
Point2f vertices[4];
rect.points(vertices);
vector<Point2f> newcont;
for (int i = 0; i < 4; ++i)
{
Point2f p;
p.x = vertices[i].x * fsc_x;
p.y = vertices[i].y * fsc_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;
// std::cout << "2 width: " << width << ", height: " << height << std::endl;
// float scale = 0.5; // 缩放比例
// rect.size.width *= fsc_x;
// rect.size.height *= fsc_y;
// std::cout << "fsc_x: " << fsc_x << ", fsc_y: " << fsc_y << std::endl;
// std::cout << "Width: " << width << ", Height: " << height << std::endl;
// 获取最小外接矩形的尺寸
// width = rect.size.width;
// height = rect.size.height;
if (width > height)
{
nlen = width;
resLen[0] = width;
resLen[1] = height;
/* code */
}
else
{
nlen = height;
resLen[0] = height;
resLen[1] = width;
}
}
// getchar();
return resLen;
}
int ImgCheckAnalysisy::GetCheckResultBLob()
{
long t1, t2, t3, t4, t5, t6, t7;
t1 = CheckUtil::getcurTime();
int re = GetALLBlob();
if (re != 0)
{
return re;
}
// 缺陷分类 多线程 实现。
long t11 = CheckUtil::getcurTime();
m_Classtask = std::make_shared<TaskInfo>();
m_Classtask->taskname = Task_Class;
m_task.sendTask(m_Classtask);
re = CalBlob_Other();
if (re != 0)
{
return re;
}
long t12 = CheckUtil::getcurTime();
// 等待分类 完成。
m_Classtask->waitComplate();
long t13 = CheckUtil::getcurTime();
// printf("=========== cls time %ld waite time %ld\n", t13 - t11, t13 - t12);
BLobToDetResult();
return 0;
}
void worker(const unsigned char *img, int w, int startRow, int endRow, unsigned char *rowFlags)
{
for (int y = startRow; y < endRow; y++)
{
const unsigned char *p = img + (size_t)y * w;
rowFlags[y] = 0;
for (int x = 0; x < w; x++)
{
if (p[x] != 0)
{
rowFlags[y] = 1;
break;
}
}
}
}
int ImgCheckAnalysisy::GetALLBlob()
{
std::string strBaseLog = "Blob";
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "image Blob Analysis Start");
if (m_pImageAllResult->AIMaskImg.empty())
{
return 1;
}
unsigned char *pGrayErrordata = (unsigned char *)m_pImageAllResult->AIMaskImg.data;
int width = m_pImageAllResult->AIMaskImg.cols;
int height = m_pImageAllResult->AIMaskImg.rows;
long t1 = CheckUtil::getcurTime();
memset(&blobs, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_BLOBS blobs_v1;
memset(&blobs_v1, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_BLOBS blobs_big;
memset(&blobs_big, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_BLOBS blobs_big_2;
memset(&blobs_big_2, 0x00, sizeof(ERROR_DOTS_BLOBS));
printf("=====>>>> GetALLBlob m_strCurDetChannel %s \n", m_strCurDetChannel.c_str());
if (m_strCurDetChannel == "CA")
{
printf("=====>>>>GetALLBlob USE CA %s \n", m_strCurDetChannel.c_str());
GetBlobs_ALL_New(&blobs_v1, pGrayErrordata, m_ImgBlobHFlagData, width, height, 15);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 1 num %d", blobs_v1.blobCount);
if (blobs_v1.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
GetBlobs_ALL_New(&blobs_big, pGrayErrordata, m_ImgBlobHFlagData, width, height, 200);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 2 num %d", blobs_big.blobCount);
if (blobs_big.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 3 num %d", blobs_big_2.blobCount);
GetBlobs_ALL_New(&blobs_big_2, pGrayErrordata, m_ImgBlobHFlagData, width, height, 500);
}
}
}
else
{
GetBlobs_oneLabe(&blobs_v1, pGrayErrordata, m_ImgBlobHFlagData, width, height, 15);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 1 num %d", blobs_v1.blobCount);
if (blobs_v1.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
GetBlobs_oneLabe(&blobs_big, pGrayErrordata, m_ImgBlobHFlagData, width, height, 200);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 2 num %d", blobs_big.blobCount);
if (blobs_big.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 3 num %d", blobs_big_2.blobCount);
GetBlobs_oneLabe(&blobs_big_2, pGrayErrordata, m_ImgBlobHFlagData, width, height, 500);
}
}
}
long t2 = CheckUtil::getcurTime();
PushBlob(&blobs, &blobs_big_2);
PushBlob(&blobs, &blobs_big);
PushBlob(&blobs, &blobs_v1);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob ALL num %d", blobs.blobCount);
// long t2 = CheckUtil::getcurTime();
// printf(" BLob time %ld \n", t2 - t1);
if (false || DetImgInfo_shareP->bsaveProcessImg)
{
int font_face = cv::FONT_HERSHEY_SIMPLEX;
double font_scale = 0.5;
int thickness = 1;
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, "Save Tem Img");
cv::Mat tm;
cv::cvtColor(m_pImageAllResult->AIMaskImg, tm, cv::COLOR_GRAY2RGB); // 彩色 可选项
for (int i = 0; i < blobs.blobCount; i++)
{
cv::Rect roi;
roi.x = blobs.blobTab[i].minx;
roi.y = blobs.blobTab[i].miny;
roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1;
roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1;
if (blobs.blobTab[i].ErrType == 0)
{
cv::rectangle(tm, roi, cv::Scalar(0, 0, 255));
}
else
{
cv::rectangle(tm, roi, cv::Scalar(0, 255, 255));
}
char buffer[128];
sprintf(buffer, "id:%d type:%d m %0.1f", i,blobs.blobTab[i].ErrType, blobs.blobTab[i].density);
std::string text = buffer;
cv::Point origin = cv::Point(roi.x, roi.y);
cv::putText(tm, text, origin, font_face, font_scale, cv::Scalar(0, 255, 0), thickness, 1, 0);
// printf("type: %d %d %d %d %d %d %d\n", blobs.blobTab[i].ErrType, blobs.blobTab[i].area, blobs.blobTab[i].energy, roi.x, roi.y, roi.width, roi.height);
}
cv::imwrite(m_CheckResult_shareP->in_shareImage->strChannel + "_image_resize_blob.png", tm);
}
long te = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "image Blob Analysis End use time %ld blob %ld ms", te - t1, t2 - t1);
// getchar();
return 0;
}
int ImgCheckAnalysisy::AIMaskDet()
{
// 计算 mask 图片的一行 是否有 残点,用以加速 Blob的计算。
if (m_ImgBlobHFlagData)
{
delete[] m_ImgBlobHFlagData;
m_ImgBlobHFlagData = NULL;
}
m_ImgBlobHFlagData = new unsigned char[m_pImageAllResult->detImg.rows];
memset(m_ImgBlobHFlagData, 0, sizeof(unsigned char) * m_pImageAllResult->detImg.rows);
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::shared_ptr<AIMulThreadRunBase::AITask> AImaskResult;
{
std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue);
if (m_AIMaskImgBLobQueue.size() > 0)
{
AImaskResult = std::move(m_AIMaskImgBLobQueue.front());
m_AIMaskImgBLobQueue.pop();
// printf("size ============== %ld\n", m_AIMaskImgBLobQueue.size());
}
}
// 有AI mask 的结果
if (AImaskResult)
{
// static int ss = 0;
cv::Mat &outimg = *(AImaskResult->output);
// cv::imwrite(std::to_string(ss++) + ".png", outimg);
unsigned char *pGrayErrordata = (unsigned char *)outimg.data;
int width = outimg.cols;
int height = outimg.rows;
int start_Y = AImaskResult->roi.y;
if (cv::countNonZero(outimg != 0) != 0)
{
// #pragma omp parallel for
for (int y = 0; y < height; y++)
{
if (m_ImgBlobHFlagData[y + start_Y] == 0)
{
unsigned char *p = pGrayErrordata + y * width;
for (int x = 0; x < width; x++)
{
if (p[x] != 0)
{
m_ImgBlobHFlagData[y + start_Y] = 1;
break;
}
}
}
}
}
}
else
{
/* code */
if (m_AItask->isComplate())
{
break;
}
}
}
// printf("===========================================1 \n");
m_AItask->waitComplate();
int rec = m_AItask->nresult;
if (rec != CHECK_OK)
{
return rec;
}
// printf("===========================================2 \n");
return 0;
}
int ImgCheckAnalysisy::Contours()
{
// std::string strBaseLog = "Contours";
// // m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Contours Start");
// cv::Mat detimg;
// {
// // 膨胀
// cv::Mat se = getStructuringElement(0, Size(5, 5)); // 构造矩形结构元素
// cv::dilate(m_pdetlog->temImgList[TEM_IMG_IDX_AImask], detimg, se);
// }
// std::vector<std::vector<cv::Point>> contours;
// std::vector<cv::Vec4i> hierarchy;
// cv::findContours(detimg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); // 只找最外层轮廓
// // cv::cvtColor(m_pdetlog->temImgList[TEM_IMG_IDX_SrcCrop], m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc], cv::COLOR_GRAY2BGR);
// for (int i = 0; i < contours.size(); ++i)
// { // 绘制所有轮廓
// cv::drawContours(m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc], contours, i, cv::Scalar(255, 0, 255)); // thickness为-1时为填充整个轮廓
// }
// float fx = m_pdetlog->temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_pdetlog->temImgList[TEM_IMG_IDX_SrcCrop].cols;
// float fy = m_pdetlog->temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_pdetlog->temImgList[TEM_IMG_IDX_SrcCrop].rows;
// for (int i = 0; i < contours.size(); ++i)
// {
// for (int j = 0; j < contours.at(i).size(); ++j)
// {
// contours.at(i).at(j).x *= fx;
// contours.at(i).at(j).y *= fy;
// }
// }
// // cv::cvtColor(m_pdetlog->temImgList[TEM_IMG_IDX_Result], m_pdetlog->temImgList[TEM_IMG_IDX_Result], cv::COLOR_GRAY2BGR);
// for (int i = 0; i < contours.size(); ++i)
// { // 绘制所有轮廓
// cv::drawContours(m_pdetlog->temImgList[TEM_IMG_IDX_Result], contours, i, cv::Scalar(255, 0, 255)); // thickness为-1时为填充整个轮廓
// }
// cv::imwrite("TEM_IMG_IDX_Result.png", m_pdetlog->temImgList[TEM_IMG_IDX_Result]);
// cv::imwrite("deeeee.png", m_pdetlog->temImgList[TEM_IMG_IDX_Drawmask]);
// getchar();
// m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Contours End");
return 0;
}
int ImgCheckAnalysisy::CheckImgInit()
{
// 1、初始化
m_pDetResult->pQx_ErrorList = std::make_shared<std::vector<QX_ERROR_INFO_>>();
m_pdetlog->Init();
m_pdetlog->addLogLevel = DET_LOG_LEVEL_3;
memset(&blobs, 0, sizeof(ERROR_DOTS_BLOBS));
m_nCheckResultErrorCode = 0;
m_Draw_qxImageResult.erase(m_Draw_qxImageResult.begin(), m_Draw_qxImageResult.end());
m_DetRoiList.Init();
return 0;
}
int ImgCheckAnalysisy::ConfigCheck(cv::Mat img)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "start", "Config Check");
int re = CHECK_OK;
if (img.empty())
{
m_nErrorCode = CHECK_ERROR_CheckImg_Empty;
m_pdetlog->AddCheckstr(PrintLevel_1, "Error", "check Img empty");
return m_nErrorCode;
}
// if (m_pCommonAnalysisyConfig->regionConfigArr.size() <= 0)
// {
// m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Error", "regionConfig Num = 0");
// m_nErrorCode = CHECK_ERROR_Config_Value;
// return m_nErrorCode;
// }
m_pdetlog->AddCheckstr(PrintLevel_0, "Succ", "Config Check Succ");
return re;
}
int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
{
// 依次使用多个检测模型,各模型输出 mask 取并集作为最终 outmask
std::vector<std::shared_ptr<AIModel_Base>> pAIDetList;
pAIDetList.push_back(AI_Factory->Defect);
pAIDetList.push_back(AI_Factory->Defect_QueXi);
std::string strBaseLog = "AI_Detect";
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect Start");
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)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " cutSmallImg error %d", re);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
return re;
/* code */
}
// 临时存图
if (DetImgInfo_shareP->bsaveProcessImg)
{
cv::Mat imshow;
if (img.channels() == 1)
{
cv::cvtColor(img, imshow, cv::COLOR_GRAY2RGB); // 彩色 可选项
}
else
{
imshow = img.clone();
}
for (int i = 0; i < SmallRoiList.size(); i++)
{
cv::rectangle(imshow, SmallRoiList.at(i), cv::Scalar(0, 0, 255), 3);
}
cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_Det_ROI.jpg", imshow);
}
ResultImg = cv::Mat::zeros(img.size(), CV_8UC1);
const int totalTasks = SmallRoiList.size();
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
t2 = CheckUtil::getcurTime();
// 依次用多个模型做检测,所有模型输出的 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::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;
runner->SubmitTask(task);
submitted++;
}
// 尝试取结果
std::shared_ptr<AIMulThreadRunBase::AITask> result;
if (runner->PopResult(result))
{
{
std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue);
m_AIMaskImgBLobQueue.push(result);
}
cv::Mat &outimg = *(result->output);
if (!outimg.empty())
{
// 多个模型的结果取并集
cv::Mat roiMat = ResultImg(result->roi);
cv::bitwise_or(roiMat, outimg, roiMat);
}
// 同一 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
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
}
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);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
// 临时存图
if (DetImgInfo_shareP->bsaveProcessImg)
{
cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_mask.png", ResultImg);
}
// getchar();
return 0;
}
int ImgCheckAnalysisy::AI_QX_Class_Thread()
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "QX_Class", " Start");
std::shared_ptr<AIModel_Base> pAIDet;
// printf("=====>>>>AI_QX_Class_Thread m_strCurDetChannel %s \n", m_strCurDetChannel.c_str());
{
// printf("=====>>>>AI_QX_Class_Thread USE CA %s \n", m_strCurDetChannel.c_str());
pAIDet = AI_Factory->Class;
}
int deal_image_width = pAIDet->input_0.width;
int deal_image_height = pAIDet->input_0.height;
const int totalTasks = blobs.blobCount;
int submitted = 0;
int completed = 0;
int detblobIdx = 0;
int clsnum = 0;
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
long t2 = CheckUtil::getcurTime();
while (completed < totalTasks)
{
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (submitted < totalTasks)
{
ERROR_DOTS_BLOB_DATA *pblob = &blobs.blobTab[submitted];
if (pblob->ErrType == ERR_TYPE_2)
{
pblob->AIclasstype = CONFIG_QX_NAME_cell_ymhs;
submitted++;
completed++;
continue;
}
else
{
// 如果任务还没提交完,且当前处理任务数 < 2提交新任务
if (runner->GetProcessingCount() < 10)
{
clsnum++;
cv::Rect roi;
roi.x = pblob->minx;
roi.y = pblob->miny;
roi.width = pblob->maxx - pblob->minx + 1;
roi.height = pblob->maxy - pblob->miny + 1;
std::shared_ptr<AIMulThreadRunBase::AITask> task = std::make_shared<AIMulThreadRunBase::AITask>();
task->id = submitted;
int re = GetClassImg(m_pImageAllResult->detImg, task->input, roi, deal_image_width, deal_image_height);
if (re == 0)
{
task->bclass = true;
task->engine = pAIDet;
runner->SubmitTask(task);
}
else
{
completed++;
}
submitted++;
}
}
}
// 尝试取结果
std::shared_ptr<AIMulThreadRunBase::AITask> result;
if (runner->PopResult(result))
{
int temClass = result->cls_label;
int cls_num = 0;
switch (temClass)
{
case 0:
cls_num = AI_CLass_QX_NAME_aotudian;
break;
case 1:
cls_num = AI_CLass_QX_NAME_other;
break;
case 2:
cls_num = AI_CLass_QX_NAME_line;
break;
case 3:
cls_num = AI_CLass_QX_NAME_zangwu;
break;
case 4:
cls_num = AI_CLass_QX_NAME_dianzhuang;
break;
case 5:
cls_num = AI_CLass_QX_NAME_posun;
break;
case 6:
cls_num = AI_CLass_QX_NAME_xianwei;
break;
case 7:
cls_num = AI_CLass_QX_NAME_shuizi;
break;
case 8:
cls_num = AI_CLass_QX_NAME_danban;
break;
case 9:
cls_num = AI_CLass_QX_NAME_fuchen;
break;
default:
cls_num = AI_CLass_QX_NAME_zangwu;
break;
}
// std::string strclassName = AI_CLass_QX_NAME_Names[cls_num];
// printf("AI Class num %d = %s %f\n", cls_num, strclassName.c_str(), result->cls_score);
// 分类存图 开启。
if (m_pbaseCheckFunction->saveImg.bSaveAlginImg)
{
std::string saveimgpaht = "";
if (m_strCurDetChannel == "TA")
{
saveimgpaht = m_strRootPath_TA_cls + std::to_string(cls_num) + "/" + std::to_string(CheckUtil::getcurTime()) + "_" + std::to_string(result->cls_score) + ".png";
}
else
{
saveimgpaht = m_strRootPath_CA_cls + std::to_string(cls_num) + "/" + std::to_string(CheckUtil::getcurTime()) + "_" + std::to_string(result->cls_score) + ".png";
}
{
m_pImageStorage->addImage(saveimgpaht, result->input);
}
}
int configqx = AIClassTypeToConfigType(cls_num);
ERROR_DOTS_BLOB_DATA *pblob = &blobs.blobTab[result->id];
pblob->AIclasstype = configqx;
completed++;
}
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
// printf("=====>>>>AI_QX_Class_Thread clsnum %d \n", clsnum);
return 0;
}
int ImgCheckAnalysisy::ThreadTask(int nId)
{
while (!m_bExit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
// 等待是否有任务
std::shared_ptr<TaskInfo> task = m_task.GetTask();
// 把任务发送给对应的任务处理函数进行处理
switch (task->taskname)
{
case Task_AI:
TaskFun_AIDet(task);
break;
case Task_Class:
TaskFun_QxClass(task);
break;
default:
break;
}
}
return 0;
}
int ImgCheckAnalysisy::ResizeImg()
{
cv::Size sz;
sz.width = RESIZE_IMAGE_WIDTH;
float fw = RESIZE_IMAGE_WIDTH * 1.0f / m_pImageAllResult->detImg.cols;
sz.height = int(m_pImageAllResult->detImg.rows * fw);
cv::resize(m_pImageAllResult->detImg, m_pImageAllResult->resultImg, sz);
if (m_pImageAllResult->resultImg.channels() == 1)
{
cv::cvtColor(m_pImageAllResult->resultImg, m_pImageAllResult->resultImg, cv::COLOR_GRAY2BGR);
}
m_CheckResult_shareP->resultimg = m_pImageAllResult->resultImg;
m_pdetlog->AddCheckstr(PrintLevel_1, "showImg size", " [w %d,h %d]-> show img [w %d,h %d] ",
m_outer_roi.width, m_outer_roi.height, sz.width, sz.height);
return 0;
}
void ImgCheckAnalysisy::TaskFun_AIDet(std::shared_ptr<TaskInfo> task)
{
task->SetStatus(TaskStep_run);
long t1, t2;
// AI 推理生成
{
t1 = CheckUtil::getcurTime();
int rec = AI_Detect_Thread(m_pImageAllResult->detImg, m_pImageAllResult->AIMaskImg);
t2 = CheckUtil::getcurTime();
task->nresult = rec;
}
task->SetStatus(TaskStep_compate);
}
void ImgCheckAnalysisy::TaskFun_QxClass(std::shared_ptr<TaskInfo> task)
{
task->SetStatus(TaskStep_run);
long t1, t2;
// AI 推理生成
{
t1 = CheckUtil::getcurTime();
int rec = AI_QX_Class_Thread();
t2 = CheckUtil::getcurTime();
task->nresult = rec;
}
task->SetStatus(TaskStep_compate);
}
int ImgCheckAnalysisy::Update_DetRoiList()
{
float fx = m_pImageAllResult->fscale_detToresult_x;
float fy = m_pImageAllResult->fscale_detToresult_y;
int num = 0;
cv::Rect offsetroi = m_Crop_Roi_paramImg;
if (m_pEdge_Align_Result && m_pEdge_Align_Result->buseOfft)
{
for (const auto &region : m_pCommonAnalysisyConfig->regionConfigArr)
{
if (m_pEdge_Align_Result->H.empty())
{
m_DetRoiList.Update_1(region.basicInfo.pointArry, offsetroi, m_pEdge_Align_Result->offt_x, m_pEdge_Align_Result->offt_y, fx, fy);
}
else
{
m_DetRoiList.Update_Marit(region.basicInfo.pointArry, offsetroi, m_pEdge_Align_Result->H, fx, fy);
}
// m_DetRoiList.Update_1(region.basicInfo.pointArry, offsetroi, m_pEdge_Align_Result->offt_x, m_pEdge_Align_Result->offt_y, fx, fy);
}
}
else
{
for (const auto &region : m_pCommonAnalysisyConfig->regionConfigArr)
{
m_DetRoiList.Update(region.basicInfo.pointArry, m_Crop_Roi_paramImg, fx, fy);
}
}
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "info", "roiList_Src roi num %ld", m_DetRoiList.roiList_Src.size());
// m_DetRoiList.print("m_DetRoiList");
return 0;
}
int ImgCheckAnalysisy::DrawResult_Step_1()
{
// std::cout << m_pBasicConfig->bDrawPreRoi << std::endl;
if (m_pBasicConfig->bDrawPreRoi)
{
int n = 0;
// std::cout << m_DetRoiList.roiList_Show.size() << std::endl;
for (const auto &polygon : m_DetRoiList.roiList_Show)
{
// n++;
// if (n == 1)
// {
// continue;
// }
// std::cout << polygon << std::endl;
// 绘制多边形的边界不填充使用绿色线条线宽为2
cv::polylines(m_CheckResult_shareP->resultimg, polygon, true, cv::Scalar(128, 128, 255), 1); // true表示闭合多边形
}
// cv::imwrite(DetImgInfo_shareP->strChannel + "roi_src.png", m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc]);
// cv::imwrite(DetImgInfo_shareP->strChannel + "roi_ss.png", m_pdetlog->temImgList[TEM_IMG_IDX_Result]);
// getchar();
}
float fs_resize_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols;
float fs_resize_y = m_pImageAllResult->resultImg.rows * 1.0f / m_pImageAllResult->detImg.rows;
// 绘制模板 pin 轮廓(绿色)与当前 pin 轮廓(红色)
for (const auto &contour : m_tplPinContours)
{
std::vector<cv::Point> draw_pts;
draw_pts.reserve(contour.size());
for (const auto &pt : contour)
{
draw_pts.emplace_back(cvRound(pt.x * fs_resize_x), cvRound(pt.y * fs_resize_y));
}
cv::polylines(m_CheckResult_shareP->resultimg, draw_pts, true, cv::Scalar(255, 255, 0), 1);
}
for (const auto &contour : m_curPinContours)
{
std::vector<cv::Point> draw_pts;
draw_pts.reserve(contour.size());
for (const auto &pt : contour)
{
draw_pts.emplace_back(cvRound(pt.x * fs_resize_x), cvRound(pt.y * fs_resize_y));
}
cv::polylines(m_CheckResult_shareP->resultimg, draw_pts, true, cv::Scalar(255, 0, 255), 1);
}
// 绘制m_inner_rroi蓝色
{
cv::Point2f vertices[4];
m_inner_rroi.points(vertices);
std::vector<cv::Point> draw_pts;
draw_pts.reserve(4);
for (int i = 0; i < 4; i++)
{
draw_pts.emplace_back(cvRound((vertices[i].x - m_Crop_Roi_paramImg.x) * fs_resize_x),
cvRound((vertices[i].y - m_Crop_Roi_paramImg.y) * fs_resize_y));
}
cv::polylines(m_CheckResult_shareP->resultimg, draw_pts, true, cv::Scalar(255, 0, 0), 1);
}
// cv::imwrite("sss.png", m_CheckResult_shareP->resultimg);
return 0;
}
int ImgCheckAnalysisy::AIClassTypeToConfigType(int nAIQXType)
{
int resultError_type = CONFIG_QX_NAME_cell_aotudian;
switch (nAIQXType)
{
case AI_CLass_QX_NAME_aotudian:
resultError_type = CONFIG_QX_NAME_cell_aotudian;
break;
case AI_CLass_QX_NAME_other:
resultError_type = CONFIG_QX_NAME_cell_other;
break;
case AI_CLass_QX_NAME_line:
resultError_type = CONFIG_QX_NAME_cell_line;
break;
case AI_CLass_QX_NAME_zangwu:
resultError_type = CONFIG_QX_NAME_cell_zangwu;
break;
case AI_CLass_QX_NAME_dianzhuang:
resultError_type = CONFIG_QX_NAME_cell_dianzhuang;
break;
case AI_CLass_QX_NAME_posun:
resultError_type = CONFIG_QX_NAME_cell_posun;
break;
case AI_CLass_QX_NAME_xianwei:
resultError_type = CONFIG_QX_NAME_cell_xianwei;
break;
case AI_CLass_QX_NAME_shuizi:
resultError_type = CONFIG_QX_NAME_cell_shuizi;
break;
case AI_CLass_QX_NAME_danban:
resultError_type = CONFIG_QX_NAME_cell_danban;
break;
case AI_CLass_QX_NAME_fuchen:
resultError_type = CONFIG_QX_NAME_cell_fuchen;
break;
default:
break;
}
return resultError_type;
}
int ImgCheckAnalysisy::UpdateImgageScale()
{
if (m_pBasicConfig->fImage_Scale_x > 0 && m_pBasicConfig->fImage_Scale_x < 1 &&
m_pBasicConfig->fImage_Scale_y > 0 && m_pBasicConfig->fImage_Scale_y < 1)
{
m_fImgage_Scale_X = m_pBasicConfig->fImage_Scale_x;
m_fImgage_Scale_Y = m_pBasicConfig->fImage_Scale_y;
}
return 0;
}
int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
{
m_Edge_DetConfig.Init();
m_Edge_DetConfig.strChannel = m_strCurDetChannel;
m_Edge_DetConfig.pBaseCheckFunction = m_pbaseCheckFunction;
m_Edge_DetConfig.bSaveResultImg = false;
if (DetImgInfo_shareP->bsaveProcessImg)
{
m_Edge_DetConfig.bSaveResultImg = true;
}
// m_pbaseCheckFunction->print("Pin_Qx_Det");
Mat pin_mask;
int re = m_Pin_QX_Det.GetPinMask(img, &m_Edge_DetConfig, pin_mask);
// 统计tplPinMask的blob边缘点并绘制到tplImg上
vector<vector<Point>> pin_contours;
vector<Vec4i> hierarchy;
cv::findContours(pin_mask, pin_contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
//缩放比例
const float pin_scale_x = (pin_mask.cols > 0) ? static_cast<float>(img.cols) / pin_mask.cols : 0.0f;
const float pin_scale_y = (pin_mask.rows > 0) ? static_cast<float>(img.rows) / pin_mask.rows : 0.0f;
// 将轮廓点从 mask 坐标系 映射回 tplImg 坐标系
m_curPinContours.clear();
m_curPinContours.reserve(pin_contours.size());
for (size_t i = 0; i < pin_contours.size(); i++)
{
std::vector<cv::Point> mapped;
mapped.reserve(pin_contours[i].size());
for (const auto &pt : pin_contours[i])
{
mapped.emplace_back(cvRound(pt.x * pin_scale_x),
cvRound(pt.y * pin_scale_y));
}
m_curPinContours.push_back(mapped);
}
// 根据模板Pin和当前Pin轮廓进行对比判断当前有无缺失和偏移
{
// 计算轮廓中心点(外接矩形中心)
auto getCenter = [](const std::vector<cv::Point> &contour) -> cv::Point2f
{
cv::Rect r = cv::boundingRect(contour);
return cv::Point2f(r.x + r.width * 0.5f, r.y + r.height * 0.5f);
};
const int nTpl = static_cast<int>(m_tplPinContours.size());
const int nCur = static_cast<int>(m_curPinContours.size());
if (nTpl > 0)
{
// 1、统计模板 pin 中心与平均最小边长,用于自适应阈值
std::vector<cv::Point2f> tplCenters(nTpl);
double sumMinDim = 0.0;
for (int i = 0; i < nTpl; i++)
{
tplCenters[i] = getCenter(m_tplPinContours[i]);
cv::Rect r = cv::boundingRect(m_tplPinContours[i]);
sumMinDim += (r.width < r.height) ? r.width : r.height;
}
const float avgMinDim = static_cast<float>(sumMinDim / nTpl);
// 偏移阈值约 1/4 个 pin 尺寸,缺失阈值约 3/4 个 pin 尺寸
float offsetTh = avgMinDim * 0.5f;
if (offsetTh < 3.0f)
{
offsetTh = 3.0f;
}
float missTh = avgMinDim * 0.75f;
if (missTh < offsetTh + 1.0f)
{
missTh = offsetTh + 1.0f;
}
// 2、当前 pin 中心
std::vector<cv::Point2f> curCenters(nCur);
for (int i = 0; i < nCur; i++)
{
curCenters[i] = getCenter(m_curPinContours[i]);
}
std::vector<bool> curUsed(nCur, false);
// 上报缺失/偏移缺陷(缺陷类型可按需调整)
auto reportPinError = [&](int pinIdx, const cv::Point2f &tplCenter, const std::string &reason)
{
QX_ERROR_INFO_ pinErr;
pinErr.Idx = static_cast<int>(m_pDetResult->pQx_ErrorList->size());
cv::Rect r = cv::boundingRect(m_tplPinContours[pinIdx]);
pinErr.roi = r;
pinErr.area = static_cast<int>(cv::contourArea(m_tplPinContours[pinIdx]));
pinErr.JudgArea = pinErr.area * m_fImgage_Scale_X * m_fImgage_Scale_Y;
int longSide = (r.width > r.height) ? r.width : r.height;
int shortSide = (r.width < r.height) ? r.width : r.height;
pinErr.flen = longSide * m_fImgage_Scale_X;
pinErr.fbreadth = shortSide * m_fImgage_Scale_Y;
pinErr.nconfig_qx_type = CONFIG_QX_NAME_cell_ymhs;
pinErr.qx_name = CONFIG_QX_NAME_Names[CONFIG_QX_NAME_cell_ymhs];
pinErr.detRegionidxList.push_back(0);
pinErr.detlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Pin Check",
"pin %d center(%d,%d) %s",
pinIdx, static_cast<int>(tplCenter.x), static_cast<int>(tplCenter.y),
reason.c_str());
m_pDetResult->pQx_ErrorList->push_back(pinErr);
};
int nMiss = 0;
int nOffset = 0;
// 3、逐个模板 pin 找最近且未被占用的当前 pin
for (int i = 0; i < nTpl; i++)
{
int bestIdx = -1;
double bestDist = 1e12;
for (int j = 0; j < nCur; j++)
{
if (curUsed[j])
{
continue;
}
float dx = tplCenters[i].x - curCenters[j].x;
float dy = tplCenters[i].y - curCenters[j].y;
double d = std::sqrt(static_cast<double>(dx) * dx + static_cast<double>(dy) * dy);
if (d < bestDist)
{
bestDist = d;
bestIdx = j;
}
}
// 无候选或距离过远 -> 缺失
if (bestIdx < 0 || bestDist > missTh)
{
nMiss++;
reportPinError(i, tplCenters[i], "miss");
m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "pin %d MISS", i);
continue;
}
curUsed[bestIdx] = true;
// 距离超出偏移阈值 -> 偏移
if (bestDist > offsetTh)
{
nOffset++;
char buf[64];
snprintf(buf, sizeof(buf), "offset %.1fpx", bestDist);
reportPinError(i, tplCenters[i], buf);
m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "pin %d OFFSET %.1fpx", i, bestDist);
}
}
m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "tpl %d cur %d miss %d offset %d", nTpl, nCur, nMiss, nOffset);
}
}
if (m_Edge_DetConfig.bSaveResultImg)
{
Mat showimg;
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
cv::drawContours(showimg, m_curPinContours, -1, cv::Scalar(0, 0, 255), 1);
cv::drawContours(showimg, m_tplPinContours, -1, cv::Scalar(0, 255, 0), 1);
imwrite("pin_contours.png", showimg);
}
return 0;
}
int ImgCheckAnalysisy::BLobToDetResult()
{
long t1 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", " Start old qx num %ld", m_pDetResult->pQx_ErrorList->size());
// 遍历每个检测blob
for (int i = 0; i < blobs.blobCount; i++)
{
cv::Rect roi;
roi.x = blobs.blobTab[i].minx;
roi.y = blobs.blobTab[i].miny;
roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1;
roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1;
int config_qx_type = blobs.blobTab[i].AIclasstype;
float JudgArea = blobs.blobTab[i].JudgArea;
float fsecondArea = JudgArea;
std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type];
if (true)
{
QX_ERROR_INFO_ temerror;
temerror.roi = roi;
temerror.Idx = m_pDetResult->pQx_ErrorList->size();
temerror.area = blobs.blobTab[i].area;
temerror.JudgArea = JudgArea;
temerror.JudgArea_second = fsecondArea;
temerror.energy = blobs.blobTab[i].energy;
temerror.flen = blobs.blobTab[i].len;
temerror.fbreadth = blobs.blobTab[i].breadth;
temerror.nconfig_qx_type = config_qx_type;
temerror.qx_name = qx_name;
temerror.maxValue = blobs.blobTab[i].maxValue;
temerror.grayDis = blobs.blobTab[i].grayDis;
temerror.density = blobs.blobTab[i].density;
temerror.fUpIou = 0;
temerror.whiteOrBlack = blobs.blobTab[i].whiteOrblack;
{
cv::Point pCenter;
pCenter.x = roi.x + roi.width * 0.5;
pCenter.y = roi.y + roi.height * 0.5;
int nmaxregionIdx = 0;
for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
{
const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion];
double result = cv::pointPolygonTest(polygon, pCenter, false);
if (result < 0)
{
continue;
}
nmaxregionIdx = iregion;
}
temerror.detRegionidxList.push_back(nmaxregionIdx);
}
// {
// cv::Point pCenter;
// pCenter.x = roi.x + roi.width * 0.5;
// pCenter.y = roi.y + roi.height * 0.5;
// for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
// {
// const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion];
// double result = cv::pointPolygonTest(polygon, pCenter, false);
// if (result < 0)
// {
// continue;
// }
// temerror.detRegionidxList.push_back(iregion);
// }
// if (temerror.detRegionidxList.size() <= 0)
// {
// temerror.detRegionidxList.push_back(0);
// }
// }
m_pDetResult->pQx_ErrorList->push_back(temerror);
// printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen);
}
}
long t2 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", " end qx num %ld use time %ld", m_pDetResult->pQx_ErrorList->size(), t2 - t1);
return 0;
}
int ImgCheckAnalysisy::AI_Edge(const cv::Mat &img, cv::RotatedRect &outerRoi, cv::RotatedRect &innerRoi)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "AI_Edge", "-------------------start--------------");
AI_Edge_Algin::DetConfig config;
if (DetImgInfo_shareP->bsaveProcessImg)
{
config.bSaveResultImg = true;
}
config.strChannel = DetImgInfo_shareP->strChannel;
config.pBaseCheckFunction = m_pbaseCheckFunction;
int re = m_pAI_Edge_Algin.Detect(img, &config, m_pEdge_Align_Result);
if (re != 0)
{
printf("AI_Edge Is Error = %d \n", re);
}
outerRoi = m_pEdge_Align_Result->bigroi;
innerRoi = m_pEdge_Align_Result->smallroi;
// getchar();
return re;
}
int ImgCheckAnalysisy::CalProductSize()
{
float fw = m_outer_roi.width * m_fImgage_Scale_X;
float fh = m_outer_roi.height * m_fImgage_Scale_Y;
fw = std::ceil(fw * 10) / 10;
fh = std::ceil(fh * 10) / 10;
m_CheckResult_shareP->productWidht_mm = fw;
m_CheckResult_shareP->productHeight_mm = fh;
m_pdetlog->AddCheckstr(PrintLevel_1, "Det ROI", " [w %d,h %d] (piexl) -> [w %f h %f](mm),scale %f %f",
m_outer_roi.width, m_outer_roi.height, fw, fh, m_fImgage_Scale_X, m_fImgage_Scale_Y);
return 0;
}
int ImgCheckAnalysisy::ImgPreDet()
{
// 计算产品尺寸
CalProductSize();
if (m_pbaseCheckFunction->saveImg.bSaveClsImg)
{
creatsavedir();
}
m_CheckResult_shareP->cutSrcimg = m_pImageAllResult->detImg;
ResizeImg();
m_pImageAllResult->fscale_detToresult_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols;
m_pImageAllResult->fscale_detToresult_y = m_pImageAllResult->resultImg.rows * 1.0f / m_pImageAllResult->detImg.rows;
return 0;
}