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/example/deal.h

808 lines
20 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.

#ifndef _deal_HPP_
#define _deal_HPP_
#include <map>
#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <mutex>
#include <unistd.h>
#include "SystemCommonDefine.h"
#include "ImgCheckBase.h"
#include "ImgCheckConfig.h"
#include "ConfigBase.h"
#include <mutex>
#include <condition_variable>
#include <string>
#include "Image_ReadAndChange.h"
#include <filesystem>
#include "Read_Image.h"
#include "LoadImage.hpp"
namespace fs = std::filesystem;
// ============ 产品检测线程配置 ============
#define READ_PRODUCT_THREAD_NUM 8 // 读图线程数
#define PRODUCT_QUEUE_MAX_SIZE 30 // 任务队列最大长度
enum Thread_Status_
{
Thread_Status_IDE,
Thread_Status_READY,
Thread_Status_BUSY,
Thread_Status_COMMPLET,
};
enum Thread_ReadImg_Status_
{
ReadImg_Status_IDE,
ReadImg_Status_Read,
ReadImg_Status_COMMPLET,
};
// 各种线程处理状态信息
enum DET_Status_Type_
{
Status_Type_ReadAndDet, // 读取图和处理
Status_Type_PullPath, // 读取图片路径
Status_Type_Count,
};
enum Mutex_Type_
{
Mutex_Type_ReadImgThread, // 读图线程
Mutex_Type_DetStatus,
Mutex_Type_DetResult,
Mutex_Type_Count,
};
// 读线程,处理类型。
enum READ_THREAD_TYPE_
{
READ_THREAD_TYPE_NULL,
READ_THREAD_TYPE_READIMG, // 读图
READ_THREAD_Detect, // 检测模式
READ_THREAD_TYPE_COUNT,
};
// 线程运行模式
enum THREAD_RUN_TYPE
{
THREAD_RUN_Only_ReadImg, // 仅读图
THREAD_RUN_ALL, // 所有
};
#define READ_IMG_THREAD_NUM 4
#define Save_IMG_THREAD_NUM 4
// ============ 产品检测任务结构体 ============
struct ReadImgTask
{
std::string productId;
std::string channelName;
std::string imageName; // 图片名称(不含路径)
std::string left_path; // 左图路径
std::string right_path; // 右图路径
int camera_Num;
int taskIndex;
std::string cameraSide; // 相机方位:"left" | "right" | "merge"
ReadImgTask() : taskIndex(0), camera_Num(0), cameraSide("") {}
};
struct FailedImgRecord
{
std::string left_path;
std::string right_path;
std::string productId;
std::string channelName;
std::string errorReason;
FailedImgRecord() {}
};
// 图片检测通知信息
struct CheckImgNotifyInfo
{
int taskIndex;
std::string productId;
std::string channelName;
std::string imageName;
std::string left_path;
std::string right_path;
int width;
int height;
long readTimeMs;
bool success;
std::string errorReason; // 失败原因
cv::Mat left_img; // 左图数据
cv::Mat right_img; // 右图数据
int camera_Num;
// 新增字段
std::string cameraSide; // 相机方位:"left" | "right" | "merge"
CheckImgNotifyInfo()
: taskIndex(0), width(0), height(0),
readTimeMs(0), success(false), camera_Num(0), cameraSide("") {}
};
using namespace std;
enum RUNTYPE_
{
RUNTYPE_RUN_Pre,
RUNTYPE_RUN_File,
RUNTYPE_RUN_File_AI_TEST,
RUNTYPE_RUN_File_Edge_Test_Save_Qx,
RUNTYPE_RUN_File_Edge_Test_Save_ALL,
};
// 程序运行模式
enum Process_Run_Type
{
Process_Run_Detect, // 正常检测模式
Process_Run_ReJson, // 复测模式
Process_Run_SaveImg, // 解密图片并存图
};
struct JC_IMAGE_INFO_
{
enum Status_
{
STATUS_Image_IDE,
STATUS_Image_READ,
STATUS_Image_COMMPLET,
STATUS_Det_Start,
};
std::string strProductID; // 产品ID
std::string strCamID; // 相机名称
std::string strchannelName; // 通道名称
std::string strPath; // 完整路径
std::string strName; // 图片名称
cv::Mat img; // 图像数据
Status_ status; // 状态
long readImg_start; // 读取开始时间
long readImg_end; // 读取结束时间
// 构造函数,调用 Init 初始化
JC_IMAGE_INFO_()
{
Init();
}
// 初始化函数,重置所有成员变量
void Init()
{
strProductID = "";
strCamID = "";
strchannelName = "";
strPath = "";
strName = "";
img.release(); // 释放图像内存
status = STATUS_Image_IDE;
readImg_start = 0;
readImg_end = 0;
}
// 拷贝函数,将传入的结构体内容复制到当前对象
void copy(JC_IMAGE_INFO_ tem)
{
this->strProductID = tem.strProductID;
this->strCamID = tem.strCamID;
this->strchannelName = tem.strchannelName;
this->strPath = tem.strPath;
this->strName = tem.strName;
if (!tem.img.empty())
{
this->img = tem.img.clone(); // 深拷贝图像数据
}
this->status = tem.status;
this->readImg_start = tem.readImg_start;
this->readImg_end = tem.readImg_end;
}
// 打印信息函数(可选)
void print()
{
std::cout << "Product ID: " << strProductID << std::endl;
std::cout << "Camera ID: " << strCamID << std::endl;
std::cout << "Channel Name: " << strchannelName << std::endl;
std::cout << "Image Path: " << strPath << std::endl;
std::cout << "Image Name: " << strName << std::endl;
std::cout << "Status: " << status << std::endl;
std::cout << "Read Start Time: " << readImg_start << std::endl;
std::cout << "Read End Time: " << readImg_end << std::endl;
}
};
struct Det_single_img_Result_Info
{
int result;
std::string name;
std::string qx_name;
Det_single_img_Result_Info()
{
Init();
}
void Init()
{
name = "";
result = 0;
qx_name = "NO";
}
};
struct Det_One_Result_Info
{
int result;
long time_s;
long time_e;
std::string Product_ID;
std::vector<Det_single_img_Result_Info> img_result_list;
Det_One_Result_Info()
{
Init();
}
void Init()
{
Product_ID = "";
time_s = 0;
time_e = 0;
result = 0;
img_result_list.erase(img_result_list.begin(), img_result_list.end());
img_result_list.clear();
}
std::string print()
{
std::string str = "";
// printf("%s:result %d | ", Product_ID.c_str(), result);
char buffer[64];
sprintf(buffer, "%s:result %d time %ld | ", Product_ID.c_str(), result, time_e - time_s);
std::string st1 = buffer;
str += st1;
for (size_t i = 0; i < img_result_list.size(); i++)
{
str += img_result_list.at(i).name + " " + img_result_list.at(i).qx_name + " | ";
}
// str += str;
return str;
// printf("%s\n", str.c_str());
}
};
struct Det_File_qx_Info
{
std::string qx_name;
int num;
Det_File_qx_Info()
{
Init();
}
void Init()
{
qx_name = "";
num = 0;
}
};
// 套图检测 统计结果信息
struct Det_File_Result_Info
{
int det_num_all;
int det_num_ok;
int det_num_ng;
int det_num_error;
float sumtime_S;
long startTime_S;
float mean_time;
std::vector<Det_One_Result_Info> one_result_list;
std::vector<std::string> strlist;
std::vector<Det_File_qx_Info> qx_result_list;
Det_File_Result_Info()
{
Init();
}
void Init()
{
det_num_all = 0;
det_num_ok = 0;
det_num_ng = 0;
det_num_error = 0;
sumtime_S = 0;
startTime_S = 0;
mean_time = 0;
one_result_list.erase(one_result_list.begin(), one_result_list.end());
one_result_list.clear();
strlist.erase(strlist.begin(), strlist.end());
strlist.clear();
qx_result_list.erase(qx_result_list.begin(), qx_result_list.end());
qx_result_list.clear();
}
void updata(std::string productid, std::string imgname, int nresult, long t)
{
sumtime_S = t - startTime_S;
sumtime_S /= 1000;
if (det_num_all > 0)
{
mean_time = sumtime_S / det_num_all;
}
for (int i = 0; i < one_result_list.size(); i++)
{
if (one_result_list.at(i).Product_ID == productid)
{
// if (one_result_list.at(i).result < 0)
// {
// one_result_list.at(i).result = 0;
// }
one_result_list.at(i).time_e = t;
for (size_t j = 0; j < one_result_list.at(i).img_result_list.size(); j++)
{
if (one_result_list.at(i).img_result_list.at(j).name == imgname)
{
one_result_list.at(i).img_result_list.at(j).result = nresult;
if (nresult == 0)
{
one_result_list.at(i).img_result_list.at(j).qx_name = "OK";
}
else if (nresult > 0)
{
one_result_list.at(i).img_result_list.at(j).qx_name = "NG";
if (one_result_list.at(i).result == 0)
{
one_result_list.at(i).result = 1;
}
}
else
{
one_result_list.at(i).img_result_list.at(j).qx_name = "ER";
one_result_list.at(i).result = -1;
}
}
}
}
}
}
void update_qx(std::string qx_name, int num)
{
for (int i = 0; i < qx_result_list.size(); i++)
{
if (qx_result_list.at(i).qx_name == qx_name)
{
qx_result_list.at(i).num += num;
return;
}
}
Det_File_qx_Info tem;
tem.qx_name = qx_name;
tem.num = num;
qx_result_list.push_back(tem);
}
void print(bool show = true)
{
strlist.erase(strlist.begin(), strlist.end());
strlist.clear();
det_num_ok = 0;
det_num_ng = 0;
det_num_error = 0;
std::string str = "";
str = "*****************************************************************************";
strlist.push_back(str);
str = "*****************************detect result***********************************";
strlist.push_back(str);
float fok = 0;
float fng = 0;
float ferror = 0;
// printf("one_result_list.size() %d \n", one_result_list.size());
for (int i = 0; i < one_result_list.size(); i++)
{
if (one_result_list.at(i).result == 0)
{
det_num_ok++;
}
else if (one_result_list.at(i).result > 0)
{
det_num_ng++;
}
else
{
det_num_error++;
}
}
if (det_num_all > 0)
{
fok = det_num_ok * 1.0f / det_num_all * 100;
fng = det_num_ng * 1.0f / det_num_all * 100;
ferror = det_num_error * 1.0f / det_num_all * 100;
}
char buffer[64];
sprintf(buffer, "ALL:%d OK:%d %.1f%% NG:%d %.1f%% Error:%d %.1f%%", det_num_all, det_num_ok, fok, det_num_ng, fng, det_num_error, ferror);
std::string st1 = buffer;
strlist.push_back(st1);
sprintf(buffer, "Use time %f s mean time %f s", sumtime_S, mean_time);
std::string st2 = buffer;
strlist.push_back(st2);
// printf("%s\n", st1.c_str());
// printf("------------------------------------------------------------------------------\n");
str = "------------------------------------------------------------------------------";
strlist.push_back(str);
{
int qx_all_num = 0;
for (size_t i = 0; i < qx_result_list.size(); i++)
{
qx_all_num += qx_result_list.at(i).num;
}
for (size_t i = 0; i < qx_result_list.size(); i++)
{
float fr = qx_result_list.at(i).num * 1.0 / qx_all_num * 100;
std::string str_qx = "";
// printf("len %d \n", qx_result_list.at(i).qx_name.length());
for (int k = 0; k < (20 - qx_result_list.at(i).qx_name.length()); k++)
{
str_qx += " ";
}
str_qx += qx_result_list.at(i).qx_name;
char buffer123[64];
sprintf(buffer123, ":%d %.1f%% ", qx_result_list.at(i).num, fr);
std::string st1 = buffer123;
str_qx += st1;
int nlen = fr;
for (int j = 0; j < nlen; j++)
{
str_qx += "|";
}
strlist.push_back(str_qx);
}
}
str = "------------------------------------------------------------------------------";
strlist.push_back(str);
for (int i = 0; i < one_result_list.size(); i++)
{
st1 = one_result_list.at(i).print();
strlist.push_back(st1);
}
str = "*****************************************************************************";
strlist.push_back(str);
// printf("*****************************************************************************\n");
if (show)
{
for (size_t i = 0; i < strlist.size(); i++)
{
printf("%s\n", strlist.at(i).c_str());
}
}
}
};
struct IMG_BASE_INFO_
{
std::string strPath;
std::string strChannel;
std::string strImgSN;
IMG_BASE_INFO_()
{
strPath = "";
strImgSN = "";
strChannel = "";
}
};
struct ReadImgInfo
{
std::string strPath;
std::string strChannel;
int stype;
int status;
std::string strImgSN;
int idx;
int sumNUm;
cv::Rect cutRoi;
std::vector<IMG_BASE_INFO_> imglist;
ReadImgInfo()
{
strPath = "";
strImgSN = "";
stype = 0;
status = 0;
idx = 0;
imglist.clear();
cutRoi = cv::Rect(0, 0, 0, 0);
sumNUm = 0;
}
};
struct AI_Det_Path
{
std::string strPath_CutImg;
std::string strPath_AIMask;
/* data */
};
struct AI_Det_Channel_
{
std::string strChannel;
AI_Det_Path path;
/* data */
};
struct Json_Det_Path
{
std::string strPath_CutImg;
std::string strPath_Json;
/* data */
};
struct READ_IMG_INFO
{
std::string strpath = "";
std::string strproduct = "";
};
struct DealRunConfig
{
Process_Run_Type run_Type = Process_Run_Detect; // 运行模式
RUNTYPE_ det_Type = RUNTYPE_RUN_Pre; // 处理
std::string filePath = ""; // 处理文件路径 如果为空 处理当前的单张图片
bool bDebugSaveImg = false; // 是否中间图片图片
int m_nTestNum = 999999;
void print(std::string str)
{
printf(">>>>>>>>>>>>>>> %s <<<<<<<<<<<<\n", str.c_str());
printf("run_Type %d det_Type %d file %s bsave %d \n", run_Type, det_Type, filePath.c_str(), bDebugSaveImg);
}
};
class deal
{
public:
// 构造函数
deal();
~deal();
int start();
private:
// 初始化
int Init();
// 检测参数
int LoadCheckImgConfig();
// 初始化检测分析线程类
int InitCheckAnalysisy();
int InitConfig();
// 初始化 检查存图路径
int InitSaveImgPath();
int LoadCheckConfig();
// 分析参数
int LoadAnalysisConfig();
// 开启线程
int StartThread(THREAD_RUN_TYPE type);
// 停止线程
int StopThread();
int preCheck();
std::string readTestImg();
int readTestImg(READ_IMG_INFO &read);
// 重复检测
int repeatCheck();
int saveImg(std::string strpath, std::shared_ptr<CheckResult> result);
int writeLog(std::string strSavePath, std::vector<std::string> logList);
int WriteJsonString(std::string strSavePath, std::string strjson);
// 获取图片路径
int GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector<JC_IMAGE_INFO_> &jcImageInfoList);
// 解析图片的信息 -- cell et
int GetImgInfo_POL_ET(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo);
int GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo);
// 随机绘制错误
int RandDrawImg(cv::Mat srcimg, cv::Mat &randErrorImg);
int LoadOfflineCheckImg(std::string strImgPath);
int LoadImgPath_JCSN(std::string strImgPath);
bool isValidString(const std::string &str);
int LoadProductID(std::string strImgPath);
int set_cpu_id(const std::vector<int> &cpu_set_vec);
void GetDealResultToQueu();
// 加载系统配置文件
bool ReadSystemConfig(const std::string &strPath);
int GetJcImageInfo(std::string strpath, std::vector<JC_IMAGE_INFO_> &jcImageInfoList);
int ReadTestImgaData();
// 处理前,初始化部分数据
int InitDetData();
// 检测结果 插入结果队列
int InsertDetResult(ReadImgInfo tem);
int GetUpMaskImg(cv::Mat inImg, cv::Rect roi, cv::Mat &maskimg);
int ReJson();
int ReJson_ALL();
int DetImg(); // 套图复测
int ReJson_product(std::vector<Json_Det_Path> &jsonList, std::string strProductName); // 套图复测
int CheckFileImg(); ///< 检查文件图片(新增)
int CheckProduct(const LoadProductImages &product); ///< 检查单个产品(新增)
int SendCheckImg(const CheckImgNotifyInfo &info, IN_IMG_Status_ status, bool bComplete = false); // 处理图片
// ============ 产品检测线程池相关 ============
void ProductReadImgThreadFunc(int threadId);
std::shared_ptr<ReadImgTask> GetProductTask();
void DistributeProductTasks(const LoadProductImages &product);
void RecordFailedImg(const FailedImgRecord &record);
void PrintProductStatistics(const LoadProductImages &product);
// ============ 线程池生命周期管理 ============
void InitProductReadThreadPool(); ///< 初始化线程池(构造时调用)
void DestroyProductReadThreadPool(); ///< 销毁线程池(析构时调用)
private:
// 处理调度线程
std::shared_ptr<std::thread> ptr_DealImgthread;
void DealImg();
std::vector<std::string> extractAllDirectories(const std::string &path);
// 结果处理线程
// std::shared_ptr<std::thread> ptr_Resultthread;
std::vector<std::shared_ptr<std::thread>> ptr_ResultthreadList;
void ResultThread(int id);
// 结果拷贝线程
std::shared_ptr<std::thread> ptr_GetResultthread;
void GetResultThread();
std::vector<std::shared_ptr<std::thread>> threadArray;
void ReadImgThread(int id);
void testimg(cv::Mat img);
int updataResltInfo(std::shared_ptr<CheckResult> result);
void slidingWindowAutoThreshold(const cv::Mat &src, cv::Mat &dst, int windowSize, int step, double C);
int SetStatus(int type, int status);
int GetStatus(int type);
bool IsStatus(int type, int status);
int SetStatus_List(int idx, Thread_Status_ status);
int GetStatus_List(int idx);
bool IsStatus_List(int idx, Thread_Status_ status);
int setReadThreadStart();
int GetReadImgCompleteThreadIdx(); // 获取读取完成后的idx
bool IsALLComplete();
int InitCPUIDX();
// 线程读图
void Thread_ReadImg(int id);
int InsertReadImgInfo(std::shared_ptr<JC_IMAGE_INFO_> pImageInfo);
int GetReadImgInfo(std::shared_ptr<JC_IMAGE_INFO_> &pImageInfo);
public:
std::vector<cv::Mat> m_OffLineCheckImgList; // 离线检测图片列表
std::vector<std::string> m_OffLineCheckImgNameList; // 离线检测图片列表
std::vector<std::string> m_OffImageSNPathList; // 离线检测图片列表
std::vector<std::string> m_product_ID_List; // 离线检测图片列表
ALLImgCheckBase *m_pALLImgCheckAnalysisy;
std::vector<std::string> m_TestJC_ImageDate; // 离线检测图片列表
std::string m_strCurDate;
int m_nSystemCheckType;
bool m_bExit;
int nLastCheckAnalysisyThreadIdx;
RunInfoST m_RunConfig; // 检测基本参数
std::mutex mutex_Result_list;
std::queue<std::shared_ptr<CheckResult>> m_Result_list;
// 检测区域list
std::vector<cv::Point> m_DetRoiMaskPointList;
// 检测区域list
std::vector<cv::Point> m_CoreMaskPointList;
DealRunConfig runConfig;
int m_nTestNum;
std::string m_strSaveImgPath;
ConfigManagerBase *m_pConfigManager = NULL;
SystemConfigParam m_system_param;
int m_nCurUseCPUIDX;
int m_nCamIdx;
ImageInfo m_ImgInfo_src;
ImageInfo m_ImgInfo_result;
cv::Rect m_CutRoi;
int nn;
int nddd;
int kkd;
int maxidx;
Det_File_Result_Info m_DetResult;
std::vector<JC_IMAGE_INFO_> m_ImageInfoList;
std::queue<std::shared_ptr<JC_IMAGE_INFO_>> m_ReadImg_queue; // 读图队列
std::mutex mutex_ReadImgList;
std::condition_variable cv_ReadImgList;
int m_nReadStausList[READ_IMG_THREAD_NUM];
// 读图线程状态
std::shared_ptr<JC_IMAGE_INFO_> m_ReadImgThread_Result[READ_IMG_THREAD_NUM];
READ_THREAD_TYPE_ m_nReadThread_type;
bool m_nreadImg_Stop;
std::mutex mutex_DetResult_;
std::queue<ReadImgInfo> m_DetImgQueue; // 存储生产者生产的数据
std::mutex mtx_DetImgQueue; // 互斥量,保护共享资源
std::mutex mtx_DetImgQueue_edge; // 互斥量,保护共享资源
std::condition_variable cv; // 条件变量,用于线程间通信
std::mutex mtx_DetImgQueue_com; //
int m_read_ImgNum;
long m_readImgStarttime;
int m_DetStatusList[Status_Type_Count]; // 各种需要线程同步的状态信息
std::mutex mtx_List[Mutex_Type_Count]; // 互斥量
std::vector<ReadImgInfo> m_DetResultList;
CPU_ID_INFO_ m_CPUInfo[THREAD_CPU_Count];
Image_ReadChannel m_image_ReadChannel;
Process_Run_Type m_processRunType = Process_Run_Detect; // 程序运行模式
// ============ 产品检测线程池相关成员 ============
std::vector<std::shared_ptr<std::thread>> m_productReadThreads; // 读图线程池
std::queue<std::shared_ptr<ReadImgTask>> m_productTaskQueue; // 任务队列
std::mutex m_productTaskMutex;
std::condition_variable m_productTaskCV;
std::atomic<bool> m_bProductReadExit{false}; // 退出标志
std::atomic<int> m_nProductPendingTasks{0}; // 待处理任务数
std::atomic<int> m_nProductSuccessCount{0}; // 成功数量
std::atomic<int> m_nProductFailCount{0}; // 失败数量
std::vector<FailedImgRecord> m_ProductFailedList;
std::mutex m_productFailedMutex;
int m_nProductReadThreadNum; // 读图线程数
int m_nProductQueueMaxSize; // 队列最大长度
// ============ 图片检测通知相关 ============
std::queue<CheckImgNotifyInfo> m_checkNotifyQueue; // 通知队列
std::mutex m_checkNotifyMutex; // 通知队列锁
std::condition_variable m_checkNotifyCV; // 通知条件变量
std::atomic<int> m_nCheckNotifiedCount{0}; // 已通知数量
std::atomic<int> m_nProductSavedResultCount{0}; // 已保存结果数量(用于产品间同步等待)
std::condition_variable m_productResultCV; // 产品结果保存通知CV每次save后notify
std::set<std::string> m_productIdList; // 产品ID列表
};
#endif //_CORELOGICFACTORY_HPP_