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/CameraCheckAnalysisy.cpp

1464 lines
48 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: xiewenji 527774126@qq.com
* @Date: 2025-09-23 18:06:58
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-26 10:10:28
* @FilePath: /BOE_POL_ET_Detect/AlgorithmModule/src/CameraCheckAnalysisy.cpp
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-25 18:03:34
* @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 "CameraCheckAnalysisy.hpp"
#include "CheckUtil.hpp"
#include "Define.h"
#include <fstream>
#include <dirent.h>
#include <sys/stat.h>
#include <atomic>
#include <future>
#include <vector>
#include <mutex>
#include <algorithm>
static std::mutex g_ngImgSave_mutex;
static std::vector<std::future<void>> g_ngImgSave_futures;
CameraCheckAnalysisy::CameraCheckAnalysisy()
{
m_nErrorCode = 0; // 错误代码
m_bInitSucc = false; // 初始化状态
m_bExit = false; // 是否退出检测
m_bHaveImgeDet = false;
m_strcameraName = "";
nLastCheckAnalysisyThreadIdx = 0;
m_pChannelFuntion = &m_AnalysisyConfig.checkFunction;
m_pbaseCheckFunction = &m_AnalysisyConfig.baseFunction;
m_nConfigIdx = -1;
m_pdetlog = std::make_shared<DetLog>();
m_pCommonAnalysisyConfig = NULL;
m_imageResultJudge.SetAnalysisyConfig(&m_AnalysisyConfig);
m_strRootPath_MergeImg = "/home/aidlux/BOE/FOG/MergeImg/";
CheckUtil::CreateDir(m_strRootPath_MergeImg);
// m_pQX_Merge_Analysis = QX_Merge_Analysis::GetInstance();
}
CameraCheckAnalysisy::~CameraCheckAnalysisy()
{
}
int CameraCheckAnalysisy::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 CameraCheckAnalysisy::WaitDetImg()
{
std::unique_lock<std::mutex> lk(mtx_WaiteImg);
cond_WaiteImg.wait(lk, [this]()
{ return m_bHaveImgeDet; });
lk.unlock();
return 0;
}
int CameraCheckAnalysisy::Detect_Pre()
{
//==========解密图片
long ts = CheckUtil::getcurTime();
std::string strlog;
std::string strSN;
std::string strBasic;
strSN = m_pCheck_Result->productBaseResult->strproductName;
strBasic = ">>" + strSN + " cam:" + m_strcameraName;
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s ==================start",
strBasic.c_str());
// printf( "%s ==================Detect_Pre start\n", strBasic.c_str());
std::shared_ptr<ImageAllResult> L255 = m_pCheck_Result->GetL255DetImg();
if (L255 == NULL || L255->result->in_shareImage->img.empty())
{
if (L255 && L255->result->in_shareImage->img.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --L255 Img is empty ", strBasic.c_str());
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --L255 NULL ", strBasic.c_str());
}
return 1;
}
ChannelCheckFunction *pFuntion_L255 = GetChannelFuntion("L255");
if (!pFuntion_L255)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --L255 function is error ", strBasic.c_str());
return 1;
}
// 用L255 检测图片边缘
int re = ImgEdge(L255, pFuntion_L255);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --ImgEdge error ", strBasic.c_str());
return 1;
}
if (m_pCheck_Result->cameraBaseResult->pEdgeDetResult->nresult != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --ImgEdge result error = %d ",
strBasic.c_str(), m_pCheck_Result->cameraBaseResult->pEdgeDetResult->nresult);
return 1;
}
// 如果是 边缘检测模式,则停止后面检测,直接退出
if (L255->result->in_shareImage->Det_Mode == DET_MODE_EDGE)
{
return 9;
}
cv::Rect Det_CropRoi = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->cutRoi;
if (!CheckUtil::RoiInImg(Det_CropRoi, L255->result->in_shareImage->img))
{
return 0;
}
cv::Mat L255CutImg = L255->result->in_shareImage->img(Det_CropRoi).clone();
re = Det_MarkLine(L255CutImg, L255, &m_pbaseCheckFunction->markLine);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --Det_MarkLine error ", strBasic.c_str());
}
if (DET_MODE_MarkLine == L255->result->in_shareImage->Det_Mode)
{
return 1;
}
re = preDet_ZF(L255CutImg, L255);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --preDet_ZF error ", strBasic.c_str());
}
if (DET_MODE_ZF == L255->result->in_shareImage->Det_Mode)
{
return 1;
}
long te = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "Detect_Pre", "==================End time %ld ms ", te - ts);
re = preDet_BQ(L255CutImg, L255);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "%s --preDet_BQ error ", strBasic.c_str());
}
// getchar();
// return 1;
// printf("Cam image channle %s ==================send start \n", pL255ImageResult->strChannel.c_str());
// getchar();
return 0;
}
// 对该相机下的每一张图片进行处理
int CameraCheckAnalysisy::Detect_Images()
{
std::string strlog;
std::string strSN;
std::string strBasic;
strSN = m_pCheck_Result->productBaseResult->strproductName;
strBasic = ">>" + strSN + " cam:" + m_strcameraName;
m_pdetlog->AddCheckstr(PrintLevel_0, "Detect_Images", "Cam %s ==================start", strBasic.c_str());
// // 循环处理每个图片
bool bcomplete = false;
long time_No_CheckAnalysisy = 30 * 1000;
long ts = CheckUtil::getcurTime();
while (!bcomplete)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
ImgCheckBase *pImgCheckAnalysisy = NULL;
long t1 = CheckUtil::getcurTime();
// 拿到计算资源
while (true)
{
pImgCheckAnalysisy = GetDealResult(-1);
if (pImgCheckAnalysisy != NULL)
{
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(20)); //
long t2 = CheckUtil::getcurTime();
// 如果 超过秒XX都没有拿到处理资源则直接退出
if (t2 - t1 > time_No_CheckAnalysisy)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Images", "Error %ld ms No pImgCheckAnalysisy", time_No_CheckAnalysisy);
break;
}
}
// 没有分析检测资源,直接退出
if (pImgCheckAnalysisy == NULL)
{
continue;
}
UpdateConfigStatus();
// 1、把每张图都进行AI 推理 获得 blob 结果
std::shared_ptr<ImageAllResult> pImageResult = m_pCheck_Result->GetNoDetImg();
bool bHaveNotdetImg = false;
// 没有未检测的图片了。
if (pImageResult)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Images", "strSN %s channel %s send det %s",
strSN.c_str(), pImageResult->strChannel.c_str(), CheckUtil::getCurTimeHMS().c_str());
bHaveNotdetImg = true;
{
pImgCheckAnalysisy->SetDataRun_SharePtr(pImageResult);
}
}
else
{
// printf("Cam Detect_Images %s =======nnnnnnnnnnnnnnnnnnnnnnnnnnn===========send end \n", strBasic.c_str());
// 图片都已经送完了。
if (m_pCheck_Result->getImgPushComplate())
{
// printf("Cam Detect_Images %s ===========PushComplate=======send end \n", strBasic.c_str());
// 没有图在进行 检测了。
bool bhavedet = false;
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
{
if (CHECK_THREAD_STATUS_IDLE != m_pImgCheckAnalysisy[i]->GetStatus())
{
bhavedet = true;
break;
}
}
// printf("Cam Detect_Images %s ==================bhavedet %d\n", strBasic.c_str(), bhavedet);
if (!bhavedet)
{
bcomplete = true;
}
}
else
{
// printf("Cam Detect_Images %s ==================No send end\n", strBasic.c_str());
}
}
}
long te = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "Detect_Images", "Cam %s =====ALL image det complate time %ld ms=============End", strBasic.c_str(), te - ts);
// getchar();
// printf("Cam %s =====ALL image det complate time %ld ms=============End \n", strBasic.c_str(), te - ts);
return 0;
}
int CameraCheckAnalysisy::ResultParamJudge()
{
//==================================================
//======= 适用于 单相机或多相机,每个相机之间的图相互没关系。
//=======
//=======
//=======
//==================================================
std::string strSN;
std::string strBasic;
strSN = m_pCheck_Result->productBaseResult->strproductName;
strBasic = ">>" + strSN + " cam:" + m_strcameraName;
m_pdetlog->AddCheckstr(PrintLevel_0, "ResultParamJudge", "Cam %s ==================start", strBasic.c_str());
std::string strlog;
long ts = CheckUtil::getcurTime();
int ImageNum = m_pCheck_Result->ImageALLDetResultList.size();
if (ImageNum <= 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "Error ImageNum <=0");
return 1;
}
// 如果 参数是空,直接返回。
if (m_pCommonAnalysisyConfig == NULL)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "Error m_pCommonAnalysisyConfig == NULL");
return 1;
}
int regionNum = m_pCommonAnalysisyConfig->regionConfigArr.size();
if (regionNum <= 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "Error Config region num = 0");
}
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "==================start image Num %d region num %d %s",
ImageNum, regionNum, CheckUtil::getCurTimeHMS().c_str());
m_pQX_Merge_Analysis = m_pCheck_Result->productBaseResult->pQX_Merge_Analysis;
m_pQX_Merge_Analysis->SetbaseCheckFunction(m_strcameraName, m_pChannelFuntion, m_pbaseCheckFunction);
m_pQX_Merge_Analysis->setSendStatus(m_strcameraName, QX_Merge_Analysis::RUN_STATUS_NULL);
m_imageResultJudge.UpdateMergedet(m_pCheck_Result);
// 对每个图片通道进行单独分析
for (int imgidx = 0; imgidx < ImageNum; imgidx++)
{
long t1 = CheckUtil::getcurTime();
int re = m_imageResultJudge.ResultJudge(m_pCheck_Result->ImageALLDetResultList.at(imgidx));
long t2 = CheckUtil::getcurTime();
}
m_pQX_Merge_Analysis->setSendStatus(m_strcameraName, QX_Merge_Analysis::RUN_STATUS_READY);
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "===============QX_Merge_Analysis===start %s", CheckUtil::getCurTimeHMS().c_str());
// 等待所有 个数 和距离的分析完成。
m_pQX_Merge_Analysis->waitComplete();
for (auto log : m_pQX_Merge_Analysis->m_pMergedetlog->logList)
{
m_pdetlog->logList.push_back(log);
}
QX_Analysis_Result_List *ptemre;
m_pQX_Merge_Analysis->GetReusult(ptemre);
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "===============QX_Merge_Analysis===end %s", CheckUtil::getCurTimeHMS().c_str());
// 对每个图片通道进行单独分析
for (int imgidx = 0; imgidx < ImageNum; imgidx++)
{
long t1 = CheckUtil::getcurTime();
int re = m_imageResultJudge.MergeResult(m_pCheck_Result->ImageALLDetResultList.at(imgidx), ptemre);
long t2 = CheckUtil::getcurTime();
#ifdef AI_Time
m_imageResultJudge.DrawResult(m_pCheck_Result->ImageALLDetResultList.at(imgidx));
#endif
long t3 = CheckUtil::getcurTime();
// m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", " det time %ld ms judge %ld draw %ld", t3 - t1, t2 - t1, t3 - t2);
// 把结果转成 json 保存。 用以复测
// std::shared_ptr<CheckResult> m_CheckResult_shareP = m_pCheck_Result->ImageALLDetResultList.at(imgidx)->result;
// m_CheckResult_shareP->strResultJson = m_CheckResultJson.GetResultString(m_pCheck_Result->ImageALLDetResultList.at(imgidx)->pDetResult);
}
long te = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "==================End time %ld ms ", te - ts);
// m_pdetlog->printLog(m_strcameraName);
return 0;
}
int CameraCheckAnalysisy::MergeResultAnalysisy()
{
return 0;
}
int CameraCheckAnalysisy::UpdateConfigStatus()
{
std::string strBasic;
for (int i = 0; i < m_pCheck_Result->ImageALLDetResultList.size(); i++)
{
std::shared_ptr<ImageAllResult> pImageResult = m_pCheck_Result->ImageALLDetResultList.at(i);
if (pImageResult->config_update.bUpdate)
{
continue;
}
std::string strChannel = m_pCheck_Result->ImageALLDetResultList.at(i)->strChannel;
ChannelCheckFunction *pFuntion = GetChannelFuntion(strChannel);
if (pFuntion != NULL)
{
pImageResult->config_update.wait_UP = pFuntion->function.f_UseUpQX.bOpen;
}
bool bUseDpResult = false;
if (pFuntion != NULL)
{
// 亮点检测 开启
if (pFuntion->function.f_LDConfig.bOpen)
{
// 需要dp
bUseDpResult = pFuntion->function.f_LDConfig.bUseDP;
}
if (pFuntion->function.f_AIQX.bPOLToWhitePOL && pFuntion->function.f_AIQX.b127WhitePOl_UseDP)
{
bUseDpResult = true;
}
}
pImageResult->config_update.wait_DP = bUseDpResult;
pImageResult->config_update.bUpdate = true;
m_pdetlog->AddCheckstr(PrintLevel_2, "config_update", " %s wait_UP %d wait_DP %d", pImageResult->strBaseInfo.c_str(), pImageResult->config_update.wait_UP, pImageResult->config_update.wait_DP);
}
return 0;
}
int CameraCheckAnalysisy::ResultParamJudge_New()
{
return 0;
}
int CameraCheckAnalysisy::ImgEdge(std::shared_ptr<ImageAllResult> L255, ChannelCheckFunction *pFuntion_L255)
{
long ts = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, "ImgEdge", "==================start %s ", m_strcameraName.c_str());
Function_EdgeROI *pEdgeROI;
pEdgeROI = &pFuntion_L255->function.f_EdgeROI;
// pEdgeROI->print("pEdgeROI");
Function_Image_Align *pAlign;
pAlign = &pFuntion_L255->function.f_Image_Align;
Edge_Search::DetConfigResult detConfigResult;
detConfigResult.pEdgeROI = pEdgeROI;
detConfigResult.pAlign = pAlign;
detConfigResult.strCamName = m_strcameraName;
detConfigResult.pdetlog = m_pdetlog;
if (L255->result->in_shareImage->Det_Mode == DET_MODE_EDGE)
{
detConfigResult.bMode_Edge_test = true;
}
detConfigResult.bDebugsaveImg = L255->result->in_shareImage->bDebugsaveImg;
m_pCheck_Result->cameraBaseResult->pEdgeDetResult = std::make_shared<EdgeDetResult>();
int re = m_Edge_Search.Detect(L255->result->in_shareImage->img, &detConfigResult, m_pCheck_Result->cameraBaseResult->pEdgeDetResult);
long te = CheckUtil::getcurTime();
if (!m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask_Src.empty())
{
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(40, 40));
// 对掩膜图像进行膨胀
cv::dilate(m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask_Src,
m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask_Src, kernel);
cv::Rect Det_CropRoi = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->cutRoi;
if (CheckUtil::RoiInImg(Det_CropRoi, m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask_Src))
{
m_pCheck_Result->cameraBaseResult->pEdgeDetResult->edge_cutMask =
~m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask_Src(Det_CropRoi).clone();
if (L255->result->in_shareImage->bDebugsaveImg)
{
cv::imwrite("edge_cutMask.png", m_pCheck_Result->cameraBaseResult->pEdgeDetResult->edge_cutMask);
cv::imwrite("edge_shieldMask_Src.png", m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask_Src);
}
}
}
m_pdetlog->AddCheckstr(PrintLevel_1, "ImgEdge", "==================End re = %d time %ld ms edge qx roi %ld ",
re, te - ts, m_pCheck_Result->cameraBaseResult->pEdgeDetResult->pEdgeDet_roiList->size());
// getchar();
return re;
}
int CameraCheckAnalysisy::Det_MarkLine(const cv::Mat &L255CutImg, std::shared_ptr<ImageAllResult> L255, Base_Function_MarkLine *pFuntion)
{
m_pCheck_Result->cameraBaseResult->pMarkLineResult = std::make_shared<MakeLine_Result>();
if (pFuntion && !pFuntion->bOpen)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Det_MarkLine", "Error pFuntion == NULL or bOpen == false");
return 0;
}
std::shared_ptr<MakeLine_Result> pMarkLineResult = m_pCheck_Result->cameraBaseResult->pMarkLineResult; // MarkLine检测结果
cv::Rect Det_CropRoi = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->cutRoi;
AI_Mark_Det::DetConfigResult detresult;
detresult.strCamName = m_strcameraName;
detresult.searchroi = pFuntion->searchRoi;
detresult.bDebugsaveimg = L255->result->in_shareImage->bDebugsaveImg;
detresult.pdetlog = m_pdetlog;
if (DET_MODE_MarkLine == L255->result->in_shareImage->Det_Mode)
{
detresult.bDetSaveImg = true;
}
detresult.searchroi.x -= Det_CropRoi.x;
detresult.searchroi.y -= Det_CropRoi.y;
// if (true)
// {
// detresult.bsaveprocessimg = true;
// }
cv::Mat detImg_mask = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask;
cv::Mat detimg = L255CutImg;
int re = m_MarkDet.Detect(detimg, &detresult);
if (re != 0)
{
return re;
}
if (detresult.nresult != 0)
{
return -1;
}
// printf("-------------------22222 \n");
// detresult.markRoi.x -= Det_CropRoi.x;
// detresult.markRoi.y -= Det_CropRoi.y;
int sheild_h = detresult.markRoi.height;
if (sheild_h < pFuntion->x_sheild_width)
{
sheild_h = pFuntion->x_sheild_width;
}
int sheild_w = detresult.markRoi.width;
if (sheild_w < pFuntion->y_sheild_width)
{
sheild_w = pFuntion->y_sheild_width;
}
int pc_x = detresult.markRoi.x + detresult.markRoi.width * 0.5;
int pc_y = detresult.markRoi.y + detresult.markRoi.height * 0.5;
cv::Rect sheildRoi;
sheildRoi.x = pc_x - sheild_w * .5;
sheildRoi.y = pc_y - sheild_h * .5;
sheildRoi.width = sheild_w;
sheildRoi.height = sheild_h;
if (CheckUtil::RoiInImg(sheildRoi, detImg_mask))
{
detImg_mask(sheildRoi).setTo(255);
}
cv::Rect sheild_x_roi;
sheild_x_roi.x = 0;
sheild_x_roi.y = pc_y - sheild_h * .5;
sheild_x_roi.width = detImg_mask.cols;
sheild_x_roi.height = sheild_h;
pMarkLineResult->markLine_Roi_X = sheild_x_roi;
if (CheckUtil::RoiInImg(sheild_x_roi, detImg_mask) && pFuntion->bUse_Roi_Sheild)
{
detImg_mask(sheild_x_roi).setTo(255);
}
cv::Rect sheild_y_roi;
sheild_y_roi.x = pc_x - sheild_w * 0.5;
sheild_y_roi.y = 0;
sheild_y_roi.width = sheild_w;
sheild_y_roi.height = detImg_mask.rows;
pMarkLineResult->markLine_Roi_Y = sheild_y_roi;
if (CheckUtil::RoiInImg(sheild_y_roi, detImg_mask) && pFuntion->bUse_Roi_Sheild)
{
detImg_mask(sheild_y_roi).setTo(255);
}
pMarkLineResult->nresult = 1;
return 0;
}
int BQ_Det(cv::Mat detimg, shared_ptr<BQ_Result> pBQ_Result)
{
cv::resize(detimg, detimg, cv::Size(), 0.1, 0.1);
cv::Mat detimg_bin;
cv::GaussianBlur(detimg, detimg, cv::Size(3, 3), 0);
cv::threshold(detimg, detimg_bin, 25, 255, cv::THRESH_BINARY_INV);
vector<vector<Point>> contours;
cv::Rect result_roi;
findContours(detimg_bin, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 找到最大轮廓
double max_area = 0;
int max_contour_index = 0;
for (int i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > max_area)
{
max_area = area;
max_contour_index = i;
}
}
if (max_contour_index < 0)
{
cerr << "No contours found!" << endl;
return 7;
}
cv::Rect r_rect = boundingRect(contours[max_contour_index]);
cv::Rect rect(r_rect.x*10, r_rect.y*10, r_rect.width*10, r_rect.height*10);
if (max_contour_index >= 0)
{
pBQ_Result->pBQ_roiList.push_back(rect);
}
return 0;
}
int CameraCheckAnalysisy::preDet_ZF(const cv::Mat &L255CutImg, std::shared_ptr<ImageAllResult> L255)
{
long ts = CheckUtil::getcurTime();
m_pCheck_Result->cameraBaseResult->pZF_Result = std::make_shared<ZF_Result>();
m_pCheck_Result->cameraBaseResult->pZF_Result->bShield_ZF = m_AnalysisyConfig.commonCheckConfig.baseConfig.bShield_ZF;
cv::Rect Det_CropRoi = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->cutRoi;
AI_ZF_Det::DetConfigResult detresult;
detresult.strCamName = m_strcameraName;
detresult.bDebugsaveimg = L255->result->in_shareImage->bDebugsaveImg;
detresult.pdetlog = m_pdetlog;
if (DET_MODE_ZF == L255->result->in_shareImage->Det_Mode)
{
detresult.bDetSaveImg = true;
}
detresult.pZF_Result = m_pCheck_Result->cameraBaseResult->pZF_Result;
cv::Mat detimg = L255CutImg;
int re = m_ZF_Det.Detect(detimg, &detresult);
if (re != 0)
{
return re;
}
// 如果要屏蔽字符
if (m_pCheck_Result->cameraBaseResult->pZF_Result->bShield_ZF)
{
m_pdetlog->AddCheckstr(PrintLevel_2, "preDet_ZF", "shieldZF is Open");
cv::Mat detImg_mask = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask;
for (int i = 0; i < m_pCheck_Result->cameraBaseResult->pZF_Result->pZF_roiList.size(); i++)
{
cv::Rect boundingRect = m_pCheck_Result->cameraBaseResult->pZF_Result->pZF_roiList.at(i);
detImg_mask(boundingRect).setTo(255);
}
if (L255->result->in_shareImage->bDebugsaveImg)
{
cv::imwrite("sheildImg.png", m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask);
}
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_2, "preDet_ZF", "shieldZF is false");
}
std::shared_ptr<ZF_Result> pZF_Result = m_pCheck_Result->cameraBaseResult->pZF_Result; // zf 检测结果
pZF_Result->ZF_centerPoint.erase(pZF_Result->ZF_centerPoint.begin(), pZF_Result->ZF_centerPoint.end());
for (int i = 0; i < pZF_Result->pZF_roiList.size(); i++)
{
// 获取当前轮廓的边界矩形
cv::Rect boundingRect = pZF_Result->pZF_roiList.at(i);
cv::Point p;
p.x = boundingRect.x + boundingRect.width * 0.5f;
p.y = boundingRect.y + boundingRect.height * 0.5f;
// printf("--- zf %d %d %d %d \n", boundingRect.x, boundingRect.y, boundingRect.width, boundingRect.height);
pZF_Result->ZF_centerPoint.push_back(p);
}
if (L255->result->in_shareImage->bDebugsaveImg)
{
cv::Mat showimg = detimg.clone();
for (int i = 0; i < m_pCheck_Result->cameraBaseResult->pZF_Result->pZF_roiList.size(); i++)
{
cv::Rect boundingRect = m_pCheck_Result->cameraBaseResult->pZF_Result->pZF_roiList.at(i);
cv::rectangle(showimg, boundingRect, cv::Scalar(200), 5);
}
cv::imwrite("zf_result.png", showimg);
}
m_pCheck_Result->cameraBaseResult->pZF_Result->nresult = 0;
long te = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, "preDet_ZF", "==================End zf num %ld re = %d time %ld ms ", m_pCheck_Result->cameraBaseResult->pZF_Result->pZF_roiList.size(), re, te - ts);
return 0;
}
int CameraCheckAnalysisy::preDet_BQ(const cv::Mat &L255CutImg, std::shared_ptr<ImageAllResult> L255)
{
long ts = CheckUtil::getcurTime();
m_pCheck_Result->cameraBaseResult->pBQ_Result = std::make_shared<BQ_Result>();
m_pCheck_Result->cameraBaseResult->pBQ_Result->bShield_BQ = m_AnalysisyConfig.commonCheckConfig.baseConfig.bShield_BQ;
cv::Rect Det_CropRoi = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->cutRoi;
AI_BQ_Det::DetConfigResult detresult;
detresult.strCamName = m_strcameraName;
detresult.bDebugsaveimg = L255->result->in_shareImage->bDebugsaveImg;
detresult.pdetlog = m_pdetlog;
if (DET_MODE_ZF == L255->result->in_shareImage->Det_Mode)
{
detresult.bDetSaveImg = true;
}
detresult.pBQ_Result = m_pCheck_Result->cameraBaseResult->pBQ_Result;
cv::Mat detimg = L255CutImg;
int re = m_BQ_Det.Detect(detimg, &detresult);
if (re != 0)
{
return re;
}
// 如果要屏蔽标签
if (m_pCheck_Result->cameraBaseResult->pBQ_Result->bShield_BQ)
{
m_pdetlog->AddCheckstr(PrintLevel_2, "preDet_BQ", "shieldBQ is Open");
cv::Mat detImg_mask = m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask;
for (int i = 0; i < m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.size(); i++)
{
cv::Rect boundingRect = m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.at(i);
boundingRect.x -= 5;
boundingRect.y -= 5;
boundingRect.width += 10;
boundingRect.height += 10;
detImg_mask(boundingRect).setTo(255);
}
if (L255->result->in_shareImage->bDebugsaveImg)
{
cv::imwrite("sheildImg.png", m_pCheck_Result->cameraBaseResult->pEdgeDetResult->shieldMask);
}
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_2, "preDet_BQ", "shieldBQ is false");
}
std::shared_ptr<BQ_Result> pBQ_Result = m_pCheck_Result->cameraBaseResult->pBQ_Result; // BQ 检测结果
pBQ_Result->BQ_centerPoint.erase(pBQ_Result->BQ_centerPoint.begin(), pBQ_Result->BQ_centerPoint.end());
for (int i = 0; i < pBQ_Result->pBQ_roiList.size(); i++)
{
// 获取当前轮廓的边界矩形
cv::Rect boundingRect = pBQ_Result->pBQ_roiList.at(i);
cv::Point p;
p.x = boundingRect.x + boundingRect.width * 0.5f;
p.y = boundingRect.y + boundingRect.height * 0.5f;
// printf("--- zf %d %d %d %d \n", boundingRect.x, boundingRect.y, boundingRect.width, boundingRect.height);
pBQ_Result->BQ_centerPoint.push_back(p);
}
if (L255->result->in_shareImage->bDebugsaveImg)
{
cv::Mat showimg = detimg.clone();
for (int i = 0; i < m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.size(); i++)
{
cv::Rect boundingRect = m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.at(i);
cv::rectangle(showimg, boundingRect, cv::Scalar(200), 5);
}
cv::imwrite("bq_result.png", showimg);
}
m_pCheck_Result->cameraBaseResult->pBQ_Result->nresult = 0;
long te = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, "preDet_BQ", "==================End bq num %ld re = %d time %ld ms ", m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.size(), re, te - ts);
return 0;
}
int CameraCheckAnalysisy::Init(std::string strcameraName)
{
m_strcameraName = strcameraName;
printf("CameraCheckAnalysisy::Init start \n");
SetNewConfig();
int re = 0;
re = InitCheckAnalysisy();
if (CHECK_OK != re)
{
printf("InitCheckAnalysisy error\n");
return -1;
}
re = InitRun();
if (CHECK_OK != re)
{
printf("InitRun error\n");
m_nErrorCode = re;
return m_nErrorCode;
}
// m_pQX_Merge_Analysis->SetbaseCheckFunction(m_strcameraName, m_pChannelFuntion, m_pbaseCheckFunction);
printf("CameraCheckAnalysisy::Init end \n");
return 0;
}
int CameraCheckAnalysisy::StartCheck(std::shared_ptr<CameraResult> pCamera_Check_Result)
{
if (m_bHaveImgeDet)
{
return -1;
}
{
std::lock_guard<std::mutex> lock(mtx_WaiteImg);
m_pCheck_Result = pCamera_Check_Result;
if (m_pCheck_Result->bJson)
{
// 如果是 复测 直接进入 参数判断阶段。
m_pCheck_Result->SetCheckStep(Check_Step_ResultParamJudg); // 进入预处理阶段
}
else
{
// m_pCheck_Result->SetCheckStep(Check_Step_PreDet); // 进入预处理阶段
}
m_bHaveImgeDet = true;
m_pdetlog = m_pCheck_Result->detlog;
m_pdetlog->AddCheckstr(PrintLevel_0, "Camera StartCheck", "==================start %s", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
}
cond_WaiteImg.notify_all();
return 0;
}
int CameraCheckAnalysisy::StartThread()
{
m_bExit = false;
// 开启检测线程
ptr_thread_Run = std::make_shared<std::thread>(std::bind(&CameraCheckAnalysisy::Run, this));
return 0;
}
int CameraCheckAnalysisy::StopThread()
{
m_bExit = true;
if (ptr_thread_Run != nullptr)
{
if (ptr_thread_Run->joinable())
{
ptr_thread_Run->join();
}
}
return 0;
}
int CameraCheckAnalysisy::InitRun()
{
int re;
re = StartThread();
if (CHECK_OK != re)
{
return re;
}
m_bInitSucc = true;
// 检测前更新参数
SetNewConfig();
return 0;
}
int CameraCheckAnalysisy::InitCheckAnalysisy()
{
int re = 0;
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
{
RunInfoST RunConfig;
RunConfig.nThreadIdx = i;
m_pImgCheckAnalysisy[i] = ImgCheckBase::GetInstance();
re = m_pImgCheckAnalysisy[i]->UpdateConfig((void *)&RunConfig, CHECK_CONFIG_Run);
if (re != 0)
{
printf("UpdateConfig %d Fail %s\n", CHECK_CONFIG_Run, m_pImgCheckAnalysisy[i]->GetErrorInfo().c_str());
return re;
}
re = m_pImgCheckAnalysisy[i]->UpdateConfig((void *)m_pConfig.get(), CHECK_CONFIG_Module);
if (re != 0)
{
printf("UpdateConfig %d Fail %s\n", CHECK_CONFIG_Module, m_pImgCheckAnalysisy[i]->GetErrorInfo().c_str());
return re;
}
re = m_pImgCheckAnalysisy[i]->RunStart();
if (re != 0)
{
printf("cami %s RunStart Fail ==%d\n", m_strcameraName.c_str(), re);
return re;
}
printf(">>>>cami %s InitCheckAnalysisy: ImgCheckThread %d / %d Start Succ \n", m_strcameraName.c_str(), i, IMGCHECKANALYSISY_NUM);
if (re != 0)
{
return re;
}
}
return 0;
}
int CameraCheckAnalysisy::CheckImgRun()
{
std::string strCameraName = m_pCheck_Result->cameraBaseResult->strCameraName;
int re = 0;
Check_Step curcheckStep = m_pCheck_Result->GetCheckStep();
m_pdetlog->AddCheckstr(PrintLevel_1, "CheckImgRun", "Cam %s ------Product_Off_X_mm %f ",
m_strcameraName.c_str(), m_AnalysisyConfig.commonCheckConfig.baseConfig.fProduct_Off_X_mm);
// 如果是未检测状态,则开始预处理
if (curcheckStep == Check_Step_NODet)
{
std::string strconfigchannel = m_pbaseCheckFunction->edgeChannel.strChannel;
if (strconfigchannel == "")
{
strconfigchannel = "L255";
}
if (m_pCheck_Result->IsHaveL255())
{
curcheckStep = Check_Step_PreDet; // 进入到预图片检测阶段
m_pCheck_Result->SetCheckStep(curcheckStep);
m_pdetlog->AddCheckstr(PrintLevel_1, "CheckImgRun", "cam %s : Have L255 Img Start Check_Step_PreDet", strCameraName.c_str());
}
else
{
if (!m_pCheck_Result->getImgPushComplate())
{
return 1;
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "Error cam %s : NO L255 Img", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
curcheckStep = Check_Step_ImgeDet_End; // 图片送图完成, 没有 L255 强制 结束
m_pCheck_Result->SetCheckStep(curcheckStep);
}
}
}
m_pdetlog->AddCheckstr(PrintLevel_1, "CheckImgRun", "Cam %s ------------curcheckStep:%d ",
m_strcameraName.c_str(), curcheckStep);
// getchar();
// 检测前更新参数
SetNewConfig();
// 预处理
if (curcheckStep == Check_Step_PreDet)
{
// m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_PreDet", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
int re = Detect_Pre();
if (re != 0)
{
// 图片 送图没有完成,则继续等待。
if (!m_pCheck_Result->getImgPushComplate())
{
return 1;
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "Error cam %s : Detect_Pre error", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
curcheckStep = Check_Step_ImgeDet_End; // Detect_Pre error
m_pCheck_Result->SetCheckStep(curcheckStep);
}
}
else
{
if (re == 9)
{
curcheckStep = Check_Step_ImgeDet_End; // 边缘检测模式,直接退出
m_pCheck_Result->SetCheckStep(curcheckStep);
}
else
{
curcheckStep = Check_Step_ImgeDet; // 进入检测
m_pCheck_Result->SetCheckStep(curcheckStep);
}
}
}
// 检测每张图片
if (curcheckStep == Check_Step_ImgeDet)
{
// m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_ImgeDet", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
// 检测每张图片
re = Detect_Images();
if (re != 0)
{
// 图片 送图没有完成,则继续等待。
if (!m_pCheck_Result->getImgPushComplate())
{
return 1;
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "Error cam %s : Detect_Images error", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
curcheckStep = Check_Step_ImgeDet_End; // Detect_Images error
m_pCheck_Result->SetCheckStep(curcheckStep);
}
}
else
{
curcheckStep = Check_Step_ResultParamJudg; // 进入到测结果进行参数判断
m_pCheck_Result->SetCheckStep(curcheckStep);
}
}
// 对检测结果进行参数判断判断是否NG.
if (curcheckStep == Check_Step_ResultParamJudg)
{
// m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_ResultParamJudg", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
// 检测每张图片
re = ResultParamJudge();
// 如果有异常
if (re != 0)
{
// 图片 送图没有完成,则继续等待。
if (!m_pCheck_Result->getImgPushComplate())
{
return 1;
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "Error cam %s : ResultParamJudge error", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
curcheckStep = Check_Step_ImgeDet_End; // ResultParamJudge error
m_pCheck_Result->SetCheckStep(curcheckStep);
}
}
else
{
curcheckStep = Check_Step_ImgeDet_End; // 检测结束
m_pCheck_Result->SetCheckStep(curcheckStep);
}
}
// 图片检测完成
if (curcheckStep == Check_Step_ImgeDet_End)
{
// m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_ImgeDet_End", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
// 所有图片都送完了。
if (m_pCheck_Result->getImgPushComplate())
{
curcheckStep = Check_Step_Complete;
m_pCheck_Result->SetCheckStep(curcheckStep);
}
else
{
// printf("========came %s wait img send end \n", m_strcameraName.c_str());
}
}
// 处理完成
if (curcheckStep == Check_Step_Complete)
{
long tend = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_Complete", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
std::string strTimg = CheckUtil::getCurTimeHMS();
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "========came %s Check ALL end time %ld ms %s",
m_pCheck_Result->cameraBaseResult->strCameraName.c_str(), tend - m_pCheck_Result->time_start, strTimg.c_str());
InsertCameraLog();
ngImgSave();
std::lock_guard<std::mutex> lock(mtx_WaiteImg);
m_bHaveImgeDet = false;
m_pCheck_Result.reset();
}
// m_pdetlog->printLog(m_strcameraName);
return 0;
}
int CameraCheckAnalysisy::Run()
{
while (!m_bExit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
WaitDetImg();
int re = CheckImgRun();
}
return 0;
}
int CameraCheckAnalysisy::ImgEdge(cv::Mat img, cv::Mat &detMaskImg, cv::Rect &roi, int productIdx)
{
int re = 0;
return re;
}
int CameraCheckAnalysisy::InsertCameraLog()
{
int ImageNum = m_pCheck_Result->ImageALLDetResultList.size();
for (int imgidx = 0; imgidx < ImageNum; imgidx++)
{
std::shared_ptr<ImageAllResult> pImageResult = m_pCheck_Result->ImageALLDetResultList.at(imgidx);
std::shared_ptr<CheckResult> m_CheckResult_shareP = pImageResult->result; // 返回结果
// 1、把图片的相关日志 写到 返回 日志中。
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pImageResult->detlog->logList.begin(), pImageResult->detlog->logList.end());
std::string str = "";
char buffer[256];
// 2、把缺陷信息 写的 返回日志中。
{
std::shared_ptr<One_Image_CheckResult_> pDetResult = pImageResult->pDetResult; // 检测结果
int qxNum = 0;
if (pDetResult->pQx_ErrorList)
{
qxNum = pDetResult->pQx_ErrorList->size();
{
sprintf(buffer, " =====================NG num %d=============================", pImageResult->NG_num);
str = buffer;
m_CheckResult_shareP->det_LogList.push_back(str);
}
for (int qxidx = 0; qxidx < qxNum; qxidx++)
{
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
if (QX_info->result == QX_RESULT_TYPE_NG)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
}
}
{
sprintf(buffer, " =====================YS num %d=============================", pImageResult->YS_num);
str = buffer;
m_CheckResult_shareP->det_LogList.push_back(str);
}
for (int qxidx = 0; qxidx < qxNum; qxidx++)
{
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
if (QX_info->result == QX_RESULT_TYPE_YS)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
}
}
{
sprintf(buffer, " =====================OK num %d=============================", pImageResult->Ok_num);
str = buffer;
m_CheckResult_shareP->det_LogList.push_back(str);
}
for (int qxidx = 0; qxidx < qxNum; qxidx++)
{
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
if (QX_info->result == QX_RESULT_TYPE_OK)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
}
}
{
sprintf(buffer, " =====================NO Judge num %d=============================", pImageResult->NoJudge_num);
str = buffer;
m_CheckResult_shareP->det_LogList.push_back(str);
}
for (int qxidx = 0; qxidx < qxNum; qxidx++)
{
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
if (QX_info->result == QX_RESULT_TYPE_NoJduge)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
}
}
}
}
{
sprintf(buffer, " =====================Cam Log =============================");
str = buffer;
m_CheckResult_shareP->det_LogList.push_back(str);
}
// 3、把相机的日志 写到 返回日志中。
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
m_pCheck_Result->detlog->logList.begin(), m_pCheck_Result->detlog->logList.end());
{
sprintf(buffer, " =====================Product Log =============================");
str = buffer;
m_CheckResult_shareP->det_LogList.push_back(str);
}
// 4、把产品相关日志 写到 返回日志中。
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
m_pCheck_Result->productBaseResult->detlog->logList.begin(), m_pCheck_Result->productBaseResult->detlog->logList.end());
}
return 0;
}
int writeLog(std::string strSavePath, std::vector<std::string> logList)
{
std::string str = strSavePath + ".txt";
// 打开文件
std::ofstream outFile(str);
// 检查文件是否成功打开
if (!outFile)
{
std::cerr << "Failed to open file." << std::endl;
return 1;
}
// 将vector中的内容写入文件
for (const auto &str : logList)
{
// printf("%s \n",str.c_str());
outFile << str << std::endl;
}
// 关闭文件
outFile.close();
return 0;
}
static std::string SanitizePathComponent(const std::string& input) {
std::string result;
result.reserve(input.size());
for (char ch : input) {
// 只允许字母、数字、下划线、点、短横线,其余替换为下划线
if (isalnum(static_cast<unsigned char>(ch)) || ch == '_' || ch == '.' || ch == '-') {
result.push_back(ch);
} else {
result.push_back('_');
}
}
// 防止相对路径伪装(如 ".", ".."
if (result == "." || result == "..") {
result = "_";
}
return result;
}
int CameraCheckAnalysisy::ngImgSave() {
// 拷贝智能指针,保证在异步任务中引用计数有效
auto result_copy = m_pCheck_Result;
std::string save_path_root = "/home/aidlux/BOE/FOG/cloud/";
auto task = std::async(std::launch::async, [result_copy, save_path_root]() {
try {
if (!result_copy) return;
// ---------- 目录清理(加锁防止并发删除)----------
{
static std::mutex cleanup_mutex; // 静态锁,所有实例共享
std::lock_guard<std::mutex> lock(cleanup_mutex);
DIR* dir = opendir(save_path_root.c_str());
if (dir) {
std::vector<std::pair<std::string, time_t>> dirs;
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
std::string name = entry->d_name;
if (name == "." || name == "..") continue;
std::string full_path = save_path_root + name;
struct stat st;
if (stat(full_path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
struct stat lst;
if (lstat(full_path.c_str(), &lst) == 0 && !S_ISLNK(lst.st_mode)) {
dirs.emplace_back(full_path, st.st_mtime);
}
}
}
closedir(dir);
if (dirs.size() > 100) {
std::sort(dirs.begin(), dirs.end(),
[](auto& a, auto& b) { return a.second < b.second; });
const std::string& oldest_dir = dirs.front().first;
if (!oldest_dir.empty() && oldest_dir != save_path_root) {
CheckUtil::DeleteDir(oldest_dir);
}
}
} else {
cerr << ("ERROR: cannot open root directory for cleanup");
}
}
// ---------- 保存NG图像 ----------
int ImageNum = static_cast<int>(result_copy->ImageALLDetResultList.size());
for (int imgidx = 0; imgidx < ImageNum; ++imgidx) {
auto pImageResult = result_copy->ImageALLDetResultList.at(imgidx);
if (!pImageResult) continue;
auto m_CheckResult_shareP = pImageResult->result;
if (!m_CheckResult_shareP) continue;
// 提取并净化路径组件
std::string raw_product = result_copy->productBaseResult ?
result_copy->productBaseResult->strproductName : "unknown";
std::string raw_camera = result_copy->cameraBaseResult ?
result_copy->cameraBaseResult->strCameraName : "unknown";
std::string raw_channel = m_CheckResult_shareP->basicResult.strChannel;
std::string safe_product = SanitizePathComponent(raw_product);
std::string safe_camera = SanitizePathComponent(raw_camera);
std::string safe_channel = SanitizePathComponent(raw_channel);
// 只保存NG结果且图像数据非空
if ((m_CheckResult_shareP->nresult == 1 || safe_channel == "L255") &&
!m_CheckResult_shareP->resultMaskImg.empty() &&
!m_CheckResult_shareP->resultimg.empty() &&
!m_CheckResult_shareP->cutSrcimg.empty()) {
// 构建保存目录(使用净化后的组件)
std::string save_dir = save_path_root + "/" + safe_product + "/" + safe_camera + "/";
if (CheckUtil::CreateDir(save_dir) != 0) {
cerr << ("Failed to create directory: " + save_dir);
continue;
}
// 深拷贝图像数据,避免原始数据被其他线程修改
cv::Mat mask_img = m_CheckResult_shareP->resultMaskImg.clone();
cv::Mat result_img = m_CheckResult_shareP->resultimg.clone();
cv::Mat cut_img = m_CheckResult_shareP->cutSrcimg.clone();
try {
// cv::imwrite(save_dir + safe_channel + "_AIMask.png", mask_img);
// cv::imwrite(save_dir + safe_channel + "_Resultimg.png", result_img);
// cv::imwrite(save_dir + safe_channel + "_CutImg.png", cut_img);
writeLog(save_dir+ safe_channel + "log", m_CheckResult_shareP->det_LogList);
} catch (const cv::Exception& e) {
cerr << ("OpenCV exception: " + std::string(e.what()));
} catch (const std::exception& e) {
cerr << ("Standard exception: " + std::string(e.what()));
} catch (...) {
cerr << ("Unknown exception during image save");
}
}
}
} catch (const std::exception& e) {
cerr << ("Future get exception: " + std::string(e.what()));
} catch (...) {
cerr << ("Future get unknown exception");
}
});
// ---------- 管理 future 队列(清理已完成任务)----------
{
std::lock_guard<std::mutex> lock(g_ngImgSave_mutex);
g_ngImgSave_futures.emplace_back(std::move(task));
size_t write_idx = 0;
for (size_t i = 0; i < g_ngImgSave_futures.size(); ++i) {
auto& f = g_ngImgSave_futures[i];
// 检查任务是否已就绪(非阻塞)
if (f.valid() && f.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
try {
f.get();
} catch (const std::exception& e) {
cerr << ("Future get exception: " + std::string(e.what()));
} catch (...) {
cerr << ("Future get unknown exception");
}
} else {
// 保留未完成的任务
if (i != write_idx) {
g_ngImgSave_futures[write_idx] = std::move(g_ngImgSave_futures[i]);
}
++write_idx;
}
}
g_ngImgSave_futures.resize(write_idx);
// 限制队列最大长度防止无限堆积例如超过100则丢弃最老的任务
const size_t MAX_PENDING_TASKS = 20;
if (g_ngImgSave_futures.size() > MAX_PENDING_TASKS) {
// 丢弃最早未完成的任务(注意:需要确保其可被销毁,不阻塞)
g_ngImgSave_futures.erase(g_ngImgSave_futures.begin());
}
}
return 0;
}
ChannelCheckFunction *CameraCheckAnalysisy::GetChannelFuntion(std::string strChannelName)
{
ChannelCheckFunction *p = NULL;
// printf("m_pChannelFuntion->channelFunctionArr.size() %zu\n", m_pChannelFuntion->channelFunctionArr.size());
for (int i = 0; i < m_pChannelFuntion->channelFunctionArr.size(); i++)
{
if (CheckUtil::compareIgnoreCase(m_pChannelFuntion->channelFunctionArr[i].strChannelName, strChannelName))
{
p = &m_pChannelFuntion->channelFunctionArr[i];
}
}
return p;
}
int CameraCheckAnalysisy::SetNewConfig()
{
if (m_pConfig.get() == nullptr)
{
return 1;
}
if (m_nConfigIdx < 0)
{
m_nConfigIdx = m_pConfig->GetConfigIdx();
m_pdetlog->AddCheckstr(PrintLevel_1, "update config", "CameraCheckAnalysisy:%s m_nConfigIdx %d", m_strcameraName.c_str(), m_nConfigIdx);
}
if (m_pConfig->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, m_nConfigIdx))
{
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_imageResultJudge.UpdateConfig(m_strcameraName);
}
else
{
m_pCommonAnalysisyConfig = NULL;
printf("m_AnalysisyConfig.commonCheckConfig.nodeConfigArr == 0 \n");
}
m_pdetlog->AddCheckstr(PrintLevel_1, "update config", "Get New analysisy config");
// printf("*******ALLImgCheckAnalysisy m_pConfig*********************** Update GetConfig \n");
// m_AnalysisyConfig.checkFunction.print("Update GetConfig");
}
return 0;
}
ImgCheckBase *CameraCheckAnalysisy::GetDealResult(int idx)
{
// 特殊情况
if (idx >= 0 && idx < IMGCHECKANALYSISY_NUM)
{
if (CHECK_THREAD_STATUS_IDLE == m_pImgCheckAnalysisy[idx]->GetStatus())
{
// printf("*-*-*-*-*-*-*-*- use m_pImgCheckAnalysisy %d \n", idx);
return m_pImgCheckAnalysisy[idx];
}
else
{
return NULL;
}
}
int re = 0;
int nidx = nLastCheckAnalysisyThreadIdx;
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
{
if (nidx >= IMGCHECKANALYSISY_NUM)
{
nidx = 0;
}
if (CHECK_THREAD_STATUS_IDLE == m_pImgCheckAnalysisy[nidx]->GetStatus())
{
nLastCheckAnalysisyThreadIdx = nidx + 1;
// printf("*-*-*-*-*-*-*-*- use m_pImgCheckAnalysisy %d \n", nidx);
return m_pImgCheckAnalysisy[nidx];
}
nidx++;
}
return NULL;
}