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.

708 lines
18 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"
namespace fs = std::filesystem;
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
using namespace std;
enum RUNTYPE_
{
RUNTYPE_RUN_Pre,
RUNTYPE_RUN_File,
RUNTYPE_RUN_EDGE_TEST,
RUNTYPE_RUN_EDGE_TEST_AI,
RUNTYPE_RUN_Merge_Img,
};
// 程序运行模式
enum Process_Run_Type
{
Process_Run_Detect, // 正常检测模式
Process_Run_ReJson, // 复测模式
};
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 strPath_B; // 完整路径
std::string strName; // 图片名称
cv::Mat img; // 图像数据
cv::Mat img_B; // 图像数据
Status_ status; // 状态
long readImg_start; // 读取开始时间
long readImg_end; // 读取结束时间
// 构造函数,调用 Init 初始化
JC_IMAGE_INFO_()
{
Init();
}
// 初始化函数,重置所有成员变量
void Init()
{
strProductID = "";
strCamID = "";
strchannelName = "";
strPath = "";
strPath_B = "";
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->strPath_B = tem.strPath_B;
this->strName = tem.strName;
if (!tem.img.empty())
{
this->img = tem.img.clone(); // 深拷贝图像数据
}
if (!tem.img_B.empty())
{
this->img_B = tem.img_B.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 strPath_B: " << strPath_B << 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++)
{
// 除零保护:没有任何缺陷统计时百分比按 0 处理
float fr = (qx_all_num > 0) ? (qx_result_list.at(i).num * 100.0f / qx_all_num) : 0.0f;
std::string str_qx = "";
// 名称补空格对齐到 20 字节。
// 注意:qx_name.length() 返回 size_t(无符号),若写成 20 - length(),
// 当名称超过 20 字节时(中文缺陷名如"铜箔面不良标签"为 21 字节)会下溢成
// 巨大无符号值,导致循环近似死循环(-f 批量卡住的根因)。
size_t nNameLen = qx_result_list.at(i).qx_name.length();
if (nNameLen < 20)
{
str_qx.append(20 - nNameLen, ' ');
}
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;
// 百分比条长度限制在 [0,100],避免异常值造成超长字符串
int nlen = static_cast<int>(fr);
if (nlen < 0)
{
nlen = 0;
}
if (nlen > 100)
{
nlen = 100;
}
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 strpath_2 = "";
std::string strproduct = "";
};
struct DealRunConfig
{
Process_Run_Type run_Type = Process_Run_Detect; // 运行模式
RUNTYPE_ det_Type = RUNTYPE_RUN_Pre; // 处理
std::string filePath = ""; // 处理文件路径 如果为空 处理当前的单张图片
bool bSaveProcessImg = false; // 是否中间图片图片
bool bLoop = false; // -8 循环执行(常驻)
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(), bSaveProcessImg);
}
};
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();
int readTestImg(READ_IMG_INFO &read);
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 DelImg_Cell_ET();
int Det_OneProduct_Cell_ET(std::string strProductName, int Idx);
// 获取图片路径
int GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector<JC_IMAGE_INFO_> &jcImageInfoList);
// 解析图片的信息
int GetImgInfo_POL_ET(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo);
int GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo);
// -f 批量跑新格式: 解析 <产品ID>_<相机名>_<位置>_src.jpg 图片名组装产品信息(相机名 t_face_bright/t_face_dark, 通道名统一 t_face)
int GetImgInfo_BACKPLATE_SRC(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo);
// 功能测试
int Det_Funtion_Test();
// 边缘测试
int Det_Funtion_Edge();
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 InsertDetResult(ReadImgInfo tem);
// 送图去检测
int SendImgToCheck(std::shared_ptr<JC_IMAGE_INFO_> pDetImageInfo, IN_IMG_Status_ status);
int ReJson_ALL();
int DetImg(); // 套图复测
int ReJson_product(std::vector<Json_Det_Path> &jsonList, std::string strProductName); // 套图复测
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);
int updataResltInfo(std::shared_ptr<CheckResult> result);
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<std::string> m_OffImageSNPathList; // 离线检测图片列表
std::vector<std::string> m_product_ID_List; // 离线检测图片列表
ALLImgCheckBase *m_pALLImgCheckAnalysisy;
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;
int m_nSaveDetprocessImg;
int m_nPushImgCount; // 送检图片总数(拆分后)
int m_nResultRecvCount; // 已收到检测结果总数(-f 逐个产品处理:等当前产品结果返回后再跑下一个)
cv::Rect m_CutRoi;
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; // 程序运行模式
};
#endif //_CORELOGICFACTORY_HPP_