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.

804 lines
20 KiB

#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}; // 已通知数量
};
#endif //_CORELOGICFACTORY_HPP_