初始化仓库(使用CELL_ET为模板)

main
liusiyang 2 weeks ago
parent 34b76f5f1c
commit a948ff6c9b

7
.gitignore vendored

@ -0,0 +1,7 @@
/build
/lib
/include
/data
/SaveImg
/.cache
.vscode/launch.json

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/include/opencv4"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

@ -0,0 +1,45 @@
cmake_minimum_required (VERSION 3.5)
find_package( OpenCV REQUIRED )
message(STATUS "oPENCV Library status:")
message(STATUS ">version:${OpenCV_VERSION}")
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
find_package(CUDA REQUIRED)
message(STATUS "cuda version: " ${CUDA_VERSION_STRING})
message(STATUS "cuda CUDA_INCLUDE_DIRS: " ${CUDA_INCLUDE_DIRS})
include_directories(${CUDA_INCLUDE_DIRS})
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/AIEngineModule/include
${PROJECT_SOURCE_DIR}/AIEngineModule/include_base
)
link_directories(
/usr/local/lib/
)
set(CMAKE_CUDA_ARCHITECTURES 86)
set(CMAKE_CUDA_COMPILER "/usr/local/cuda/bin/nvcc")
enable_language(CUDA)
file(GLOB SRC_LISTS
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.cpp
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.c
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.cu
)
add_executable("ai_test" ${SRC_LISTS})
target_link_libraries("ai_test"
pthread
z
nvinfer
${CUDA_LIBRARIES}
${OpenCV_LIBS}
)

@ -0,0 +1,9 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-04 16:18:48
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-07-04 16:23:28
* @FilePath: /AI_SO_Test/AIEngineModule/example/deal.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "deal.h"

@ -0,0 +1,5 @@
#ifndef _deal_HPP_
#define _deal_HPP_
#endif //_CORELOGICFACTORY_HPP_

@ -0,0 +1,302 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-04 16:18:48
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-06 22:37:59
* @FilePath: /AI_SO_Test/AIEngineModule/example/test_example.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include <iostream>
#include <string>
#include <signal.h>
#include "deal.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <thread>
#include "AI_Factory.h"
#include <chrono>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <sstream>
#include <sys/time.h>
#include <sys/statfs.h>
long getcurTime()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000;
}
void handler(int sig)
{
printf("Get handler sig");
std::string strcmd = "ps -ef | grep test_JBL_Check| awk '{print $2}' | xargs kill -9 ";
const char *cmd = strcmd.c_str();
printf("delete test_JBL_Check success");
if (-1 == system(cmd))
{
std::cout << "error" << std::endl;
}
// delete UnderCarriageCoreLogic::GetInstance();
exit(0);
}
int _sysmkdir(const std::string &dir)
{
int ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (ret && errno == EEXIST)
{
//printf("dir[%s] already exist.\n", dir.c_str());
}
else if (ret)
{
printf("create dir[%s] error: %d %s\n", dir.c_str(), ret, strerror(errno));
return -1;
}
else
{
printf("create dir[%s] success.\n", dir.c_str());
}
return 0;
}
std::string __getParentDir(const std::string &dir)
{
std::string pdir = dir;
if (pdir.length() < 1 || (pdir[0] != '/'))
{
return "";
}
while (pdir.length() > 1 && (pdir[pdir.length() - 1] == '/'))
pdir = pdir.substr(0, pdir.length() - 1);
pdir = pdir.substr(0, pdir.find_last_of('/'));
return pdir;
}
int _sysmkdirs(const std::string &dir)
{
int ret = 0;
if (dir.empty())
return -1;
std::string pdir;
if ((ret = _sysmkdir(dir)) == -1)
{
pdir = __getParentDir(dir);
if ((ret = _sysmkdirs(pdir)) == 0)
{
ret = _sysmkdirs(dir);
}
}
return ret;
}
int main(int argc, char *argv[])
{
// std::shared_ptr<AIFactory> AI_Factory;
// AI_Factory = AIFactory::GetInstance();
// GPU_Config gpu;
// AI_Factory->InitALLAIModle(gpu);
// std::shared_ptr<AIModel_Base> BOE_Edge_Detect = AI_Factory->BOE_Edge_Detect;
// BOE_Edge_Detect->input_0.print();
// BOE_Edge_Detect->input_1.print();
// BOE_Edge_Detect->output_0.print();
// BOE_Edge_Detect->output_1.print();
// BOE_Edge_Detect->output_2.print();
// std::shared_ptr<AIModel_Base> JBL_Detect = AI_Factory->JBL_Detect;
// JBL_Detect->input_0.print();
// JBL_Detect->input_1.print();
// JBL_Detect->output_0.print();
// JBL_Detect->output_1.print();
// JBL_Detect->output_2.print();
// cv::Mat temimg = cv::imread("../data/20250319_192154_Main_0_2_L255_Org.tif", 0);
// cv::Mat dealImg;
// printf("src img %d %d \n", temimg.cols, temimg.rows);
// cv::Size sz = cv::Size(BOE_Edge_Detect->input_0.width, BOE_Edge_Detect->input_0.height);
// cv::resize(temimg, dealImg, cv::Size(BOE_Edge_Detect->input_0.width, BOE_Edge_Detect->input_0.height));
// cv::Mat outimg;
// BOE_Edge_Detect->AIDet(dealImg, outimg);
// cv::imwrite("outimg.png", outimg);
// {
// long t1 = getcurTime();
// cv::Mat output;
// for (int i = 0; i < 1000; ++i)
// {
// cv::resize(temimg, dealImg, sz);
// BOE_Edge_Detect->AIDet(dealImg, outimg);
// }
// long t2 = getcurTime();
// std::cout << "== run 1000 : " << t2 - t1 << " 毫秒" << std::endl;
// // cv::imwrite(name + "_output.jpg", output);
// // std::cout << "[" << name << "] done\n";
// };
// printf("========================\n");
// {
// long t1 = getcurTime();
// // Lambda 线程函数
// auto run_detection = [](std::shared_ptr<AIModel_Base> engine, const cv::Mat &input, const cv::Size sz, const std::string &name)
// {
// cv::Mat output;
// for (int i = 0; i < 250; ++i)
// {
// cv::Mat dealImg123;
// cv::resize(input, dealImg123, sz);
// // printf("%s ---- \n",name.c_str());
// engine->AIDet(dealImg123, output);
// // cv::imwrite(name + "_" + std::to_string(i) + "_output.jpg", output);
// }
// // cv::imwrite(name + "_output.jpg", output);
// // std::cout << "[" << name << "] done\n";
// };
// // 启动两个线程
// std::thread thread1(run_detection, BOE_Edge_Detect, temimg, sz, "manager1");
// std::thread thread2(run_detection, BOE_Edge_Detect, temimg, sz, "manager2");
// std::thread thread3(run_detection, BOE_Edge_Detect, temimg, sz, "manager3");
// std::thread thread4(run_detection, BOE_Edge_Detect, temimg, sz, "manager4");
// // std::thread thread5(run_detection, BOE_Edge_Detect, dealImg, "manager1");
// // std::thread thread6(run_detection, BOE_Edge_Detect, dealImg, "manager2");
// // std::thread thread7(run_detection, BOE_Edge_Detect, dealImg, "manager3");
// // std::thread thread8(run_detection, BOE_Edge_Detect, dealImg, "manager4");
// // 等待线程结束
// thread1.join();
// thread2.join();
// thread3.join();
// thread4.join();
// // thread5.join();
// // thread6.join();
// // thread7.join();
// // thread8.join();
// long t2 = getcurTime();
// std::cout << "run 1000 = thread 4 * 250 耗时: " << t2 - t1 << " 毫秒" << std::endl;
// }
// cv::Mat dealImg123;
// cv::resize(temimg, dealImg123, cv::Size(JBL_Detect->input_0.width, JBL_Detect->input_0.height));
// float fss = 0;
// int rclass = JBL_Detect->AIClass(dealImg123, &fss);
// printf("test ------------rclass %d score %f\n", rclass, fss);
// // printf("%d %d\n", manager_1->BOE_Edge_Detect->m_img_In_0.width, manager_1->BOE_Edge_Detect->m_img_In_0.height);
// // std::string strModelPath = "/home/aidlux/BOE/UseModel/Edge_Big.engine";
// // std::string strModelPath_jbl = "/home/aidlux/BOE/UseModel/class_14.engine";
// // std::shared_ptr<AIManagerBase> manager_1 = AIManagerBase::GetInstance(0);
// // std::shared_ptr<AIManagerBase> manager_2 = AIManagerBase::GetInstance(1);
// // std::shared_ptr<AIManagerBase> manager_3 = AIManagerBase::GetInstance(0);
// // std::cout << "manager_1 instance address: " << manager_1.get() << std::endl;
// // std::cout << "manager_2 instance address: " << manager_2.get() << std::endl;
// // std::cout << "manager_3 instance address: " << manager_3.get() << std::endl;
// // std::cout << "manager_1->BOE_Edge_Detect instance address: " << manager_1->BOE_Edge_Detect.get() << std::endl;
// // std::cout << "manager_2->BOE_Edge_Detect instance address: " << manager_2->BOE_Edge_Detect.get() << std::endl;
// // std::cout << "manager_3->BOE_Edge_Detect instance address: " << manager_3->BOE_Edge_Detect.get() << std::endl;
// // std::cout << "manager_1->JBL_Detect instance address: " << manager_1->JBL_Detect.get() << std::endl;
// // std::cout << "manager_2->JBL_Detect instance address: " << manager_2->JBL_Detect.get() << std::endl;
// // std::cout << "manager_3->JBL_Detect instance address: " << manager_3->JBL_Detect.get() << std::endl;
// // manager_1->BOE_Edge_Detect->Init(strModelPath);
// // manager_2->BOE_Edge_Detect->Init(strModelPath);
// // manager_3->BOE_Edge_Detect->Init(strModelPath);
// // manager_1->JBL_Detect->Init(strModelPath_jbl);
// // manager_2->JBL_Detect->Init(strModelPath_jbl);
// // manager_3->JBL_Detect->Init(strModelPath_jbl);
// // cv::Mat temimg = cv::imread("/home/aidlux/xwj/AI_SO_Test/data/img/20250319_192154_Main_0_2_L255_Org.tif", 0);
// // cv::Mat dealImg;
// // printf("%d %d\n", manager_1->BOE_Edge_Detect->m_img_In_0.width, manager_1->BOE_Edge_Detect->m_img_In_0.height);
// // if (manager_1->BOE_Edge_Detect)
// // {
// // cv::resize(temimg, dealImg, cv::Size(manager_1->BOE_Edge_Detect->m_img_In_0.width, manager_1->BOE_Edge_Detect->m_img_In_0.height));
// // cv::Mat outimg;
// // manager_1->BOE_Edge_Detect->AIDet(dealImg, outimg);
// // manager_2->BOE_Edge_Detect->AIDet(dealImg, outimg);
// // {
// // long t1 = getcurTime();
// // cv::Mat output;
// // for (int i = 0; i < 500; ++i)
// // {
// // manager_1->BOE_Edge_Detect->AIDet(dealImg, output);
// // }
// // for (int i = 0; i < 500; ++i)
// // {
// // manager_1->BOE_Edge_Detect->AIDet(dealImg, output);
// // }
// // long t2 = getcurTime();
// // std::cout << "run 1000 : " << t2 - t1 << " 毫秒" << std::endl;
// // // cv::imwrite(name + "_output.jpg", output);
// // // std::cout << "[" << name << "] done\n";
// // };
// // long t1 = getcurTime();
// // // Lambda 线程函数
// // auto run_detection = [](std::shared_ptr<AIEngineBase> engine, const cv::Mat &input, const std::string &name)
// // {
// // cv::Mat output;
// // for (int i = 0; i < 500; ++i)
// // {
// // engine->AIDet(input, output);
// // }
// // // cv::imwrite(name + "_output.jpg", output);
// // // std::cout << "[" << name << "] done\n";
// // };
// // // 启动两个线程
// // std::thread thread1(run_detection, manager_1->BOE_Edge_Detect, dealImg, "manager1");
// // std::thread thread2(run_detection, manager_1->BOE_Edge_Detect, dealImg, "manager3");
// // // 等待线程结束
// // thread1.join();
// // thread2.join();
// // // for (int i = 0; i < 1000; i++)
// // // {
// // // manager_1->BOE_Edge_Detect->AIDet(dealImg, outimg);
// // // // manager_3->BOE_Edge_Detect->AIDet(dealImg, outimg);
// // // }
// // long t2 = getcurTime();
// // std::cout << "run 1000 = thread 2 * 500 耗时: " << t2 - t1 << " 毫秒" << std::endl;
// // cv::imwrite("dealImg.jpg", dealImg);
// // cv::imwrite("outimg.jpg", outimg);
// // }
// // cv::Mat dealImg123;
// // cv::resize(temimg, dealImg123, cv::Size(manager_1->JBL_Detect->m_img_In_0.width, manager_1->JBL_Detect->m_img_In_0.height));
// // float fss = 0;
// // int rclass = manager_1->JBL_Detect->AIClass(dealImg, &fss);
// // long t11 = getcurTime();
// // rclass = manager_1->JBL_Detect->AIClass(dealImg, &fss);
// // long t12 = getcurTime();
// // printf("test ------------rclass %d score %f------- time %ld\n", rclass, fss, t12 - t11);
// // printf("test ------------------- \n");
// getchar();
return 0;
}

@ -0,0 +1,220 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-06 22:23:08
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef AIModel_Impl_H_
#define AIModel_Impl_H_
#include <vector>
#include <thread>
#include <mutex>
#include "NvInfer.h"
#include "cuda_runtime_api.h"
#include "AI_Factory.h"
#include "Engine.h"
using namespace std;
// 模型输入输出最大允许的 节点数
#define MAX_MODEL_NODE_NUM 5
class AIModel_Impl : public AIModel_Base
{
public:
enum AI_Buffer_Type
{
AI_Buffer_Type_INPUT,
AI_Buffer_Type_OUTPUT,
AI_Buffer_Type_Count,
};
// 模型节点参数 一个模型包括多个节点,输入 输出。
struct Node_Config : public AI_Image
{
int type;
std::string name;
int ucharsize;
int floatsize;
int datalength;
Node_Config()
{
channel = 0;
width = 0;
height = 0;
type = AI_Buffer_Type_INPUT;
name = "";
ucharsize = 0;
floatsize = 0;
datalength = 0;
}
void copy(Node_Config tem)
{
this->type = tem.type;
this->channel = tem.channel;
this->width = tem.width;
this->height = tem.height;
this->name = tem.name;
this->ucharsize = tem.ucharsize;
this->floatsize = tem.floatsize;
this->datalength = tem.datalength;
}
void CalDataSize()
{
ucharsize = channel * width * height * sizeof(unsigned char);
floatsize = channel * width * height * sizeof(float);
datalength = channel * width * height;
}
};
// 流上的 节点参数信息。
struct Stream_Node_Config
{
Node_Config nodeConfig;
void *gpu_buffers;
void *gpu_ImgData; // uchar
float *cpu_floatData;
Stream_Node_Config()
{
gpu_buffers = NULL;
gpu_ImgData = NULL;
cpu_floatData = NULL;
}
~Stream_Node_Config()
{
if (gpu_buffers != NULL)
{
cudaFree(gpu_buffers);
gpu_buffers = NULL;
}
if (gpu_ImgData != NULL)
{
cudaFree(gpu_ImgData);
gpu_ImgData = NULL;
}
if (cpu_floatData != NULL)
{
delete[] cpu_floatData;
cpu_floatData = NULL;
}
}
};
// cuda上 一个流 包括的所有参数
struct Cuda_Stream_Config
{
int nstreamIdx;
cudaStream_t stream;
std::unique_ptr<nvinfer1::IExecutionContext> context;
std::shared_ptr<Stream_Node_Config> pstreamNode_input_0;
std::shared_ptr<Stream_Node_Config> pstreamNode_input_1;
std::shared_ptr<Stream_Node_Config> pstreamNode_output_0;
std::shared_ptr<Stream_Node_Config> pstreamNode_output_1;
std::shared_ptr<Stream_Node_Config> pstreamNode_output_2;
std::vector<std::shared_ptr<Stream_Node_Config>> streamConfigList;
Cuda_Stream_Config()
{
nstreamIdx = 0;
streamConfigList.clear();
pstreamNode_input_0 = nullptr;
pstreamNode_input_1 = nullptr;
pstreamNode_output_0 = nullptr;
pstreamNode_output_1 = nullptr;
pstreamNode_output_2 = nullptr;
}
~Cuda_Stream_Config()
{
cudaStreamDestroy(stream);
}
};
// GPU 上封装的参数信息
struct GPU_Engine
{
bool bsucc; // 是否初始化成功
int nGPUIdx; // GPU id号
std::shared_ptr<Engine> engine; // AI 模型 引擎
std::vector<std::shared_ptr<Cuda_Stream_Config>> cudaSteams; // 所有流
GPU_Engine()
{
nGPUIdx = 0;
cudaSteams.clear();
bsucc = false;
}
};
// AI 检测 顺序调用 gpu stream 流。
struct Det_GPU_Stram
{
std::mutex AI_mutex;
int nGPUIdx;
std::shared_ptr<Engine> engine; // AI 模型 引擎
std::shared_ptr<Cuda_Stream_Config> cuda_stream;
Det_GPU_Stram()
{
nGPUIdx = 0;
}
};
public:
AIModel_Impl();
~AIModel_Impl();
// 初始化函数
int Init(AIModelRun_Config config);
int AIDet(const cv::Mat &inImg, cv::Mat &outimg);
int AIDet(const cv::Mat &inImg, cv::Mat &outimg0, cv::Mat &outimg1);
int AIClass(const cv::Mat &inImg, float *fmaxScore);
private:
// 运行参数检查
int ModelRunConfigCheck(AIModelRun_Config &runConfig);
// 每个gpu 载入模型
int LoadEngine(int ngpuIdx);
// 解析 模型的信息
int GetEngineInfo1(std::shared_ptr<GPU_Engine> &pgpuengine);
int AI_Det_In_1_Out_1(Node_Config *pConfig_in, Node_Config *pConfig_out, const unsigned char *p_indata_0, unsigned char *p_outdata_1);
int AI_Det_In_1_Out_1_class(unsigned char *p_indata_0, float *fmaxScore);
int F2softmaxId(float *data, int class_num, float *fmaxScore);
private:
// 调用相关函数
int GetStream(std::shared_ptr<Det_GPU_Stram> &pdetStream);
cv::Mat InitMat(int channel, int w, int h);
private:
// 模型参数
AIModelRun_Config m_modelRun_Config;
// 模型的输入输出list
std::vector<Node_Config> m_modelNodeList;
// 输入 输出节点
Node_Config *m_pNode_input_0;
Node_Config *m_pNode_input_1;
Node_Config *m_pNode_output_0;
Node_Config *m_pNode_output_1;
Node_Config *m_pNode_output_2;
// 引擎列表,一个 gpu 一个引擎
std::vector<std::shared_ptr<GPU_Engine>> m_GPU_Engine;
// 检测信息
std::vector<std::shared_ptr<Det_GPU_Stram>> m_DetGPUStream;
int m_nALLStreamNum;
private:
// 上次使用的GPU stream Idx;
std::atomic<int> m_nLast_GPUStreamIdx;
};
#endif

@ -0,0 +1,20 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-07-08 17:55:31
* @LastEditors: xiewenji 527774126@qq.com
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef CUDA_Det_H_
#define CUDA_Det_H_
#include "cuda_runtime.h"
#include "cublas_v2.h"
#include "device_launch_parameters.h"
#include <iostream>
#include <stdio.h>
void Cuda_ucharToFloat_stream(const unsigned char* input, float* output, int size, cudaStream_t stream);
void Cuda_FloatTouchar_stream(const float* input, unsigned char* output, int size, cudaStream_t stream);
#endif

@ -0,0 +1,49 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-05 19:32:31
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-06 11:14:02
* @FilePath: /AI_SO_Test/AIEngineModule/include/Engine.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#ifndef Engine_H_
#define Engine_H_
#pragma once
#include <NvInfer.h>
#include <string>
#include <vector>
#include <memory>
#include <mutex>
#include <functional>
using namespace nvinfer1;
// 自定义删除器确保正确释放TensorRT资源
struct TensorRTDeleter
{
void operator()(nvinfer1::IRuntime *ptr) const noexcept;
void operator()(nvinfer1::ICudaEngine *ptr) const noexcept;
void operator()(nvinfer1::IExecutionContext *ptr) const noexcept; // 添加上下文删除器
};
class Engine
{
public:
Engine(int gpuId);
~Engine();
bool loadFromFile(const std::string &enginePath);
int getNbBindings() const;
std::string getBindingName(int index) const;
nvinfer1::Dims getBindingDims(int index) const;
bool bindingIsInput(int index) const;
nvinfer1::ICudaEngine *get() const { return engine_.get(); }
std::mutex mutex_;
std::unique_ptr<nvinfer1::ICudaEngine, TensorRTDeleter> engine_;
private:
int gpuId_;
std::unique_ptr<nvinfer1::IRuntime, TensorRTDeleter> runtime_;
};
#endif

@ -0,0 +1,241 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-03 09:48:19
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-24 10:29:29
* @FilePath: /AI_SO_Test/AIEngineModule/include_base/AI_Factory.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-04 14:41:18
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-03 10:27:59
* @FilePath: /AI_SO_Test/AIEngineModule/include_base/AI_Engine_Base.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#ifndef AI_Factory_H_
#define AI_Factory_H_
#include <string>
#include <opencv2/opencv.hpp>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <atomic>
#include <memory>
// GPU 可用信息
struct GPU_Config
{
int UseGPUList[4]; // 使用的GPU设备号
GPU_Config()
{
for (int i = 0; i < 4; i++)
{
UseGPUList[i] = -1;
}
UseGPUList[0] = 0;
UseGPUList[1] = 1;
}
int GetNum()
{
int num = 0;
for (int i = 0; i < 4; i++)
{
if (UseGPUList[i] >= 0)
{
num++;
}
}
return num;
}
void copy(GPU_Config tem)
{
for (int i = 0; i < 4; i++)
{
this->UseGPUList[i] = tem.UseGPUList[i];
}
}
};
// AI 模型 基础接口
class AIModel_Base
{
public:
enum Model_Input_Type
{
Input_NULL,
Input_HW,
Input_CHW,
Input_HWC,
};
// 模型相关参数
struct AIModelRun_Config
{
int Stream_num; // 流的个数
bool IsClass; // 是分类
std::string strPath; // 模型类型
std::string strName; // 名称,别名
Model_Input_Type inputType; // 数据格式类型
GPU_Config gpuconfig;
AIModelRun_Config()
{
strPath = "";
strName = "";
inputType = Input_NULL;
Stream_num = 1;
IsClass = false;
}
void Copy(AIModelRun_Config tem)
{
this->Stream_num = tem.Stream_num;
this->strPath = tem.strPath;
this->strName = tem.strName;
this->inputType = tem.inputType;
this->IsClass = tem.IsClass;
this->gpuconfig.copy(tem.gpuconfig);
}
void print(std::string str)
{
printf("%s:Stream_num %d Path:%s inputType %d\n", str.c_str(), Stream_num, strPath.c_str(), inputType);
}
};
struct AI_Image
{
int channel;
int width;
int height;
AI_Image()
{
channel = 0;
width = 0;
height = 0;
}
void copy(AI_Image tem)
{
this->channel = tem.channel;
this->height = tem.height;
this->width = tem.width;
}
void print()
{
printf("[c w h] %d %d %d\n", channel, width, height);
}
};
public:
virtual ~AIModel_Base() = default;
static std::shared_ptr<AIModel_Base> GetInstance();
// 初始化函数
virtual int Init(AIModelRun_Config config) = 0;
virtual int AIDet(const cv::Mat &inImg, cv::Mat &outimg) = 0;
virtual int AIDet(const cv::Mat &inImg, cv::Mat &outimg0, cv::Mat &outimg1) = 0;
virtual int AIClass(const cv::Mat &inImg, float *fmaxScore) = 0;
public:
bool m_bInitSuccess = false;
AI_Image input_0;
AI_Image input_1;
AI_Image output_0;
AI_Image output_1;
AI_Image output_2;
};
// 管理所有 模型
class AIFactory
{
public:
AIFactory();
~AIFactory();
static std::shared_ptr<AIFactory> GetInstance();
// 初始化所有模型
int InitALLAIModle(GPU_Config gupconfig);
private:
public:
std::shared_ptr<AIModel_Base> AI_defect_NF; // BOE测试
std::shared_ptr<AIModel_Base> AI_defect_Type2; // 第二个检测模型
std::shared_ptr<AIModel_Base> AI_defect_UP; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_Chess; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_YX_1; // L0
std::shared_ptr<AIModel_Base> AI_defect_YX_2; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_Cls; // 1023
std::shared_ptr<AIModel_Base> AI_defect_Cls_L0; //
std::shared_ptr<AIModel_Base> AI_defect_zf; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_127Cell; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_RE_POL; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_RE_AD; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_Edge_Big; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_Edge_Samll; // L127 L255
std::shared_ptr<AIModel_Base> AI_defect_LackPol; // 缺pol检测
std::shared_ptr<AIModel_Base> AI_defect_MarkLine; // 缺pol检测
std::shared_ptr<AIModel_Base> AI_defect_Edge_QX; // 边缘缺陷检测
private:
// 模型是否都加载完成了。
bool m_bInitSucc = false;
};
// 多线程推理
class AIMulThreadRunBase
{
public:
struct AITask
{
cv::Rect roi;
cv::Size srcroi;
int id;
cv::Mat input;
std::shared_ptr<cv::Mat> output;
std::shared_ptr<AIModel_Base> engine;
bool bclass = false;
int cls_label = 0;
float cls_score = 0.0;
int userflag = 0;
};
public:
AIMulThreadRunBase();
~AIMulThreadRunBase();
void Start(int num_threads = 2);
void Stop();
void SubmitTask(std::shared_ptr<AITask> task);
bool PopResult(std::shared_ptr<AITask> &result);
// 新增接口,查询当前正在处理的任务数
int GetProcessingCount() const { return m_processing_count_.load(); }
std::atomic<int> m_detnum; // 当前正在执行任务数
private:
void ThreadLoop();
private:
std::queue<std::shared_ptr<AITask>> m_tasks_;
std::queue<std::shared_ptr<AITask>> m_results_;
std::vector<std::thread> m_workers_;
std::mutex m_task_mutex_;
std::mutex m_result_mutex_;
std::mutex m_AI_mutex_;
std::condition_variable m_task_cv_;
std::atomic<bool> m_running_;
std::atomic<int> m_processing_count_; // 当前正在执行任务数
};
#endif

@ -0,0 +1,675 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-03 10:44:31
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-06 22:29:55
* @FilePath: /AI_SO_Test/AIEngineModule/src/AIModel_Impl.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "AIModel_Impl.h"
#include "CUDA_DataChange.cuh"
#include <cstdio>
namespace
{
thread_local int g_last_cuda_device = -1;
bool EnsureCudaDevice(int gpuIdx)
{
if (g_last_cuda_device == gpuIdx)
{
return true;
}
cudaError_t err = cudaSetDevice(gpuIdx);
if (err != cudaSuccess)
{
std::fprintf(stderr, "[AIEngine] cudaSetDevice(%d) failed: %s\n", gpuIdx, cudaGetErrorString(err));
return false;
}
g_last_cuda_device = gpuIdx;
return true;
}
} // namespace
AIModel_Impl::AIModel_Impl() : m_nLast_GPUStreamIdx(0)
{
m_bInitSuccess = false;
m_GPU_Engine.clear();
m_modelNodeList.clear();
m_pNode_input_0 = NULL;
m_pNode_input_1 = NULL;
m_pNode_output_0 = NULL;
m_pNode_output_1 = NULL;
m_pNode_output_2 = NULL;
m_DetGPUStream.clear();
m_nALLStreamNum = 0;
}
AIModel_Impl::~AIModel_Impl()
{
}
int AIModel_Impl::Init(AIModelRun_Config config)
{
m_modelRun_Config.Copy(config);
printf(">>> %s Init Start \n", m_modelRun_Config.strName.c_str());
if (m_bInitSuccess)
{
printf("strName %s Init Success %d ************ return \n", m_modelRun_Config.strName.c_str(), m_bInitSuccess);
return 0;
}
int re = 0;
re = ModelRunConfigCheck(m_modelRun_Config);
if (re != 0)
{
printf("strName %s Init Error =%d run Config error \n", m_modelRun_Config.strName.c_str(), re);
return re;
}
// 不同显卡 单独 载入模型
if (m_modelRun_Config.gpuconfig.UseGPUList[0] >= 0)
{
re = LoadEngine(m_modelRun_Config.gpuconfig.UseGPUList[0]);
// 加载失败
if (re != 0)
{
}
}
if (m_modelRun_Config.gpuconfig.UseGPUList[1] >= 0)
{
re = LoadEngine(m_modelRun_Config.gpuconfig.UseGPUList[1]);
// 加载失败
if (re != 0)
{
}
}
int nGPUNum = m_GPU_Engine.size();
// 模型载入失败
if (nGPUNum <= 0 || nGPUNum > 2)
{
printf(" %s model Init error \n", m_modelRun_Config.strName.c_str());
return 2;
}
int m_nOutImgNum = 0;
for (int i = 0; i < m_modelNodeList.size(); i++)
{
if (m_modelNodeList.at(i).type == AI_Buffer_Type_INPUT)
{
if (m_pNode_input_0 == NULL)
{
m_pNode_input_0 = &m_modelNodeList.at(i);
input_0.copy(*m_pNode_input_0);
}
else
{
m_pNode_input_1 = &m_modelNodeList.at(i);
input_1.copy(*m_pNode_input_1);
}
}
else
{
m_nOutImgNum++;
if (m_pNode_output_0 == NULL)
{
m_pNode_output_0 = &m_modelNodeList.at(i);
output_0.copy(*m_pNode_output_0);
}
else if (m_pNode_output_1 == NULL)
{
m_pNode_output_1 = &m_modelNodeList.at(i);
output_1.copy(*m_pNode_output_1);
}
else
{
m_pNode_output_2 = &m_modelNodeList.at(i);
output_2.copy(*m_pNode_output_2);
}
}
}
if (m_pNode_input_0 == NULL || m_pNode_output_0 == NULL)
{
printf(" %s model Init error \n", m_modelRun_Config.strName.c_str());
return 3;
}
int streamNum = m_GPU_Engine.at(0)->cudaSteams.size();
// 生产推理用的 参数信息
if (m_GPU_Engine.size() > 1)
{
if (m_GPU_Engine.at(0)->cudaSteams.size() != m_GPU_Engine.at(1)->cudaSteams.size())
{
printf(" %s model Init error \n", m_modelRun_Config.strName.c_str());
return 3;
}
}
if (streamNum <= 0)
{
printf(" %s model Init streamNum error \n", m_modelRun_Config.strName.c_str());
return 4;
}
// 显示初始化信息
if (true)
{
printf("Model Name :%s GUP engine Num %ld\n", m_modelRun_Config.strName.c_str(), m_GPU_Engine.size());
for (const auto &ge : m_GPU_Engine)
{
printf(" gpu %d status %d strem Num %ld \n", ge->nGPUIdx, ge->bsucc, ge->cudaSteams.size());
for (const auto &psteam : ge->cudaSteams)
{
printf(" steam %d \n", psteam->nstreamIdx);
for (const auto &pcon : psteam->streamConfigList)
{
printf(" type %d [chw] %d %d %d input %p output %p\n",
pcon->nodeConfig.type, pcon->nodeConfig.channel, pcon->nodeConfig.height, pcon->nodeConfig.width,
pcon->gpu_buffers, pcon->gpu_ImgData);
}
}
}
}
// 把所有gup 的所有stream 都放到一起,方便调用。
m_DetGPUStream.reserve(nGPUNum * streamNum);
for (int i = 0; i < streamNum; i++)
{
for (int igpu = 0; igpu < nGPUNum; igpu++)
{
std::shared_ptr<Det_GPU_Stram> temDetStream = std::make_shared<Det_GPU_Stram>();
temDetStream->nGPUIdx = m_GPU_Engine.at(igpu)->nGPUIdx;
temDetStream->engine = m_GPU_Engine.at(igpu)->engine;
temDetStream->cuda_stream = m_GPU_Engine.at(igpu)->cudaSteams.at(i);
m_DetGPUStream.push_back(temDetStream);
}
}
m_nALLStreamNum = m_DetGPUStream.size();
printf("========********* Model Name :%s GUP engine Num %ld **************=============\n", m_modelRun_Config.strName.c_str(), m_GPU_Engine.size());
for (const auto steam : m_DetGPUStream)
{
printf(">>> gpu %d stream %d \n",
steam->nGPUIdx, steam->cuda_stream->nstreamIdx);
}
if (config.IsClass)
{
cv::Mat temimg = cv::Mat::zeros(input_0.height, input_0.width, CV_8UC1);
float fs = 0;
for (int ig = 0; ig < nGPUNum * 2; ig++)
{
AIClass(temimg, &fs);
}
}
else
{
if (m_nOutImgNum == 1)
{
cv::Mat temimg = cv::Mat::zeros(input_0.height, input_0.width, CV_8UC1);
cv::Mat outimg = cv::Mat::zeros(output_0.height, output_0.width, CV_8UC1);
for (int ig = 0; ig < nGPUNum * 2; ig++)
{
AIDet(temimg, outimg);
printf(">>>test AIDet ====1================= \n");
}
}
else if (m_nOutImgNum == 2)
{
cv::Mat temimg = cv::Mat::zeros(input_0.height, input_0.width, CV_8UC1);
cv::Mat outimg = cv::Mat::zeros(output_0.height, output_0.width, CV_8UC1);
cv::Mat outimg1 = cv::Mat::zeros(output_1.height, output_1.width, CV_8UC1);
for (int ig = 0; ig < nGPUNum * 2; ig++)
{
AIDet(temimg, outimg, outimg1);
printf(">>>test AIDet =====2================ \n");
}
}
}
m_bInitSuccess = true;
return 0;
}
cv::Mat AIModel_Impl::InitMat(int channel, int w, int h)
{
if (w <= 0 || h <= 0 || channel <= 0 || channel > 3)
{
return cv::Mat();
}
cv::Mat dst;
if (channel == 1)
{
dst = cv::Mat(h, w, CV_8UC1, cv::Scalar(0));
}
else
{
dst = cv::Mat(h, w, CV_8UC3, cv::Scalar(0, 0, 0));
}
return dst;
}
int AIModel_Impl::AIDet(const cv::Mat &inImg, cv::Mat &outimg)
{
// 1、准备数据
if (m_pNode_input_0 == NULL || m_pNode_output_0 == NULL)
{
printf("AIDet: Node Config INput output Node error \n");
return 1;
}
// std::this_thread::sleep_for(std::chrono::milliseconds(2)); // Sleep for 100 milliseconds
uchar *p_indata_0 = (uchar *)inImg.data;
int outType = m_pNode_output_0->channel == 1 ? CV_8UC1 : CV_8UC3;
if (outimg.empty() || outimg.rows != m_pNode_output_0->height ||
outimg.cols != m_pNode_output_0->width || outimg.type() != outType)
{
outimg.create(m_pNode_output_0->height, m_pNode_output_0->width, outType);
}
uchar *p_outdata_1 = (uchar *)outimg.data;
if (!m_bInitSuccess)
{
return 2;
}
AI_Det_In_1_Out_1(m_pNode_input_0, m_pNode_output_0, p_indata_0, p_outdata_1);
return 0;
}
int AIModel_Impl::AIDet(const cv::Mat &inImg, cv::Mat &outimg0, cv::Mat &outimg1)
{
return 0;
}
int AIModel_Impl::AIClass(const cv::Mat &inImg, float *fmaxScore)
{
// 1、准备数据
if (m_pNode_input_0 == NULL || m_pNode_output_0 == NULL)
{
printf("AIDet: Node Config INput output Node error \n");
return -1;
}
if (!m_bInitSuccess)
{
return -2;
}
uchar *p_indata_0 = (uchar *)inImg.data;
int class_dix = 0;
class_dix = AI_Det_In_1_Out_1_class(p_indata_0, fmaxScore);
return class_dix;
}
// 检测模型的运行参数是否合法,是否正常
int AIModel_Impl::ModelRunConfigCheck(AIModelRun_Config &runConfig)
{
// GPU 数量判断
if (runConfig.gpuconfig.GetNum() == 0)
{
return 1;
}
if (runConfig.strPath == "")
{
printf(" %s model path is error \n", runConfig.strName.c_str());
return 2;
}
if (runConfig.Stream_num <= 0)
{
runConfig.Stream_num = 1;
}
if (runConfig.Stream_num > 4)
{
runConfig.Stream_num = 4;
}
return 0;
}
// 载入模型。。。。
int AIModel_Impl::LoadEngine(int ngpuIdx)
{
std::shared_ptr<GPU_Engine> gpuEngine = std::make_shared<GPU_Engine>();
gpuEngine->engine = std::make_shared<Engine>(ngpuIdx);
gpuEngine->nGPUIdx = ngpuIdx;
if (!gpuEngine->engine)
{
printf("Engine Create error\n");
return -1;
}
// 1、加载模型
bool reload = gpuEngine->engine->loadFromFile(m_modelRun_Config.strPath);
if (!reload)
{
printf("GPU %d Load error %s\n", ngpuIdx, m_modelRun_Config.strPath.c_str());
printf("Load model error\n");
return -2;
}
printf("%s GPU %d Load succ %s\n", m_modelRun_Config.strName.c_str(), ngpuIdx, m_modelRun_Config.strPath.c_str());
// 2、 解析 egengine的 相关信息
int re = GetEngineInfo1(gpuEngine);
if (re != 0)
{
return re;
}
// 没有输入输出 节点。
if (m_modelNodeList.size() <= 0 || m_modelNodeList.size() > MAX_MODEL_NODE_NUM)
{
printf("Load model input output error\n");
return -3;
}
cudaSetDevice(ngpuIdx);
// 3、 申请显存
for (int i = 0; i < m_modelRun_Config.Stream_num; i++)
{
std::shared_ptr<Cuda_Stream_Config> cudasteam = std::make_shared<Cuda_Stream_Config>();
cudasteam->nstreamIdx = i;
if (cudaStreamCreateWithFlags(&cudasteam->stream, cudaStreamNonBlocking) != cudaSuccess)
{
printf("Failed to create CUDA stream\n");
return -4;
}
cudasteam->context = std::unique_ptr<nvinfer1::IExecutionContext>(
gpuEngine->engine->engine_->createExecutionContext());
// printf("----- stream %d \n", i);
// 初始化 数据 内存
for (int j = 0; j < m_modelNodeList.size(); j++)
{
std::shared_ptr<Stream_Node_Config> steamNodeconfig = std::make_shared<Stream_Node_Config>();
steamNodeconfig->nodeConfig.copy(m_modelNodeList.at(j));
cudaMalloc(&steamNodeconfig->gpu_buffers, steamNodeconfig->nodeConfig.floatsize);
cudaMalloc(&steamNodeconfig->gpu_ImgData, steamNodeconfig->nodeConfig.ucharsize);
// 分类 的模型
if (m_modelRun_Config.IsClass)
{
if (steamNodeconfig->cpu_floatData)
{
delete[] steamNodeconfig->cpu_floatData;
steamNodeconfig->cpu_floatData = NULL;
}
steamNodeconfig->cpu_floatData = new float[steamNodeconfig->nodeConfig.datalength];
}
printf("-----******GPU %d stream %d cuda malloc %d inOrout %d [chw] %d*%d*%d \n",
ngpuIdx, i, j, steamNodeconfig->nodeConfig.type, steamNodeconfig->nodeConfig.channel,
steamNodeconfig->nodeConfig.height, steamNodeconfig->nodeConfig.width);
if (m_modelNodeList.at(j).type == AI_Buffer_Type_INPUT)
{
if (cudasteam->pstreamNode_input_0 == nullptr)
{
cudasteam->pstreamNode_input_0 = steamNodeconfig;
}
else
{
cudasteam->pstreamNode_input_1 = steamNodeconfig;
}
}
else
{
if (cudasteam->pstreamNode_output_0 == nullptr)
{
cudasteam->pstreamNode_output_0 = steamNodeconfig;
}
else if (cudasteam->pstreamNode_output_1 == nullptr)
{
cudasteam->pstreamNode_output_1 = steamNodeconfig;
}
else
{
cudasteam->pstreamNode_output_2 = steamNodeconfig;
}
}
cudasteam->streamConfigList.push_back(steamNodeconfig);
}
gpuEngine->cudaSteams.push_back(cudasteam);
}
gpuEngine->bsucc = true;
m_GPU_Engine.push_back(gpuEngine);
return 0;
}
int AIModel_Impl::GetEngineInfo1(std::shared_ptr<GPU_Engine> &pgpuengine)
{
int nInputNum = pgpuengine->engine->getNbBindings();
m_modelNodeList.erase(m_modelNodeList.begin(), m_modelNodeList.end());
m_modelNodeList.clear();
for (int i = 0; i < nInputNum; i++)
{
Node_Config node_config;
std::string name = pgpuengine->engine->getBindingName(i);
node_config.name = name;
Dims dims = pgpuengine->engine->getBindingDims(i);
if (pgpuengine->engine->bindingIsInput(i))
{
std::cout << "Input: " << name << "\n";
node_config.type = AI_Buffer_Type_INPUT;
}
else
{
std::cout << "Output: " << name << "\n";
node_config.type = AI_Buffer_Type_OUTPUT;
}
std::cout << "dims.nbDims: " << dims.nbDims << "\n";
if (dims.nbDims == 4)
{
switch (m_modelRun_Config.inputType)
{
case Input_CHW:
node_config.channel = dims.d[1];
node_config.height = dims.d[2];
node_config.width = dims.d[3];
break;
case Input_HWC:
node_config.height = dims.d[1];
node_config.width = dims.d[2];
node_config.channel = dims.d[3];
break;
default:
node_config.channel = dims.d[1];
node_config.height = dims.d[2];
node_config.width = dims.d[3];
break;
}
}
else if (dims.nbDims == 3)
{
switch (m_modelRun_Config.inputType)
{
case Input_CHW:
node_config.channel = dims.d[0];
node_config.height = dims.d[1];
node_config.width = dims.d[2];
break;
case Input_HWC:
node_config.height = dims.d[0];
node_config.width = dims.d[1];
node_config.channel = dims.d[2];
break;
default:
node_config.channel = dims.d[0];
node_config.height = dims.d[1];
node_config.width = dims.d[2];
break;
}
if (dims.d[0] == 1 || dims.d[2] != 1)
{
node_config.channel = dims.d[0];
node_config.height = dims.d[1];
node_config.width = dims.d[2];
}
if (dims.d[0] != 1 || dims.d[2] == 1)
{
node_config.channel = dims.d[2];
node_config.height = dims.d[0];
node_config.width = dims.d[1];
}
}
else if (dims.nbDims == 2)
{
node_config.channel = 1;
node_config.height = dims.d[0];
node_config.width = dims.d[1];
}
else if (dims.nbDims == 1)
{
node_config.channel = 1;
node_config.height = dims.d[0];
node_config.width = 1;
}
else
{
printf("engine C H W is error\n");
return -2;
}
node_config.CalDataSize();
m_modelNodeList.push_back(node_config);
printf("dim: ");
for (int di = 0; di < dims.nbDims; di++)
{
printf(" %ld ", dims.d[di]);
}
printf(" \n");
printf("C H W [%d %d %d]\n", node_config.channel, node_config.height, node_config.width);
}
return 0;
}
int AIModel_Impl::AI_Det_In_1_Out_1(Node_Config *pConfig_in, Node_Config *pConfig_out, const unsigned char *p_indata_0, unsigned char *p_outdata_1)
{
// printf("=== s1 ");
std::shared_ptr<Det_GPU_Stram> pdetStream;
if (GetStream(pdetStream) != 0 || !pdetStream)
{
return -1;
}
// printf("=== s2 ");
std::lock_guard<std::mutex> lock(pdetStream->AI_mutex);
// printf(" ss g %d s %d -- ", pdetStream->nGPUIdx, pdetStream->cuda_stream->nstreamIdx);
// // 设置 显卡ID
if (!EnsureCudaDevice(pdetStream->nGPUIdx))
{
return -1;
}
cudaMemcpyAsync(pdetStream->cuda_stream->pstreamNode_input_0->gpu_ImgData,
p_indata_0, pConfig_in->ucharsize, cudaMemcpyHostToDevice, pdetStream->cuda_stream->stream);
// // // 在显存中 图片数据从 uchar 转到 float
Cuda_ucharToFloat_stream((unsigned char *)pdetStream->cuda_stream->pstreamNode_input_0->gpu_ImgData,
(float *)pdetStream->cuda_stream->pstreamNode_input_0->gpu_buffers, pConfig_in->datalength, pdetStream->cuda_stream->stream);
pdetStream->cuda_stream->context->setTensorAddress(pConfig_in->name.c_str(), pdetStream->cuda_stream->pstreamNode_input_0->gpu_buffers);
pdetStream->cuda_stream->context->setTensorAddress(pConfig_out->name.c_str(), pdetStream->cuda_stream->pstreamNode_output_0->gpu_buffers);
pdetStream->cuda_stream->context->enqueueV3(pdetStream->cuda_stream->stream);
Cuda_FloatTouchar_stream((float *)pdetStream->cuda_stream->pstreamNode_output_0->gpu_buffers,
(unsigned char *)pdetStream->cuda_stream->pstreamNode_output_0->gpu_ImgData, pConfig_out->datalength, pdetStream->cuda_stream->stream);
cudaMemcpyAsync(p_outdata_1, pdetStream->cuda_stream->pstreamNode_output_0->gpu_ImgData,
pConfig_out->ucharsize, cudaMemcpyDeviceToHost, pdetStream->cuda_stream->stream);
cudaStreamSynchronize(pdetStream->cuda_stream->stream);
// printf("**ee g %d s %d ** \n", pdetStream->nGPUIdx, pdetStream->cuda_stream->nstreamIdx);
return 0;
}
int AIModel_Impl::GetStream(std::shared_ptr<Det_GPU_Stram> &pdetStream)
{
if (m_nALLStreamNum <= 0)
{
pdetStream = nullptr;
return -1;
}
int sidx = m_nLast_GPUStreamIdx.fetch_add(1, std::memory_order_relaxed) % m_nALLStreamNum;
pdetStream = m_DetGPUStream.at(sidx);
return 0;
}
int AIModel_Impl::AI_Det_In_1_Out_1_class(unsigned char *p_indata_0, float *fmaxScore)
{
std::shared_ptr<Det_GPU_Stram> pdetStream;
if (GetStream(pdetStream) != 0 || !pdetStream)
{
return -1;
}
// printf("=== s2 ");
std::lock_guard<std::mutex> lock(pdetStream->AI_mutex);
// printf(" ss g %d s %d -- ", pdetStream->nGPUIdx, pdetStream->cuda_stream->nstreamIdx);
// // 设置 显卡ID
std::shared_ptr<Stream_Node_Config> p_input_0 = pdetStream->cuda_stream->pstreamNode_input_0;
std::shared_ptr<Stream_Node_Config> p_output_0 = pdetStream->cuda_stream->pstreamNode_output_0;
if (!EnsureCudaDevice(pdetStream->nGPUIdx))
{
return -1;
}
cudaMemcpyAsync(p_input_0->gpu_ImgData, p_indata_0,
p_input_0->nodeConfig.ucharsize, cudaMemcpyHostToDevice, pdetStream->cuda_stream->stream);
// // // 在显存中 图片数据从 uchar 转到 float
Cuda_ucharToFloat_stream((unsigned char *)p_input_0->gpu_ImgData,
(float *)p_input_0->gpu_buffers, p_input_0->nodeConfig.datalength, pdetStream->cuda_stream->stream);
pdetStream->cuda_stream->context->setTensorAddress(p_input_0->nodeConfig.name.c_str(), p_input_0->gpu_buffers);
pdetStream->cuda_stream->context->setTensorAddress(p_output_0->nodeConfig.name.c_str(), p_output_0->gpu_buffers);
pdetStream->cuda_stream->context->enqueueV3(pdetStream->cuda_stream->stream);
cudaMemcpyAsync(p_output_0->cpu_floatData, p_output_0->gpu_buffers,
p_output_0->nodeConfig.floatsize, cudaMemcpyDeviceToHost, pdetStream->cuda_stream->stream);
cudaStreamSynchronize(pdetStream->cuda_stream->stream);
int label = F2softmaxId(p_output_0->cpu_floatData, p_output_0->nodeConfig.datalength, fmaxScore);
return label;
}
int AIModel_Impl::F2softmaxId(float *data, int class_num, float *fmaxScore)
{
int cls_num = class_num;
float total = 0;
for (int i = 0; i < cls_num; i++)
{
// std::cout<<"data["<<i<<"]="<<data[i]<<std::endl;
total += exp(data[i]);
}
// std::cout<<"total="<<total<<std::endl;
// std::vector<float> output;//这样才可以用push_back-但相比于=更耗时
std::vector<float> output(cls_num);
for (int i = 0; i < output.size(); i++)
{
float outi = (float)exp(data[i]) / (float)total;
output[i] = outi;
// output.push_back(outi);
// std::cout<<"output["<<i<<"]="<<output[i]<<std::endl;
}
int max_id = 0;
float max_score = 0;
for (int i = 0; i < output.size(); i++)
{
// std::cout << "output[" << i << "]=" << output[i] << std::endl;
if (output[i] > max_score)
{
max_id = i;
max_score = output[i];
}
}
*fmaxScore = max_score;
// std::cout << "F2softmaxId()----------------------------------max_score=" << max_score << std::endl; // 1023dyy
// std::cout << "F2softmaxId()----------------------------------max_id=" << max_id << std::endl; // 1023dyy
return max_id;
}

@ -0,0 +1,120 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-11 11:35:40
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-15 10:29:44
* @FilePath: /BOE_Bounding/AIEngineModule/src/AIMulThreadRunBase.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "AI_Factory.h"
#include <iostream>
#include <chrono>
#include <sys/time.h>
long getcurTime4444()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000;
}
AIMulThreadRunBase::AIMulThreadRunBase() : m_running_(false), m_processing_count_(0) {}
AIMulThreadRunBase::~AIMulThreadRunBase()
{
Stop();
}
void AIMulThreadRunBase::Start(int num_threads)
{
if (m_running_)
return;
m_running_ = true;
m_detnum = 0;
// num_threads = 2;
// 仅启动1个线程
for (int i = 0; i < num_threads; ++i)
{
m_workers_.emplace_back(&AIMulThreadRunBase::ThreadLoop, this);
}
}
void AIMulThreadRunBase::Stop()
{
m_running_ = false;
m_task_cv_.notify_all();
for (auto &t : m_workers_)
{
if (t.joinable())
t.join();
}
m_workers_.clear();
}
void AIMulThreadRunBase::SubmitTask(std::shared_ptr<AITask> task)
{
{
std::lock_guard<std::mutex> lock(m_task_mutex_);
m_tasks_.push(task);
}
m_processing_count_++;
m_task_cv_.notify_one();
}
bool AIMulThreadRunBase::PopResult(std::shared_ptr<AITask> &result)
{
std::lock_guard<std::mutex> lock(m_result_mutex_);
if (m_results_.empty())
return false;
result = m_results_.front();
m_results_.pop();
return true;
}
void AIMulThreadRunBase::ThreadLoop()
{
while (m_running_)
{
std::shared_ptr<AITask> task;
{
std::unique_lock<std::mutex> lock(m_task_mutex_);
m_task_cv_.wait(lock, [this]()
{ return !m_tasks_.empty() || !m_running_; });
if (!m_running_ && m_tasks_.empty())
return;
task = std::move(m_tasks_.front());
m_tasks_.pop();
}
if (task->bclass)
{
// 执行推理
if (task->engine)
{
// std::lock_guard<std::mutex> lock(m_AI_mutex_);
// long t1 = getcurTime4444();
task->cls_label = task->engine->AIClass(task->input, &task->cls_score);
// long t2 = getcurTime4444();
// printf("det time %d m_tasks_ size %ld\n", t2 - t1,m_tasks_.size());
}
}
else
{
// 执行推理
if (task->engine && task->output)
{
// std::lock_guard<std::mutex> lock(m_AI_mutex_);
// long t1 = getcurTime4444();
task->engine->AIDet(task->input, *task->output);
// long t2 = getcurTime4444();
// printf("det time %d m_tasks_ size %ld\n", t2 - t1,m_tasks_.size());
}
}
{
std::lock_guard<std::mutex> lock(m_result_mutex_);
m_results_.push(task);
}
// m_detnum++;
m_processing_count_--;
}
}

@ -0,0 +1,237 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-03 10:33:48
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-25 15:42:47
* @FilePath: /AI_SO_Test/AIEngineModule/src/AI_Factory.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "AI_Factory.h"
#include "AIModel_Impl.h"
std::shared_ptr<AIModel_Base> AIModel_Base::GetInstance()
{
std::shared_ptr<AIModel_Base> instance = std::make_shared<AIModel_Impl>();
return instance;
}
AIFactory::AIFactory()
{
}
AIFactory::~AIFactory()
{
}
std::shared_ptr<AIFactory> AIFactory::GetInstance()
{
static std::shared_ptr<AIFactory> instance = std::make_shared<AIFactory>();
return instance;
}
int AIFactory::InitALLAIModle(GPU_Config gupconfig)
{
if (gupconfig.GetNum() == 0)
{
printf("GPU Num Error \n");
return 1;
}
// 主检测
if (!AI_defect_NF)
{
AI_defect_NF = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect.engine";
boe_config.inputType = AIModel_Base::Input_CHW;
boe_config.strName = "Base_detect";
boe_config.Stream_num = 2;
AI_defect_NF->Init(boe_config);
}
// 黑白画面模型
if (!AI_defect_Type2)
{
AI_defect_Type2 = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_WTB.engine";
boe_config.inputType = AIModel_Base::Input_CHW;
boe_config.strName = "WTB_detect";
boe_config.Stream_num = 2;
AI_defect_Type2->Init(boe_config);
}
// UP画面模型
if (!AI_defect_UP)
{
AI_defect_UP = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_UP.engine";
boe_config.inputType = AIModel_Base::Input_CHW;
boe_config.strName = "UP_detect";
boe_config.Stream_num = 2;
AI_defect_UP->Init(boe_config);
}
// UP画面模型
if (!AI_defect_Chess)
{
AI_defect_Chess = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_CHESS.engine";
boe_config.inputType = AIModel_Base::Input_CHW;
boe_config.strName = "chess_detect";
boe_config.Stream_num = 2;
AI_defect_Chess->Init(boe_config);
}
// 异显
if (!AI_defect_YX_1)
{
AI_defect_YX_1 = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_YX_L0.engine";
boe_config.strName = "YX1";
boe_config.inputType = AIModel_Base::Input_CHW;
AI_defect_YX_1->Init(boe_config);
}
if (!AI_defect_YX_2)
{
AI_defect_YX_2 = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_YX_L127L255.engine";
boe_config.strName = "YX2";
boe_config.inputType = AIModel_Base::Input_CHW;
AI_defect_YX_2->Init(boe_config);
}
// 分类
if (!AI_defect_Cls_L0)
{
AI_defect_Cls_L0 = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config jbl_config;
jbl_config.gpuconfig.copy(gupconfig);
jbl_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/class_14.engine";
jbl_config.inputType = AIModel_Base::Input_HWC;
jbl_config.strName = "14_Class";
jbl_config.IsClass = true;
AI_defect_Cls_L0->Init(jbl_config);
}
if (!AI_defect_Cls)
{
AI_defect_Cls = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config jbl_config;
jbl_config.gpuconfig.copy(gupconfig);
jbl_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/class_14.engine";
jbl_config.inputType = AIModel_Base::Input_HWC;
jbl_config.strName = "old_Class";
jbl_config.IsClass = true;
AI_defect_Cls->Init(jbl_config);
}
// 字符 检测
if (!AI_defect_zf)
{
AI_defect_zf = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_zf.engine";
boe_config.strName = "zf";
boe_config.inputType = AIModel_Base::Input_CHW;
AI_defect_zf->Init(boe_config);
}
// 字符 127cell
if (!AI_defect_127Cell)
{
AI_defect_127Cell = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_L127.engine";
boe_config.strName = "127Cell";
boe_config.inputType = AIModel_Base::Input_CHW;
AI_defect_127Cell->Init(boe_config);
}
// 精确检测 POL 异物
if (!AI_defect_RE_POL)
{
AI_defect_RE_POL = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/BOE_POL_128x128.engine";
boe_config.strName = "RE_POL";
boe_config.inputType = AIModel_Base::Input_CHW;
AI_defect_RE_POL->Init(boe_config);
}
// 精确检测 AD 异物
if (!AI_defect_RE_AD)
{
AI_defect_RE_AD = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/BOE_AD_128x128.engine";
boe_config.strName = "RE_POL";
boe_config.inputType = AIModel_Base::Input_CHW;
AI_defect_RE_AD->Init(boe_config);
}
// 边缘模型
if (!AI_defect_Edge_Big)
{
AI_defect_Edge_Big = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/Edge_Big.engine";
boe_config.strName = "Edge_Big";
boe_config.inputType = AIModel_Base::Input_HWC;
AI_defect_Edge_Big->Init(boe_config);
}
if (!AI_defect_Edge_Samll)
{
AI_defect_Edge_Samll = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/Edge_Small.engine";
boe_config.inputType = AIModel_Base::Input_HWC;
boe_config.strName = "Edge_Small";
AI_defect_Edge_Samll->Init(boe_config);
}
// 缺pol检测
if (!AI_defect_LackPol)
{
AI_defect_LackPol = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/BOE_LOSSPOL.engine";
boe_config.inputType = AIModel_Base::Input_CHW;
boe_config.strName = "BOE_LOSSPOL";
AI_defect_LackPol->Init(boe_config);
}
// 缺pol检测
if (!AI_defect_MarkLine)
{
AI_defect_MarkLine = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/defect_MARK_LINE.engine";
boe_config.inputType = AIModel_Base::Input_CHW;
boe_config.strName = "MarkLine";
AI_defect_MarkLine->Init(boe_config);
}
// 缺pol检测
if (!AI_defect_Edge_QX)
{
AI_defect_Edge_QX = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config boe_config;
boe_config.gpuconfig.copy(gupconfig);
boe_config.strPath = "/home/aidlux/BOE/UseModel_Cell_ET/BOE_Edge_320x320.engine";
boe_config.inputType = AIModel_Base::Input_CHW;
boe_config.strName = "Edge_QX";
AI_defect_Edge_QX->Init(boe_config);
}
m_bInitSucc = true;
return 0;
}

@ -0,0 +1,34 @@
#include "CUDA_DataChange.cuh"
__global__ void ucharToFloat_stream(const unsigned char *input, float *output, int size)
{
int tid = blockIdx.x * blockDim.x + threadIdx.x;
if (tid < size)
{
output[tid] = static_cast<float>(input[tid]);
}
}
__global__ void floatToUchar_stream(const float *input, unsigned char *output, int size)
{
int tid = blockIdx.x * blockDim.x + threadIdx.x;
if (tid < size)
{
output[tid] = static_cast<unsigned char>(input[tid]);
}
}
void Cuda_ucharToFloat_stream(const unsigned char *input, float *output, int size, cudaStream_t stream)
{
int blockSize = 1024;
int numBlocks = (size + blockSize - 1) / blockSize;
ucharToFloat_stream<<<numBlocks, blockSize, 0, stream>>>(input, output, size);
}
void Cuda_FloatTouchar_stream(const float *input, unsigned char *output, int size, cudaStream_t stream)
{
int blockSize = 1024;
int numBlocks = (size + blockSize - 1) / blockSize;
floatToUchar_stream<<<numBlocks, blockSize, 0, stream>>>(input, output, size);
}

@ -0,0 +1,158 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-05 19:32:41
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-06 11:13:54
* @FilePath: /AI_SO_Test/AIEngineModule/src/Engine.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "Engine.h"
#include <fstream>
#include <iostream>
#include <cuda_runtime_api.h>
using namespace nvinfer1;
class Logger : public ILogger
{
public:
void log(Severity severity, const char *msg) noexcept override
{
if (severity <= Severity::kWARNING)
std::cout << "[TensorRT] " << msg << std::endl;
}
} gLogger;
// 实现自定义删除器
void TensorRTDeleter::operator()(nvinfer1::IRuntime *ptr) const noexcept
{
// if (ptr)
// {
// printf("************ IRuntime \n");
// // delete ptr;
// }
}
void TensorRTDeleter::operator()(nvinfer1::IExecutionContext *ptr) const noexcept
{
// if (!ptr)
// return;
// try
// {
// printf("************ IExecutionContext \n");
// // 检查有效性、上下文等
// delete ptr;
// }
// catch (const std::exception &e)
// {
// std::cerr << "[Deleter] Exception: " << e.what() << "\n";
// }
// catch (...)
// {
// std::cerr << "[Deleter] Unknown error during deletion\n";
// }
}
void TensorRTDeleter::operator()(nvinfer1::ICudaEngine *ptr) const noexcept
{
// if (ptr)
// {
// printf("************ ICudaEngine \n");
// delete ptr;
// }
// if (ptr)
// {
// printf("************ ICudaEngine \n");
// try
// {
// // delete ptr; //
// }
// catch (...)
// {
// std::cerr << "[Deleter] Exception deleting ICudaEngine\n";
// }
// }
}
Engine::Engine(int gpuId) : gpuId_(gpuId) {}
Engine::~Engine()
{
// printf("========Engine= start ====\n");
// engine_.reset();
// runtime_.reset();
// printf("========Engine= engine_.reset();====\n");
}
bool Engine::loadFromFile(const std::string &enginePath)
{
try
{
cudaSetDevice(gpuId_);
std::ifstream file(enginePath, std::ios::binary);
if (!file)
{
std::cerr << "[Engine] Failed to open engine file: " << enginePath << std::endl;
return false;
}
file.seekg(0, file.end);
size_t size = file.tellg();
file.seekg(0, file.beg);
std::vector<char> engineData(size);
file.read(engineData.data(), size);
runtime_ = std::unique_ptr<IRuntime, TensorRTDeleter>(createInferRuntime(gLogger));
if (!runtime_)
{
std::cerr << "[Engine] Failed to create runtime." << std::endl;
return false;
}
engine_ = std::unique_ptr<ICudaEngine, TensorRTDeleter>(
runtime_->deserializeCudaEngine(engineData.data(), size));
if (!engine_)
{
std::cerr << "[Engine] Failed to deserialize engine." << std::endl;
return false;
}
return true;
}
catch (const std::exception &e)
{
std::cerr << "[Engine] Exception during loadFromFile: " << e.what() << std::endl;
return false;
}
catch (...)
{
std::cerr << "[Engine] Unknown exception during loadFromFile." << std::endl;
return false;
}
}
int Engine::getNbBindings() const
{
return engine_ ? engine_->getNbIOTensors() : 0;
}
std::string Engine::getBindingName(int index) const
{
return engine_ ? engine_->getIOTensorName(index) : "";
}
Dims Engine::getBindingDims(int index) const
{
if (!engine_)
return Dims{};
std::string name = engine_->getIOTensorName(index);
return engine_->getTensorShape(name.c_str());
}
bool Engine::bindingIsInput(int index) const
{
if (!engine_)
return false;
std::string name = engine_->getIOTensorName(index);
return engine_->getTensorIOMode(name.c_str()) == TensorIOMode::kINPUT;
}

@ -0,0 +1,95 @@
cmake_minimum_required (VERSION 3.5)
set(ModuleName "TY_CheckModule")
#==============TensorRT ====================
# TensorRT
find_path(TENSORRT_INCLUDE_DIR
NAMES NvInfer.h
PATHS /usr/include/x86_64-linux-gnu /usr/local/include
)
if(NOT TENSORRT_INCLUDE_DIR)
message(FATAL_ERROR "TensorRT headers not found")
endif()
message(STATUS "TENSORRT_INCLUDE_DIR: " ${TENSORRT_INCLUDE_DIR})
#
file(READ "${TENSORRT_INCLUDE_DIR}/NvInferVersion.h" TENSORRT_VERSION_CONTENTS)
string(REGEX MATCH "#define NV_TENSORRT_MAJOR ([0-9]+)" _ ${TENSORRT_VERSION_CONTENTS})
set(TRT_MAJOR_VERSION ${CMAKE_MATCH_1})
message(STATUS "Found TensorRT v${TRT_MAJOR_VERSION}")
#
if(TRT_MAJOR_VERSION VERSION_LESS 10)
message(STATUS " close //#define USE_TERNSORRT10_BIGMODEL")
else()
add_definitions(-DUSE_TERNSORRT10_BIGMODEL=${TEST_VALUE})
message(STATUS "#define USE_TERNSORRT10_BIGMODEL")
endif()
#==============TensorRT ====================
set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
find_package(CUDA REQUIRED)
message(STATUS "cuda version: " ${CUDA_VERSION_STRING})
message(STATUS "cuda CUDA_INCLUDE_DIRS: " ${CUDA_INCLUDE_DIRS})
include_directories(${CUDA_INCLUDE_DIRS})
include_directories(
/usr/include
#/usr/local/cuda-11.3/targets/x86_64-linux/include
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/Utils
${CMAKE_CURRENT_SOURCE_DIR}/Algorithms
${PROJECT_SOURCE_DIR}/include/TensorRT
${PROJECT_SOURCE_DIR}/ConfigModule/include
${PROJECT_SOURCE_DIR}/Common/include
${PROJECT_SOURCE_DIR}/AIEngineModule/include
${PROJECT_SOURCE_DIR}/AIEngineModule/include_base
)
link_directories(
/usr/local/lib/
)
set(CMAKE_CUDA_ARCHITECTURES 86)
set(CMAKE_CUDA_COMPILER "/usr/local/cuda/bin/nvcc")
enable_language(CUDA)
# set使*.cpp
file(GLOB_RECURSE SRC_LISTS
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
${CMAKE_CURRENT_SOURCE_DIR}/Utils/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utils/*.c
${CMAKE_CURRENT_SOURCE_DIR}/Algorithms/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Algorithms/*.c
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.cpp
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.c
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.cu
)
add_library(CELL_ET_Check SHARED ${SRC_LISTS})
target_link_libraries(CELL_ET_Check
nvinfer
Config
${OpenCV_LIBS}
${CUDA_LIBRARIES}
)
set(ModuleName "")
# make install /usr/local
#
set(CMAKE_INSTALL_PREFIX /usr/local/cellet CACHE PATH "Install path prefix" FORCE)
set(HEADER_FILES include/ImgCheckBase.h include/ImgCheckConfig.h)
#
install(TARGETS CELL_ET_Check
LIBRARY DESTINATION lib # CMAKE_INSTALL_PREFIX/lib
ARCHIVE DESTINATION lib/static
RUNTIME DESTINATION bin
PUBLIC_HEADER DESTINATION include) # CMAKE_INSTALL_PREFIX/include
#
install(FILES ${HEADER_FILES} DESTINATION include)

@ -0,0 +1,77 @@
#include "ParmNameChange.h"
#include <iostream>
#include <regex>
ParmNameChange *ParmNameChange::instance = nullptr;
ParmNameChange::ParmNameChange(/* args */)
{
m_nWorkIdx = 0;
m_bUseWorkIdx = false;
}
ParmNameChange::~ParmNameChange()
{
}
ParmNameChange *ParmNameChange::getInstance()
{
if (instance == nullptr)
{
instance = new ParmNameChange(); // 如果实例为空,则创建新实例
}
return instance;
}
int ParmNameChange::GetWorkIdx_WebConfigCamNameT(std::string strWebConfigCamName)
{
int number = -1;
std::regex regex(R"(work_(\d+)_)", std::regex_constants::icase);
// 用正则表达式搜索字符串
std::smatch match;
if (std::regex_search(strWebConfigCamName, match, regex))
{
std::string number_str = match.str(1); // 提取到的数字部分
try
{
number = std::stoi(number_str); // 转换为整数
// std::cout << "Extracted number as integer: " << number << std::endl;
}
catch (const std::invalid_argument &e)
{
// std::cout << "Invalid argument: " << e.what() << std::endl;
number = -1;
}
catch (const std::out_of_range &e)
{
// std::cout << "Out of range: " << e.what() << std::endl;
number = -1;
}
}
else
{
std::cout << "No match found." << std::endl;
}
number--;
return number;
}
std::string ParmNameChange::GetWebConfigCamName_DetImgCamName(std::string strDetImgCamName)
{
std::string strWebConfigCamName = "";
if (strDetImgCamName == "left")
{
strWebConfigCamName = "left";
}
else if (strDetImgCamName == "right")
{
strWebConfigCamName = "right";
}
else
{
strWebConfigCamName = "Merge";
}
return strWebConfigCamName;
}

@ -0,0 +1,40 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-25 16:25:30
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-25 17:16:49
* @FilePath: /BOE_POL_ET_Detect/AlgorithmModule/include/AI_Mark_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef ParmNameChange_H_
#define ParmNameChange_H_
#include <string>
class ParmNameChange
{
private:
/* data */
public:
ParmNameChange(/* args */);
~ParmNameChange();
static ParmNameChange *getInstance();
// 从web参数的相机名称获得 工位序号
int GetWorkIdx_WebConfigCamNameT(std::string strWebConfigCamName);
// 从检测图片的相机名称 获得 界面的参数的相机名称
std::string GetWebConfigCamName_DetImgCamName(std::string strDetImgCamName);
public:
bool m_nWorkIdx; // 工位序号
private:
static ParmNameChange *instance; // 静态成员指针,存储单例对象
bool m_bUseWorkIdx; // 是否使用 工位序号
};
#endif

@ -0,0 +1,66 @@
/*
//图片基本处理
*/
#ifndef AIClassify_H_
#define AIClassify_H_
#include <opencv2/opencv.hpp>
using namespace std;
struct AI_PIECE_INFO
{
int num;
int len;
int abs_L;
int long_num;
int short_num;
AI_PIECE_INFO()
{
num = 0;
len = 0;
abs_L = 0;
long_num = 0;
short_num = 0;
}
void print(std::string str)
{
printf("%s>> num %d len %d abs_L %d long_num %d short_num %d\n", str.c_str(), num, len, abs_L, long_num, short_num);
}
};
struct AI_Classify_Info
{
int num; // 数量
float score; // 得分
float avgScore; // 平均得分
AI_Classify_Info()
{
Init();
}
void Init()
{
num = 0;
score = 0;
avgScore = 0;
}
void print(std::string str)
{
printf("%s==== num %d score %f avgScore %f\n", str.c_str(), num, score, avgScore);
}
};
class AIClassify
{
public:
AIClassify();
~AIClassify();
// 分类
int GetDetRoiList(const cv::Mat &src_Img, cv::Rect qx_roi, std::vector<cv::Rect> &samllRoiList,int nwidth,int nheight);
private:
cv::Rect GetCutRoi(cv::Rect roi, const cv::Mat &img,int nwidth,int nheight);
// 获取检测roi list
private:
};
#endif

@ -0,0 +1,58 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-24 09:55:53
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef AICommonDefine_H_
#define AICommonDefine_H_
#define USE_WHITEBACK_CLASS 1
// AI缺陷分类缺陷的种类
enum AI_CLass_QX_NAME_
{
AI_CLass_QX_NAME_ok_yisi, // 疑似
AI_CLass_QX_NAME_yixian, // 异显
AI_CLass_QX_NAME_POL_CEL, // 亮点
AI_CLass_QX_NAME_zara, // ZARA
AI_CLass_QX_NAME_ps, // PS
AI_CLass_QX_NAME_line, // 线
AI_CLass_QX_NAME_fangge_line, // 方格线
AI_CLass_QX_NAME_qipao, // 气泡
AI_CLass_QX_NAME_qing_huashang, // 轻划伤
AI_CLass_QX_NAME_mtx, // MTX
AI_CLass_QX_NAME_yisi_qianzangwu, // 疑似浅层脏污
AI_CLass_QX_NAME_qing_zangwu, // 轻脏污
AI_CLass_QX_NAME_zhong_zangwu, // 严重脏污
AI_CLass_QX_NAME_andian, // 暗点
AI_CLass_QX_NAME_huashang, // 划伤
AI_CLass_QX_NAME_zf, // zf
AI_CLass_QX_NAME_other, // 其他
AI_CLass_QX_NAME_count,
};
// 缺陷项对应在参数中的名称
static const std::string AI_CLass_QX_NAME_Names[] =
{
"ok_yisi",
"yixian",
"liangdian",
"zara",
"ps",
"line",
"fangge_line",
"qipao",
"qing_huashang",
"mtx",
"yisi_qianzangwu",
"qing_zangwu",
"zhong_zangwu",
"andian",
"huashang",
"zf",
"other"};
#endif

@ -0,0 +1,181 @@
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef AI_Edge_Algin_H_
#define AI_Edge_Algin_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "OtherDetBaseDefine.h"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "AI_Factory.h"
using namespace std;
using namespace std;
using namespace cv;
// 边缘搜索定位结果
struct Edge_AI_Result
{
int nresult;
cv::Mat mask;
cv::Rect roi;
cv::Mat DetMask_src; // 原图上产品区域
std::shared_ptr<std::vector<cv::Rect>> edge_RoiList; // 边缘检测的roi区域
Edge_AI_Result()
{
Init();
}
void Init()
{
nresult = 0;
roi = cv::Rect(0, 0, 0, 0);
if (!mask.empty())
{
mask.release();
}
if (!DetMask_src.empty())
{
DetMask_src.release();
}
edge_RoiList = std::make_shared<std::vector<cv::Rect>>();
}
};
class AI_Edge_Algin
{
public:
enum SaveProcessType
{
Save_Close, // 不保存
Save_Filter, // 过滤的
Save_ALL, // 全部
};
/// @brief 检测过程的参数
struct DetConfig
{
int ncamId; // 相机ID
std::string strCamName; // 相机ID
int nthresholdvalue; // 背景阈值
int nAIErodesize; // 边缘腐蚀强度
bool bDebugSaveImg; // 保存结果图片
SaveProcessType saveProcessImg; // 保存过程图片
bool bUseDrawRoi_Check; // 是否用绘制的ROI进行校验
cv::Rect drawRoi; // 绘制的 ROi;
cv::Mat drawMask; // 绘制的maksk
DetConfig()
{
Init();
}
void Init()
{
ncamId = 0;
strCamName = "";
nthresholdvalue = 1;
nAIErodesize = 7;
bDebugSaveImg = false;
saveProcessImg = Save_Close;
bUseDrawRoi_Check = false;
drawRoi = cv::Rect(0, 0, 0, 0);
if (!drawMask.empty())
{
drawMask.release();
/* code */
}
}
void Print()
{
printf("nthresholdvalue:%d;nAIErodesize %d;bSaveResultImg %s SaveProcessImg %d\n",
nthresholdvalue, nAIErodesize, BOOL_TO_STR(bDebugSaveImg), saveProcessImg);
printf("bUseDrawRoi_Check %s roi %s \n",
BOOL_TO_STR(bUseDrawRoi_Check), CheckUtil::GetRectString(drawRoi).c_str());
}
bool IsSaveProcessImg()
{
if (saveProcessImg != Save_Close)
{
return true;
}
return false;
}
};
public:
AI_Edge_Algin(/* args */);
~AI_Edge_Algin();
// 初始化检测模型
int InitModel_ALL();
int Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared_ptr<Edge_AI_Result> &pCheckResult_Aling);
int SaveSmallImg(const cv::Mat &img, const cv::Mat &mask, cv::Rect roi);
private:
int InitModel_Big();
int InitModel_Small();
int Det_big(const cv::Mat &img, vector<Rect> &smallRoiList, std::shared_ptr<std::vector<cv::Rect>> edgeRoiList, cv::Rect &bigRoi, cv::Mat &big_mask);
int Dtet_small(const cv::Mat &img, vector<Rect> &smallRoiList, cv::Mat &Src_Mask);
private:
bool m_bInitSucc; // 是否初始化成功
// 检测结果
// std::shared_ptr<Edge_AI_Result> m_pCheckResult_Aling;
OtherDet_Config *m_pOtherDet_Config;
DetConfig *m_pDetConfig;
std::shared_ptr<AIFactory> AI_Factory;
std::shared_ptr<AIMulThreadRunBase> runner;
std::string m_str_curCamName;
bool m_bInitialized;
bool m_bModelSucc;
private:
/* data */
};
// 图片特征定位
class Image_Feature_Algin
{
public:
struct DetConfig
{
bool bSaveImg;
bool bSave_Process; // 存储过程图片
float fscore;
cv::Mat TemplateImg; // 模版图片
cv::Mat DetImg; // 检测图片
cv::Rect Search_Roi; // 搜索 范围
cv::Rect feature_Roi; // 特征区域
cv::Rect param_CropRoi; // 裁剪区域,在参数图片上
cv::Rect DetImg_CropROi; // 裁剪区域,在检测图片上
DetConfig()
{
bSaveImg = false;
bSave_Process = false;
fscore = 0.9;
Search_Roi = cv::Rect(0, 0, 0, 0);
feature_Roi = cv::Rect(0, 0, 0, 0);
param_CropRoi = cv::Rect(0, 0, 0, 0);
DetImg_CropROi = cv::Rect(0, 0, 0, 0);
}
};
public:
Image_Feature_Algin(/* args */);
~Image_Feature_Algin();
int Detect(DetConfig *pDetConfig, Align_Result *pResult, std::vector<std::string> &LogList);
private:
cv::Point findBestTemplateMatch(const cv::Mat &detectionImage, const cv::Mat &templateImage, double &bestScore, int method = cv::TM_CCOEFF_NORMED);
private:
PRINT_LOG_ m_PrintLog;
private:
/* data */
};
#endif

@ -0,0 +1,73 @@
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef AI_Edge_QX_Det_H_
#define AI_Edge_QX_Det_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "OtherDetect.h"
#include "OtherDetBaseDefine.h"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
#include "ImageStorage.h"
#include "AI_Factory.h"
using namespace std;
using namespace cv;
// 边缘缺陷检测
class AI_Edge_QX_Det
{
public:
/// @brief 检测过程的参数
struct DetConfig
{
std::shared_ptr<std::vector<cv::Rect>> pEdgeDet_roiList;
Function_Edge_Det *pdege_Det_config;
std::string strCamChannel;
cv::Rect CutRoi;
int ninstruct;
DetConfig()
{
Init();
}
void Init()
{
pdege_Det_config = NULL;
strCamChannel = "";
ninstruct = 0;
CutRoi = cv::Rect(0, 0, 0, 0);
}
};
public:
AI_Edge_QX_Det(/* args */);
~AI_Edge_QX_Det();
int Detect(const cv::Mat &img, cv::Mat &detmask, DetConfig *pDetConfig,std::shared_ptr<DetLog> pdetlog);
private:
int SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, bool isALLzeros, DetConfig *pDetConfig, int idx = 0, int nruntype = 0);
std::string GetImgSaveName(int flag = 0);
private:
bool m_bInitSucc; // 是否初始化成功
std::string m_strSaveImgRootPath;
std::string m_strSaveImgRootPath_OK;
std::string m_strSaveImgRootPath_Qx;
ImageStorage *m_pImageStorage;
DetConfig *m_pDetConfig;
std::shared_ptr<AIFactory> AI_Factory;
std::shared_ptr<DetLog> m_pdetlog;
int m_nImge_num;
std::string m_strCamChannel;
private:
/* data */
};
#endif

@ -0,0 +1,89 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-25 16:25:30
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-25 16:57:01
* @FilePath: /BOE_POL_ET_Detect/AlgorithmModule/include/AI_Mark_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef AI_Mark_Det_H_
#define AI_Mark_Det_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "OtherDetect.h"
#include "OtherDetBaseDefine.h"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
#include "ImageStorage.h"
#include "AI_Factory.h"
using namespace std;
using namespace cv;
// 二次分割求面积
class AI_Mark_Det : public AIDetectBase
{
public:
// 检测参数和结果
struct DetConfigResult
{
std::string strCamName;
int nresult;
cv::Rect searchroi;
std::string strChannel;
bool bDebugsaveimg;
bool bDetSaveImg;
std::shared_ptr<DetLog> pdetlog;
cv::Rect markRoi;
DetConfigResult()
{
nresult = -1;
strCamName = "";
strChannel = "";
searchroi = cv::Rect(0, 0, 0, 0);
bDebugsaveimg = false;
bDetSaveImg = false;
markRoi = cv::Rect(0, 0, 0, 0);
}
};
public:
AI_Mark_Det(/* args */);
~AI_Mark_Det();
int Detect(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
int Det_img(const cv::Mat &img, DetConfigResult *pDetConfig);
// 分析结果
int Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig);
// 存储过程图片
int SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig);
private:
bool m_bModelSucc;
cv::Mat detimg123;
ImageStorage *m_pImageStorage;
std::shared_ptr<AIFactory> AI_Factory;
std::shared_ptr<DetLog> m_pdetlog;
int m_Show_Area;
float m_Show_Len;
cv::Point m_Len_P1;
cv::Point m_Len_P2;
private:
/* data */
};
#endif

@ -0,0 +1,101 @@
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef AI_Second_Det_H_
#define AI_Second_Det_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "OtherDetect.h"
#include "OtherDetBaseDefine.h"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
#include "ImageStorage.h"
#include "AI_Factory.h"
using namespace std;
using namespace cv;
// 二次分割求面积
class AI_SecondDet : public AIDetectBase
{
public:
// 检测参数和结果
struct DetConfigResult
{
Function_SecondDet *pfunction_secondDet;
float fImgage_Scale_X;
float fImgage_Scale_Y;
float min_DetArea;
cv::Rect qx_roi;
int qx_type;
std::string qx_name;
int old_Area;
float old_len;
int new_Area;
float new_len;
int nresult;
std::string strChannel;
std::shared_ptr<DetLog> pdetlog; // 检测日志
DetConfigResult()
{
qx_roi = cv::Rect(0, 0, 0, 0);
qx_type = 0;
min_DetArea = 0;
qx_name = "";
old_Area = 0;
old_len = 0;
new_Area = 0;
new_len = 0;
nresult = 0;
pfunction_secondDet = NULL;
strChannel = "";
fImgage_Scale_X = 0.0333;
fImgage_Scale_Y = 0.0333;
}
void SetAreaAndLen(int oldArea, float oldLen)
{
old_Area = oldArea;
old_len = oldLen;
new_Area = old_Area;
new_len = old_len;
}
};
public:
AI_SecondDet(/* args */);
~AI_SecondDet();
int Detect(const cv::Mat &img, const cv::Mat &mask, DetConfigResult *pDetConfig);
private:
cv::Rect GetCutRoi(cv::Rect &roi, const cv::Mat &img);
int Det_Pol(const cv::Mat &img, DetConfigResult *pDetConfig);
int Det_AD(const cv::Mat &img, DetConfigResult *pDetConfig);
// 分析结果
int Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig);
// 存储过程图片
int SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig);
private:
bool m_bModelSucc_AD;
bool m_bModelSucc_POL;
cv::Mat detimg123;
ImageStorage *m_pImageStorage;
std::shared_ptr<AIFactory> AI_Factory;
int m_Show_Area;
float m_Show_Len;
cv::Point m_Len_P1;
cv::Point m_Len_P2;
std::shared_ptr<DetLog> m_pdetlog;
private:
/* data */
};
#endif

@ -0,0 +1,85 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-25 16:25:30
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-25 17:16:49
* @FilePath: /BOE_POL_ET_Detect/AlgorithmModule/include/AI_Mark_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef AI_ZF_Det_H_
#define AI_ZF_Det_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "OtherDetect.h"
#include "OtherDetBaseDefine.h"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
#include "ImageStorage.h"
#include "AI_Factory.h"
using namespace std;
using namespace cv;
// 二次分割求面积
class AI_ZF_Det
{
public:
// 检测参数和结果
struct DetConfigResult
{
std::string strCamName;
int nresult;
std::shared_ptr<ZF_Result> pZF_Result;
bool bDebugsaveimg;
bool bDetSaveImg;
std::shared_ptr<DetLog> pdetlog;
DetConfigResult()
{
nresult = -1;
strCamName = "";
bDebugsaveimg = false;
bDetSaveImg = false;
}
};
public:
AI_ZF_Det(/* args */);
~AI_ZF_Det();
int Detect(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
int Det_img(const cv::Mat &img, DetConfigResult *pDetConfig);
// 分析结果
int Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig);
// 存储过程图片
int SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig);
private:
bool m_bModelSucc;
cv::Mat detimg123;
ImageStorage *m_pImageStorage;
std::shared_ptr<AIFactory> AI_Factory;
std::shared_ptr<DetLog> m_pdetlog;
int m_Show_Area;
float m_Show_Len;
cv::Point m_Len_P1;
cv::Point m_Len_P2;
private:
/* data */
};
#endif

@ -0,0 +1,174 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-17 20:05:16
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef ALLImgCheckAnalysisy_H_
#define ALLImgCheckAnalysisy_H_
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <opencv2/opencv.hpp>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <thread>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "BlobBase.h"
#include "ImgCheckBase.h"
#include "ImageDetBase.h"
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
#include "ConfigBase.h"
#include "CheckConfigDefine.h"
#include "ImageDetConfig.h"
#include "Define_Product.hpp"
#include "CameraCheckAnalysisy.hpp"
#include "Product.h"
#include "ParmNameChange/ParmNameChange.h"
#include "QX_Merge_Analysis.h"
using namespace std;
using namespace cv;
class ALLImgCheckAnalysisy : public ALLImgCheckBase
{
public:
ALLImgCheckAnalysisy();
~ALLImgCheckAnalysisy();
// 初始化参数 pconfig 参数指针 返回0 成功 其他异常
int RunStart(void *pconfig1);
// 设置检测数据,并开启检测 返回0 成AT_THRESHOLD_TYPE_READY功 其他异常
int SetDataRun_SharePtr(std::shared_ptr<shareImage> p);
// 获取结果信息 返回0 成功 其他异常
int GetCheckReuslt(std::shared_ptr<CheckResult> &pResult);
int ReJson(std::shared_ptr<shareImage> p, std::shared_ptr<CheckResult> &pResult);
int CheckImg(std::shared_ptr<shareImage> p, std::shared_ptr<CheckResult> &pResult);
// 获取检测库 状态信息 返回CHECK_THREAD_RUN_STATUS
int GetStatus();
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
int UpdateConfig(void *pconfig, int nConfigType);
std::string GetVersion();
std::string GetErrorInfo();
private:
// 加载运行参数
int LoadRunConfig(void *p);
// 加载分析参数
int LoadCheckConfig(void *p);
/// @brief 初始化并且启动程序
/// @return
int InitRun();
/// @brief 开启检测
/// @return
int StartCheck();
/// @brief 设置空闲
/// @return
int SetIDLE();
// 核对参数版本号
int CheckConfigVersion(void *pconfig1);
private:
// 开启线程
int StartThread();
// 停止线程
int StopThread();
// 退出系统
int ExitSystem();
// 初始化相机检测分析类
int InitCameraCheckAnalysisy();
// 初始化
int InitData();
// 处理产品
int Det_Product(std::shared_ptr<Product> &product);
std::shared_ptr<Product> GetProduct();
// 联合分析
int AnalysiyAll(int productIdx);
// 设置最终结果
int SetProductResult(std::shared_ptr<Product> product);
// 设置检测完成
int SetSetComplet_New(std::shared_ptr<Product> product, int nerror);
// 加载图片 队列
int PushInImg_New(std::shared_ptr<shareImage> p);
cv::Mat hconcatWithFirstBase(const cv::Mat &img1, const cv::Mat &img2, int interpolation);
int MergeShowImg(std::shared_ptr<Product> product); // 合并图片
// 异常返回
int ErrorReturn(std::shared_ptr<shareImage> p);
std::shared_ptr<Product> GetProduct(std::string strProduct);
int InitAIFactory();
private:
// 图片处理线程
std::shared_ptr<std::thread> ptr_thread_Run;
int Run(); // 运行;
int set_cpu_id(const std::vector<int> &cpu_set_vec);
private:
RunInfoST m_RunConfig;
// 检测参数模块
ConfigManagerBase *m_pConfigManager;
// 图片处理线程
// 相机处理模块,负责完成对应相机图片的处理功能。
std::unordered_map<std::string, std::shared_ptr<CameraCheckAnalysisy>> m_pCameraCheckAnalysisyList;
PRINT_LOG_ m_PrintLog;
// 互斥锁定义
private:
// 产品队列
std::vector<std::shared_ptr<Product>> m_ProductList;
std::mutex mtx_ProductList; // 互斥量
std::condition_variable ProductList_cond; // 条件变量,
std::shared_ptr<DetLog> m_pdetlog;
std::queue<std::shared_ptr<CheckResult>> m_CheckResultList; // 检测结果
std::mutex mtx_CheckResult; // 互斥锁,用于保护数据队列
std::condition_variable CheckResult_cond; // 条件变量,用于同步生产者和消费者线程
private:
int m_nErrorCode; // 错误代码
bool m_bInitSucc; // 初始化状态
bool m_bExit; // 是否退出检测
std::string m_strTest;
ParmNameChange *m_pParamName;
};
#endif

@ -0,0 +1,127 @@
#pragma once
enum ERR_DOT_TYPE_ENUM
{
ERR_TYPE_1,
ERR_TYPE_2,
ERR_TYPE_COUNT,
};
#define Value_ERR_TYPE_1 64
#define Value_ERR_TYPE_2 128
//-----------------------sxg added
#define _MAX_ERROR_SCAN_LINE_PER_ROW 300
#define _MAX_ERROR_DOT_BLOB 500
#define _MAX_MACRO_COUNT 4
#define _MAX_ERR_CLASS ERR_TYPE_COUNT
// #define _CAM_WIDTH 640
#define _MAX_MIN_VALUE_NUM 10
typedef struct ERROR_DOTS_SCAN_DATA
{
unsigned short x, count;
unsigned short minx, miny;
unsigned short maxx, maxy;
int area, energy;
int xposSum, yposSum;
int macro;
int type;
int ErrClass[_MAX_ERR_CLASS];
} ERROR_DOTS_SCAN_DATA;
typedef struct ERROR_DOTS_SCAN_ROW
{
int scanCount;
ERROR_DOTS_SCAN_DATA errorScanLineTab[_MAX_ERROR_SCAN_LINE_PER_ROW];
int macro[_MAX_MACRO_COUNT];
int ErrClass[_MAX_ERR_CLASS];
int minValue[_MAX_MIN_VALUE_NUM];
} ERROR_DOTS_SCAN_ROW;
typedef struct ERROR_DOTS_BLOB_DATA
{
unsigned short x, y;
unsigned short minx, miny;
unsigned short maxx, maxy;
int area;
int energy;
float JudgArea;
float len;
int macro[_MAX_MACRO_COUNT];
int ErrClass[_MAX_ERR_CLASS];
int whiteOrblack;
int ErrType;
int UserErrorType;
int maxValue;
float grayDis;
int AIclasstype;
float density;
unsigned short badd;
} ERROR_DOTS_BLOB_DATA;
typedef struct ERROR_DOTS_BLOBS
{
int blobCount;
int srcBlobCount;
int totalArea;
int totalEnergy;
ERROR_DOTS_BLOB_DATA blobTab[_MAX_ERROR_DOT_BLOB];
int ErrClass[_MAX_ERR_CLASS];
} ERROR_DOTS_BLOBS;
typedef struct ERROR_DOTS_BLOB_PARAM
{
int minArea; // ²ÐµãÇøÓòÃæ»ý×îСֵ£¬µ¥Î»ÎªÏñËØµã£¬Èç¹ûСÓÚ´ËÖµ£¬ÔòºöÂÔ
int minEnergy; // ²ÐµãÇøÓòÄÜÁ¿×îСֵ£¬Èç¹ûСÓÚ´ËÖµ£¬ÔòºöÂÔ
int maxErrorBlobCount; // ×î´óÔÊÐíµÄÂú×ãÉÏÊöÌõ¼þºóµÄ²ÐµãÇøÓòÊýÁ¿£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í
int maxTotalArea; // ×î´óÔÊÐíµÄÂú×ãÉÏÊöÌõ¼þºóµÄ²ÐµãÇøÓò×ÜÃæ»ý£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í
int maxTotalEnergy; // ×î´óÔÊÐíµÄÂú×ãÉÏÊöÌõ¼þºóµÄ²ÐµãÇøÓò×ÜÄÜÁ¿£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í
int maxRegionArea; // ×î´óÔÊÐíµÄµ¥¸ö²ÐµãÇøÓòÃæ»ý£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í
int maxRegionEnergy; // ×î´óÔÊÐíµÄµ¥¸ö²ÐµãÇøÓòÄÜÁ¿£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í
int Hthold[4]; // ѧϰģ°æºóµÄÀ©Õ¹ãÐÖµ
int Lthold[4]; // ѧϰģ°æºóµÄÀ©Õ¹ãÐÖµ
int Level[2]; // ÑÏÖØµÈ¼¶
int mergeDistance; // ²ÐµãºÏ²¢×îС¾àÀë £¬¡¡ÈôÁ½¸ö²Ðµã¾àÀëСÓÚ´ËÖµÔòºÏ²¢ÎªÒ»¸ö
int isUseMacro;
} ERROR_DOTS_BLOB_PARAM;
typedef struct ERROR_BLOBS_PARAM
{
int id;
unsigned char *pb;
unsigned char *pr;
unsigned char *pc;
int width;
int height;
int obj;
ERROR_DOTS_BLOBS *blobs;
} ERROR_BLOBS_PARAM;
#ifdef __cplusplus
extern "C"
{
#endif
void pretest(double x);
extern void AddErrorScan(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int mdx, int *pErrClass);
extern void LinkScanLineToBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width);
extern void SortBlob(ERROR_DOTS_BLOBS *blobs);
extern void MergeBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOB_PARAM *param);
extern void AddErrorScan_New(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int errorType);
extern void LinkScanLineToBlob_New(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width);
extern int GetBlobs_V2(ERROR_DOTS_BLOBS *blobs, unsigned char *pImgdata, unsigned char *pErrordata, int width, int height, int basev, int minArea);
extern int GetBlobs_V3(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, int width, int height, int minArea);
extern int GetBlobs_V3_CA(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, int width, int height, int minArea, int err_1_value, int err_2_value);
extern int GetBlobs_ALL_New(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, unsigned char *pHdata, int width, int height, int minArea);
extern int GetBlobs_oneLabe(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, unsigned char *pHdata, int width, int height, int minArea);
extern int PushBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOBS *addblobs);
//逐像素计算灰阶
extern int CalHJ_Pixel(unsigned char *pErrordata,unsigned char *pMaskdata, int width, int height,int bkvalue,float ratio );
#ifdef __cplusplus
}
#endif

@ -0,0 +1,163 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-25 17:22: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/include/CamDeal.h
*/
#ifndef CameraCheckAnalysisy_H_
#define CameraCheckAnalysisy_H_
#include <mutex>
#include <vector>
#include <thread>
#include <string>
#include <stdio.h>
#include <condition_variable>
#include "Define_Base.h"
#include "ImgCheckBase.h"
#include "ImageDetBase.h"
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
#include "ConfigBase.h"
#include "CheckConfigDefine.h"
#include "ImageDetConfig.h"
#include "Define_Product.hpp"
#include "CameraResult.h"
#include "DetLog.h"
#include "ImageResultJudge.h"
#include "CheckResultJson.h"
#include "Edge_Search.h"
#include "AI_Mark_Det.h"
#include "AI_ZF_Det.h"
#include "ImageMerge.h"
#include "QX_Merge_Analysis.h"
using namespace std;
using namespace cv;
// 相机处理类
class CameraCheckAnalysisy
{
public:
CameraCheckAnalysisy();
~CameraCheckAnalysisy();
// 相机处理类 初始化
int Init(std::string strcameraName);
int StartCheck(std::shared_ptr<CameraResult> pCamera_Check_Result);
private:
// 开启线程
int StartThread();
// 停止线程
int StopThread();
// 初始化检测分析线程类
int InitCheckAnalysisy();
// 初始化其他
int InitRun();
// 设置新的检测参数
int SetNewConfig();
// 处理每张图片
int CheckImgRun();
int Run(); // 运行;
int set_cpu_id(const std::vector<int> &cpu_set_vec);
// 等待处理图片
int WaitDetImg();
// 预处理图片
int Detect_Pre();
// 处理每张图片
int Detect_Images();
// 结果参数分析
int ResultParamJudge();
int MergeResultAnalysisy(); // 合并结果分析
int UpdateConfigStatus();
// 结果参数分析
int ResultParamJudge_New();
// 边缘处理
int ImgEdge(std::shared_ptr<ImageAllResult> L255, ChannelCheckFunction *pFuntion_L255);
// 检测MarkLine
int Det_MarkLine(const cv::Mat &L255CutImg, std::shared_ptr<ImageAllResult> L255, Base_Function_MarkLine *pFuntion);
// 预处理 字符检测
int preDet_ZF(const cv::Mat &L255CutImg, std::shared_ptr<ImageAllResult> L255);
// 边缘处理
int ImgEdge(cv::Mat img, cv::Mat &detMaskImg, cv::Rect &roi, int productIdx);
// 插入相机日志
int InsertCameraLog();
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能
// 获取 检测核心库
ImgCheckBase *GetDealResult(int idx = -1);
public:
// 运行的基本参数
RunInfoST m_RunConfig;
// 检测参数模块
std::shared_ptr<ConfigBase> m_pConfig;
int m_nConfigIdx;
// 检测分析参数
AnalysisyConfigST m_AnalysisyConfig;
CommonConfigNodeST *m_pCommonAnalysisyConfig;
ALLChannelCheckFunction *m_pChannelFuntion; // 画面检测功能
BaseCheckFunction *m_pbaseCheckFunction; // 基础检测
std::shared_ptr<DetLog> m_pdetlog;
// 结果分析类
ImageResultJudge m_imageResultJudge;
// 边缘检测模块集合
Edge_Search m_Edge_Search;
// Mark检测
AI_Mark_Det m_MarkDet;
// 字符检测
AI_ZF_Det m_ZF_Det;
ImageMerge m_ImageMerge;
private:
// 相机ID
std::string m_strcameraName;
int m_nErrorCode; // 错误代码
bool m_bInitSucc; // 初始化状态
bool m_bExit; // 是否退出检测
int nLastCheckAnalysisyThreadIdx;
// 图片处理线程
std::shared_ptr<std::thread> ptr_thread_Run;
std::shared_ptr<CameraResult> m_pCheck_Result;
bool m_bHaveImgeDet; // 是否有图片需要检查
std::mutex mtx_WaiteImg; // 等待图片的锁
std::condition_variable cond_WaiteImg; // 条件变量,是否有图片需要检查
std::string m_strRootPath_MergeImg;
private:
// 检测核心库
ImgCheckBase *m_pImgCheckAnalysisy[IMGCHECKANALYSISY_NUM];
CheckResultJson m_CheckResultJson;
std::shared_ptr<QX_Merge_Analysis> m_pQX_Merge_Analysis;
private:
private:
};
#endif

@ -0,0 +1,95 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-24 22:18:44
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef CameraResult_H_
#define CameraResult_H_
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <opencv2/opencv.hpp>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <thread>
#include <string>
#include <stdlib.h>
#include "Define_Product.hpp"
#include "CheckErrorCodeDefine.hpp"
#include "ImgCheckConfig.h"
#include "ImageDetConfig.h"
#include "ImageAllResult.h"
#include "DetLog.h"
using namespace std;
using namespace cv;
class CameraResult
{
private:
public:
CameraResult(/* args */);
~CameraResult();
void AddLog(std::string str);
// 添加图片信息
int AddDetImage(std::shared_ptr<shareImage> p);
// 是否全部检测完成
bool bCheckCamplate();
// 设置 检测步骤
Check_Step GetCheckStep();
void SetCheckStep(Check_Step step);
// 送图是否全部完成
bool getImgPushComplate();
void setImgPushComplate();
bool IsHaveL255();
bool Have_EdgeImg(std::string strConfig_Channel); // 是否有边缘图片
void SetHaveL255(bool b);
bool IsHaveDP();
void SetHaveDP(bool b);
bool IsHaveUp();
void SetHaveUp(bool b);
// 返回一个未检测的 图片进行检测
std::shared_ptr<ImageAllResult> GetNoDetImg();
std::shared_ptr<ImageAllResult> GetL255DetImg();
std::shared_ptr<ImageAllResult> GetEdgeChannel(std::string strConfig_Channel);
long time_start;
bool bJson = false;
std::string m_config_EdgeChannel; // 边缘通道
public:
std::vector<std::string> LogList;
std::shared_ptr<DetLog> detlog;
std::vector<std::shared_ptr<ImageAllResult>> ImageALLDetResultList; // 每个通道的检测结果 ,返回的结果。
std::shared_ptr<ProductBaseResult> productBaseResult;
std::shared_ptr<CameraBaseResult> cameraBaseResult;
// CameraImage_Status cameraImage_Status; // 图片状态
std::mutex mtx_Det; // 互斥量
private:
bool bIsImgComplete = false; // 图片是否都送完了。
Check_Step checkStep = Check_Step_NODet; // 检测步骤
PRINT_LOG_ m_PrintLog;
// 多线程安全
std::mutex mtx_DetImageList;
bool bHave_L255 = false;
bool bHave_DP = false;
bool bHave_Up = false;
bool bHave_EdgeImg = false; // 是否有边缘图片
};
#endif

@ -0,0 +1,291 @@
#ifndef _CheckErrorDefine_HPP_
#define _CheckErrorDefine_HPP_
#include <string>
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "Base_Define.h"
#include "Define_Base.h"
#include "Define_Error.h"
#include "DetLog.h"
#define BOOL_TO_STR(bool_expr) (bool_expr) ? "true" : "false"
#define BOOL_TO_STROK(bool_expr) (bool_expr) ? "OK" : "NG"
#define BOOL_TO_ThanLess(bool_expr) (bool_expr) ? ">" : "<"
#define BOOL_TO_LessThan(bool_expr) (bool_expr) ? "<" : ">"
#define BOOL_TO_STR_Error(bool_expr) ((bool_expr) ? "Succ" : "Error")
#define Re_TO_STR_Error(num) ((num) == 0 ? "Succ" : "Error")
#define Re_TO_STR_False(num) ((num) == 0 ? "Succ" : "false")
#define Re_TO_STR_Pass_1(num) ((num) == 1 ? "Pass" : "fail")
#define Re_TO_STR_NG(num) ((num) == 0 ? "OK" : "NG")
#define SRC_IMG_WIDTH 14192
#define SRC_IMG_HEIGHT 10640
// resize 图片的 宽度
#define RESIZE_IMAGE_WIDTH 1680
enum TEM_IMG_IDX_
{
TEM_IMG_IDX_SrcCrop,
TEM_IMG_IDX_AImask,
TEM_IMG_IDX_DrawSrc,
TEM_IMG_IDX_Result,
TEM_IMG_IDX_Count,
};
static const std::string TEM_IMG_IDX_Names[] =
{
"SrcCrop",
"AImask",
"Drawmask",
"result"};
enum Print_Level_
{
Print_Level_Info,
Print_Level_Key,
Print_Level_Error,
};
// 大于日志
struct PRINT_LOG_
{
bool bprint;
bool bshow_Info;
bool bshow_Key;
bool bshow_Error;
PRINT_LOG_()
{
Init();
}
void Init()
{
bprint = true;
bshow_Info = true;
bshow_Key = true;
bshow_Error = true;
}
template <typename... Args>
std::string printstr(int LogLevel, std::string stepStr, const std::string &format, Args... args)
{
std::string str = "";
if (!bprint)
{
return str;
}
switch (LogLevel)
{
case Print_Level_Info:
if (!bshow_Info)
{
return str;
}
str = "info-> ";
break;
case Print_Level_Key:
if (!bshow_Key)
{
return str;
}
str = "key-> ";
break;
case Print_Level_Error:
if (!bshow_Error)
{
return str;
}
str = "Error-> ";
break;
default:
return str;
break;
}
str += stepStr + ": ";
str += str_Format(format, args...);
printf("%s\n", str.c_str());
return str;
}
};
// 检测区域参数
struct Detect_ROI_Config
{
bool bdraw; // 是否绘制
std::vector<std::vector<cv::Point>> roiList_Src;
std::vector<std::vector<cv::Point>> roiList_Show;
Detect_ROI_Config()
{
Init();
}
void Init()
{
bdraw = false;
for (auto &innerVec : roiList_Src)
{
innerVec.clear();
}
roiList_Src.clear(); // 清空外层vector
for (auto &innerVec : roiList_Show)
{
innerVec.clear();
}
roiList_Show.clear(); // 清空外层vector
}
void Update(const std::vector<cv::Point> &list, const cv::Rect &roi, float fScale_x, float fScale_y)
{
std::vector<cv::Point> adjustedPolygon;
std::vector<cv::Point> adjustedPolygon_size;
// 遍历多边形中的每个点并根据roi调整位置
for (const auto &point : list)
{
// 调整每个点的位置平移到roi的位置
cv::Point adjustedPoint(point.x - roi.x, point.y - roi.y);
// printf("-- %d %d \n", adjustedPoint.x, adjustedPoint.y);
if (adjustedPoint.y < 0)
{
adjustedPoint.y = 0;
}
cv::Point sizep;
sizep.x = adjustedPoint.x * fScale_x;
sizep.y = adjustedPoint.y * fScale_y;
adjustedPolygon.push_back(adjustedPoint);
adjustedPolygon_size.push_back(sizep);
}
// 将调整后的多边形添加到roiList_Src
roiList_Src.push_back(adjustedPolygon);
roiList_Show.push_back(adjustedPolygon_size);
}
void Update_1(const std::vector<cv::Point> &list, const cv::Rect &roi, int offtx, int offty, float fScale_x, float fScale_y)
{
std::vector<cv::Point> adjustedPolygon;
std::vector<cv::Point> adjustedPolygon_size;
// 遍历多边形中的每个点并根据roi调整位置
for (const auto &point : list)
{
// 调整每个点的位置平移到roi的位置
cv::Point adjustedPoint(point.x + offtx - roi.x, point.y + offty - roi.y);
if (adjustedPoint.y < 0)
{
adjustedPoint.y = 0;
}
cv::Point sizep;
sizep.x = adjustedPoint.x * fScale_x;
sizep.y = adjustedPoint.y * fScale_y;
adjustedPolygon.push_back(adjustedPoint);
adjustedPolygon_size.push_back(sizep);
}
// 将调整后的多边形添加到roiList_Src
roiList_Src.push_back(adjustedPolygon);
roiList_Show.push_back(adjustedPolygon_size);
}
void Update_Marit(const std::vector<cv::Point> &list, const cv::Rect &roi, cv::Mat &H, float fScale_x, float fScale_y)
{
std::vector<cv::Point> adjustedPolygon;
std::vector<cv::Point> adjustedPolygon_size;
// 遍历多边形中的每个点并根据roi调整位置
for (const auto &point : list)
{
cv::Point pt = CheckUtil::transformPoint(point, H);
// printf(" %d %d -> %d %d \n",point.x,point.y,pt.x,pt.y);
// 调整每个点的位置平移到roi的位置
cv::Point adjustedPoint(pt.x - roi.x, pt.y - roi.y);
if (adjustedPoint.y < 0)
{
adjustedPoint.y = 0;
}
cv::Point sizep;
sizep.x = adjustedPoint.x * fScale_x;
sizep.y = adjustedPoint.y * fScale_y;
adjustedPolygon.push_back(adjustedPoint);
adjustedPolygon_size.push_back(sizep);
}
// 将调整后的多边形添加到roiList_Src
roiList_Src.push_back(adjustedPolygon);
roiList_Show.push_back(adjustedPolygon_size);
}
// 判断点是否在指定idx的ROI内
bool isPointInROI(int idx, const cv::Point &point)
{
// 判断索引是否有效
if (idx < 0 || idx >= roiList_Src.size())
{
printf("Invalid idx: %d\n", idx);
return false;
}
// 获取第 idx 个多边形
const std::vector<cv::Point> &polygon = roiList_Src[idx];
// 使用 pointPolygonTest 来判断点是否在多边形内
double result = cv::pointPolygonTest(polygon, point, false);
// 如果结果大于 0则点在多边形内
if (result > 0)
{
return true;
}
// 如果结果等于 0点在边界上
else if (result == 0)
{
return true; // 你可以根据需求调整边界情况
}
// 如果结果小于 0点在多边形外
return false;
}
void print(std::string str)
{
printf("%s bdraw %d roi num %ld\n", str.c_str(), bdraw, roiList_Src.size());
}
};
// 复测的状态
enum ReJson_Status
{
ReJson_Status_Idel,
ReJson_Status_start,
ReJson_Status_Run,
ReJson_Status_end,
};
// 亮点的判断参数
struct LD_ConfigT_
{
bool buse;
float minArea;
float maxArea;
float hj;
LD_ConfigT_()
{
buse = false;
minArea = 0;
maxArea = 0;
hj = 0;
}
void print(std::string str)
{
printf("%s buse %d minArea %f maxArea %f hj %f\n", str.c_str(), buse, minArea, maxArea, hj);
}
};
extern std::string GetErrorCodeInfo(int nErrorCode);
#endif //_CORELOGICFACTORY_HPP_

@ -0,0 +1,28 @@
/*
//其他类的检测
*/
#ifndef CheckResultJson_H_
#define CheckResultJson_H_
#include <vector>
#include <thread>
#include "ImgCheckConfig.h"
#include "JsonCoversion.h"
#include <stdio.h>
#include "ImageDetConfig.h"
class CheckResultJson : public JsonCoversion
{
public:
CheckResultJson() {}
virtual ~CheckResultJson() {}
public:
virtual Json::Value toJsonValue();
virtual void toObjectFromValue(Json::Value root);
int GetConfig(std::string strJson, std::shared_ptr<One_Image_CheckResult_> &pOneImgDetResult);
std::string GetResultString(std::shared_ptr<One_Image_CheckResult_> &pOneImgDetResult);
private:
std::shared_ptr<One_Image_CheckResult_> m_pOneImgDetResult;
};
#endif

@ -0,0 +1,79 @@
/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2022-04-28 10:41:42
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-03 21:32:02
*/
/*
* FileName:CoreLogicFactory.hpp
* Version:V1.0
* Description:
* Created On:Mon Sep 10 11:13:13 UTC 2018
* Modified date:
* Author:Sky
*/
#ifndef _CheckUtil_HPP_
#define _CheckUtil_HPP_
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <mutex>
#include <vector>
#include <thread>
#include <opencv2/opencv.hpp>
using namespace std;
class CheckUtil
{
public:
static long getcurTime();
static std::string getCurrentDate();
static std::string getCurTimeHMS();
static std::string Op_float2String(float nvalue);
static int64_t getSnowId();
static bool JudgRect(cv::Rect roi, int img_w, int img_h);
static bool JudgRect_SZ(cv::Rect roi, int w, int h);
static bool compareIgnoreCase(const std::string &str1, const std::string &str2);
static bool RoiInImg(cv::Rect roi, cv::Mat img);
static int printROI(cv::Rect roi, std::string str = "");
static float CalIoU(cv::Rect rect1, cv::Rect rect2);
static float CalIoU_t(cv::Rect rect1, cv::Rect rect2);
static int CheckRect(cv::Rect &roi, int img_w, int img_h);
static int SizeRect(cv::Rect &roi, int img_w, int img_h, int addw, int addh);
static int CalHj(const cv::Mat &img, const cv::Mat &mask, int b_value);
static int CalHj(const cv::Mat &img, const cv::Mat &mask, const cv::Mat &backgroundimg);
static float CalRoi2RoiPre(cv::Rect rect1, cv::Rect rect2);
// 计算平均灰度
static float CalImgBrightness(cv::Mat imgRoi);
// 计算角度
static float Cal2PointAngle(cv::Point p_left, cv::Point p_right);
// 找图片的最大外轮廓
static cv::Rect getLargestContourROI(const cv::Mat &binaryImg, bool &found);
static std::string GetRectString(cv::Rect rect);
// 创建目录
static int CreateDir(const std::string &dir);
// 点的距离是否过小
static bool bcalDis(cv::Point p1, cv::Point p2, int disT);
static double calDis(cv::Point2f p1, cv::Point2f p2);
static void PrintRect(cv::Rect roi, std::string str = "");
static int cutSmallImg(cv::Mat img, std::vector<cv::Rect> &samllRoiList, cv::Rect config_roi, int config_SmallImg_Width, int config_SmallImg_Height, int config_MinOverlap_Width, int config_MinOverlap_Height);
static cv::Point2f transformPoint(const cv::Point2f &point, const cv::Mat &transform_matrix);
};
template <typename... Args>
static std::string str_Format(const std::string &format, Args... args)
{
auto size_buf = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
std::unique_ptr<char[]> buf(new (std::nothrow) char[size_buf]);
if (!buf)
return std::string("");
std::snprintf(buf.get(), size_buf, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size_buf - 1);
}
#endif //_CORELOGICFACTORY_HPP_

@ -0,0 +1,46 @@
/*
//定义整个系统基础的 定义 信息
*/
#ifndef Define_Base_H_
#define Define_Base_H_
#include <string>
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "ImgCheckConfig.h"
#include "ImageDetConfig.h"
#include "Define_Error.h"
// 检测分析线程类数目
#define IMGCHECKANALYSISY_NUM 4
// 相机ID 的相关定义
enum Camera_IDX
{
Camera_IDX_0 = 0,
Camera_IDX_1 = 1,
};
static const std::string strCameraName[] =
{
"left",
"right"};
struct Camera_Info
{
Camera_IDX camera_ID;
std::string camera_name;
Camera_Info()
{
Init();
}
void Init()
{
camera_ID = Camera_IDX_0;
camera_name = strCameraName[camera_ID];
}
};
static const std::string WebConfig_CameraName[] =
{
"C1",
"C2",
"C3"};
#endif

@ -0,0 +1,67 @@
/*
//定义整个系统基础的 定义 信息
*/
#ifndef Define_Error_H_
#define Define_Error_H_
#include <string>
using namespace std;
enum ERRORCODEDEFINE
{
CHECK_OK,
CHECK_ERROR_VERSION, // 参数或接口版本问题
CHECK_ERROR_Config_Null, // 参数指针为空
CHECK_ERROR_Config_Value, // 参数值错误
CHECK_ERROR_Path_NULL, // 路径为空
CHECK_ERROR_Mask_Empty, // mask 图片为空
CHECK_ERROR_Config_cutRoi, // 参数的 roi 错误
CHECK_ERROR_CheckImg_Empty, // 检测 图片为空
CHECK_ERROR_PushImg_ListSize, // 送图错误 队列太长
CHECK_ERROR_PushImg_NoDetChannel, // 不检测通道
CHECK_ERROR_PushImg_Existing_ID, // ID 已存在
CHECK_ERROR_PushImg_ID_Error, // ID 错误
CHECK_ERROR_ID_Error, // ID 错误
CHECK_ERROR_L255_Empty, // L255 为空
CHECK_ERROR_L255_Edge_Fail, // L255 边界搜索失败
CHECK_ERROR_PRODUCT_ID_EXIST, // 产品 ID 已存在
CHECK_ERROR_Camear_ID_Error, // 相机ID 错误
INIT_CameraCheck_Error, // 初始化 相机处理类错误
};
static const std::string str_ErrorName[] =
{
"ok",
"ERROR_VERSION",
"Config_Null",
"Config_Value",
"Path_NULL",
"Mask_Empty",
"Config_cutRoi",
"CheckImg_Empty",
"PushImg_ListSize",
"PushImg_NoDetChannel",
"PushImg_Existing_ID",
"PushImg_ID_Error",
"ID_Error",
"L255_Empty",
"L255_Edge_Fail",
"L255_Empty",
"L255_Empty",
"PRODUCT_ID_EXIST",
"Camear_ID_Error",
"INIT_CameraCheck_Error"};
struct ErrorInfo
{
int nerror_code; // 错误代码
string strerror_msg; // 错误信息
ErrorInfo()
{
Init();
}
void Init()
{
nerror_code = CHECK_OK;
strerror_msg = str_ErrorName[CHECK_OK];
}
};
#endif

@ -0,0 +1,43 @@
#ifndef Define_Product_HPP_
#define Define_Product_HPP_
#include "Define_Base.h"
#include "ImgCheckConfig.h"
// 相机的一些状态情况
struct CameraImage_Status
{
bool bImgComplete; /// 图片送完成了
bool bHaveImg; // 是否有图片
bool bHave_L255; // 是否有L55图片
bool bHave_DP; // 是否有DP图片
bool bhave_UP; // 是否有UP图片
bool bDetCutRoi; // 是否完成边缘检测
CameraImage_Status()
{
Init();
}
void Init()
{
bImgComplete = false;
bHaveImg = false;
bHave_L255 = false;
bHave_DP = false;
bhave_UP = false;
bDetCutRoi = false;
}
};
// 处理状态
enum Check_Step
{
Check_Step_NODet = 0, // 未处理
Check_Step_PreDet, // 预处理
Check_Step_ImgeDet, // 图片处理
Check_Step_ResultParamJudg, // 结果参数判断
Check_Step_ImgeDet_End, // 图片检测完成
Check_Step_Complete, // 处理完成
Check_Step_COUNT,
};
#endif

@ -0,0 +1,158 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-16 22:35:59
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef DetLog_H_
#define DetLog_H_
#include <string>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <vector>
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
using namespace std;
enum PrintLevel_
{
PrintLevel_0,
PrintLevel_1,
PrintLevel_2,
PrintLevel_3,
PrintLevel_4,
};
template <typename... Args>
std::string str_Format_1(const std::string &format, Args... args)
{
// 先尝试用小缓冲
char buf[256];
int size = std::snprintf(buf, sizeof(buf), format.c_str(), args...);
if (size < 0)
return {};
if (size < sizeof(buf))
{
return std::string(buf, size); // 直接返回
}
else
{
// 超过栈缓存时才用堆分配
std::vector<char> dynamic_buf(size + 1);
std::snprintf(dynamic_buf.data(), dynamic_buf.size(), format.c_str(), args...);
return std::string(dynamic_buf.data(), size);
}
}
// 检测过程临结果
struct DetLog
{
std::vector<std::string> logList;
bool bPrintStr; // 是否打印日志
int addLogLevel;
std::mutex mtx;
DetLog()
{
Init();
}
void Init()
{
logList.clear();
bPrintStr = false;
addLogLevel = DET_LOG_LEVEL_3;
}
template <typename... Args>
void AddCheckstr(PrintLevel_ step, std::string stepStr, const std::string &format, Args... args)
{
std::string str = "";
if (step <= PrintLevel_0)
{
str += ".. ";
}
else if (step == PrintLevel_1)
{
str += "..... ";
}
else if (step == PrintLevel_2)
{
str += "........ ";
}
else if (step == PrintLevel_3)
{
str += "........... ";
}
else if (step >= PrintLevel_4)
{
str += ".............. ";
}
str += stepStr + ": ";
str += str_Format_1(format, args...);
if (bPrintStr)
{
printf("%s\n", str.c_str());
}
{
std::lock_guard<std::mutex> lock(mtx);
logList.push_back(str);
}
}
template <typename... Args>
void AddCheckstr(PrintLevel_ step, int LogLevel, std::string stepStr, const std::string &format, Args... args)
{
std::string str = "";
if (step <= PrintLevel_0)
{
str += ".. ";
}
else if (step == PrintLevel_1)
{
str += "..... ";
}
else if (step == PrintLevel_2)
{
str += "........ ";
}
else if (step == PrintLevel_3)
{
str += "........... ";
}
else if (step >= PrintLevel_4)
{
str += ".............. ";
}
str += stepStr + ": ";
str += str_Format_1(format, args...);
if (bPrintStr)
{
printf("%s\n", str.c_str());
}
if (LogLevel <= addLogLevel)
{
std::lock_guard<std::mutex> lock(mtx);
logList.push_back(str);
}
}
void printLog(std::string str)
{
printf("===========================%s==============================\n", str.c_str());
{
std::lock_guard<std::mutex> lock(mtx);
for (auto strl : logList)
{
printf("%s\n", strl.c_str());
}
}
printf("==========================================================\n");
}
};
#endif

@ -0,0 +1,102 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-23 18:06:58
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-25 10:19:29
* @FilePath: /BOE_POL_ET_Detect/AlgorithmModule/include/Edge_Search.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#ifndef Edge_Search_H_
#define Edge_Search_H_
#include <opencv2/opencv.hpp>
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
#include "AI_Edge_Algin.h"
using namespace std;
using namespace cv;
// 边缘缺陷检测
class Edge_Search
{
public:
// 检测参数和结果
struct DetConfigResult
{
Function_EdgeROI *pEdgeROI;
Function_Image_Align *pAlign;
std::shared_ptr<DetLog> pdetlog;
std::string strCamName;
bool bMode_Edge_test; // 是否是边缘测试模式
bool bDebugsaveImg; // 保存处理图片
DetConfigResult()
{
Init();
}
void Init()
{
bMode_Edge_test = false;
pEdgeROI = NULL;
pAlign = NULL;
pdetlog = NULL;
strCamName = "";
bDebugsaveImg = false;
}
};
public:
Edge_Search(/* args */);
~Edge_Search();
int Detect(const cv::Mat &detimg, DetConfigResult *pDetConfig, std::shared_ptr<EdgeDetResult> &pEdgeDetResult);
private:
int Detect_AI(const cv::Mat &detimg, DetConfigResult *pDetConfig, std::shared_ptr<EdgeDetResult> &pEdgeDetResult);
int Detect_Draw(const cv::Mat &detimg, DetConfigResult *pDetConfig, std::shared_ptr<EdgeDetResult> &pEdgeDetResult);
int Detect_Search(const cv::Mat &detimg, DetConfigResult *pDetConfig, std::shared_ptr<EdgeDetResult> &pEdgeDetResult);
int SearchEdge(const cv::Mat &detimg, cv::Rect &roi, bool bsave);
// 特征定位
int Feature_Align(const cv::Mat &detimg, DetConfigResult *pDetConfig, std::shared_ptr<EdgeDetResult> &pEdgeDetResult);
private:
std::shared_ptr<DetLog> m_pdetlog;
AI_Edge_Algin m_pAI_Edge_Algin;
// 图片特征定位
Image_Feature_Algin m_Image_Feature_Algin;
private:
cv::Mat showimg;
bool bshowimg;
double computeAverage(const std::vector<double> &data);
std::vector<double> removeOutliers(const std::vector<double> &data);
/// @brief
/// @param img 搜到图片 单通道
/// @param DirectSign 搜索方向 >0 正向,< 0 反向
/// @param Gate 阈值
/// @param BorW 搜索黑点 = 0还是白点 = 1
/// @param roi 搜索范围
/// @param StepCount 搜索点数
/// @param Limit 最小满是阈值点个数算上搜索成功
/// @return <0 搜索错误, >=0表示 搜索位置
int UDNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit);
/// @brief
/// @param img 搜到图片 单通道
/// @param DirectSign 搜索方向 >0 正向,< 0 反向
/// @param Gate 阈值
/// @param BorW 搜索黑点 = 0还是白点 = 1
/// @param roi 搜索范围
/// @param StepCount 搜索点数
/// @param Limit 最小满是阈值点个数算上搜索成功
/// @return <0 搜索错误, >=0表示 搜索位置
int LRNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit);
// int LRNoiseEdgeDetect(cv::Mat img,int DirectSign, int Gate,int BorW, int StartSearchSite, int Step, int StepCount, int top, int bottom, int Limit, int Depth, int MaxLimit);
};
#endif

@ -0,0 +1,228 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-10-09 18:21:49
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef ImageAllResult_H_
#define ImageAllResult_H_
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <opencv2/opencv.hpp>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <thread>
#include <string>
#include <stdlib.h>
#include "Define_Product.hpp"
#include "CheckErrorCodeDefine.hpp"
#include "ImgCheckConfig.h"
#include "ImageDetConfig.h"
#include "DetLog.h"
#include "CheckResultJson.h"
using namespace std;
using namespace cv;
// 包含所有的图片检测结果,如 返回的结果,临时结果, 其他检测结果
class ImageAllResult
{
public:
enum DetStep
{
DetStep_NotDet,
DetStep_Deting,
DetStep_Complet,
};
struct AI_Det_MaskImg
{
cv::Rect roi;
cv::Mat AI_inImg;
cv::Mat AI_mask;
};
struct Config_Update
{
bool bUpdate = false;
bool wait_DP= false;
bool wait_UP= false;
};
// AI MaskImg 的相关使用的参数信息。
struct AI_MaskImg_BlobParam
{
unsigned char *imgBlobHFlagData = NULL; // mask 图片在 Y方向是否有餐点用以加速 blob 分析。
std::queue<std::shared_ptr<AI_Det_MaskImg>> AIMaskImgBLobQueue; // AI 中间结果 队列
std::mutex mtx_AIMaskImgBLobQueue;
int ndatalen;
AI_MaskImg_BlobParam()
{
Init();
}
void Init()
{
if (imgBlobHFlagData != NULL)
{
delete[] imgBlobHFlagData;
imgBlobHFlagData = NULL;
}
ndatalen = 0;
}
void InitBLobHData(int ndataLen)
{
if (imgBlobHFlagData != NULL)
{
delete[] imgBlobHFlagData;
imgBlobHFlagData = NULL;
}
ndatalen = ndataLen;
imgBlobHFlagData = new unsigned char[ndataLen];
}
~AI_MaskImg_BlobParam()
{
Init();
}
};
// 图片的AI 检测相关结果。
// 兼容多种AI模型输出结果的。
struct Image_AI_Det_Result
{
bool bDet; // 是否有检测
int Model_in_Image_width; // AI 检测图片的宽度
int Model_in_Image_height; // AI 检测图片的高度
int Model_out_Image_width; // AI 推理后的图片的宽度
int Model_out_Image_height; // AI 推理后的图片的宽度
cv::Mat AI_MaskImg; // AI 推理的mask图片
std::vector<std::shared_ptr<AI_Det_MaskImg>> AI_Qx_MaskList; // AI 推理 输出中间结果信息。
std::shared_ptr<AI_MaskImg_BlobParam> blobDetParam; // BLob 检测要用到的一些 参数 。
Image_AI_Det_Result()
{
Init();
}
void Init()
{
bDet = false;
Model_in_Image_width = 0;
Model_in_Image_height = 0;
Model_out_Image_width = 0;
Model_out_Image_height = 0;
if (AI_MaskImg.empty())
{
AI_MaskImg.release();
}
AI_Qx_MaskList.clear();
blobDetParam = std::make_shared<AI_MaskImg_BlobParam>();
}
void InitBLobHData(int ndataLen)
{
blobDetParam->InitBLobHData(ndataLen);
}
~Image_AI_Det_Result()
{
Init();
}
};
struct WTB_Check_Result_
{
cv::Rect roi_src;
cv::Rect roi_show;
WTB_Check_Result_()
{
Init();
}
void Init()
{
roi_src = cv::Rect(0, 0, 0, 0);
roi_show = cv::Rect(0, 0, 0, 0);
}
};
private:
/* data */
public:
ImageAllResult(/* args */);
~ImageAllResult();
void AddLog(std::string str);
// 添加图片信息
int AddDetImage(std::shared_ptr<shareImage> p);
DetStep getStep();
void setStep(DetStep step);
bool IsNotDet();
bool IsChannel(std::string strChannelName);
public:
// 裁切大小
cv::Rect CropRoi = cv::Rect(0, 0, 0, 0);
// 检测的原始图片
cv::Mat detImg;
// 专用于 AI 检测的图片,如果 AI的输入尺寸 大于原始图片的尺寸,则 AIDetImg 要进行合理的扩展。
cv::Mat AI_detImg;
// AI 推理的mask图片
cv::Mat AIMaskImg;
// AI 127Cell推理的mask图片
cv::Mat AI_127CellMaskImg;
std::shared_ptr<Image_AI_Det_Result> qx_DetAIResult; // BLob 检测要用到的一些 参数 。
std::shared_ptr<Image_AI_Det_Result> cell127_DetAIResult; // 127 cell 检测要用到的一些 参数 。
// 结果图片
cv::Mat resultImg;
// 屏蔽图片 = 搜索边界的 屏蔽区域 +字符的屏蔽区 + 界面绘制的屏蔽区域
cv::Mat shieldImg;
// 专用于 AI 检测的屏蔽图片,如果 AI的输入尺寸 大于原始图片的尺寸,则 AI_shieldImg 要进行合理的扩展。
cv::Mat AI_shieldImg;
// 异显mask图片
cv::Mat YX_MaskImg;
// 缺失polmask图片
cv::Mat LcakPol_MaskImg;
float fscale_detToresult_x = 0;
float fscale_detToresult_y = 0;
int NG_num = 0;
int YS_num = 0;
int Ok_num = 0;
int NoJudge_num = 0;
int AI_Det_Img_Width = 0; // AI 检测图片的宽度
int AI_Det_Img_Height = 0; // AI 检测图片的宽度
bool bChangeSize = false; // 是否改变尺寸
bool bWhiteOrBlackImg = false; // 是否是白底黑字图片
bool bOnlyBlob = false;
Config_Update config_update;
public:
DetStep m_step = DetStep_NotDet;
std::string strBaseInfo = "";
std::string strChannel = "";
std::vector<std::string> LogList;
std::shared_ptr<DetLog> detlog;
std::shared_ptr<CheckResult> result; // 返回检测结果
std::shared_ptr<One_Image_CheckResult_> pDetResult; // 检测结果 后续主要对pDetResult 继续分析
std::shared_ptr<ProductBaseResult> productBaseResult; // 产品相关的基本结果信息
std::shared_ptr<CameraBaseResult> cameraBaseResult; // 相机相关的基本结果信息
std::shared_ptr<WTB_Check_Result_> pWTB_Check_Result;
std::vector<std::shared_ptr<AI_Det_MaskImg>> AI_Qx_MaskList;
std::mutex mtx_Det; // 互斥量
private:
PRINT_LOG_ m_PrintLog;
CheckResultJson m_CheckResultJson;
};
#endif

@ -0,0 +1,55 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-11 15:32:52
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-14 17:41:14
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/include/ImageDetBase.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#ifndef ImageDetBase_H_
#define ImageDetBase_H_
#include <string>
#include <memory>
#define INTERFACE_Det_VERSION 4
/*******************一般调用流程*************************************************************************************************************************/
/*******************1、初始化 UpdateConfig*************************************************************************************************************************/
/*******************2、初始化 Init 并开启 *************************************************************************************************************************/
/*******************3、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_IDLE 可以设置检测数据并开启检测 SetDataRun***************************************************/
/*******************4、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_COMPLETE 检测完成,可以获取检测结果 GetCheckReuslt 拷贝检测结果 自动把状态设为 CHECK_THREAD_STATUS_IDLE*****************************/
struct ImageDetconfig;
struct ImageDetResult;
struct ImageAllResult;
class ImgCheckBase
{
protected:
ImgCheckBase() {}
public:
// delete camera interface
~ImgCheckBase() {}
static ImgCheckBase *GetInstance();
// 初始化参数 pconfig 参数指针 返回0 成功 其他异常
virtual int RunStart(void *pconfig1 = NULL) = 0;
// 设置检测数据,并开启检测 返回0 成功 其他异常
virtual int SetDataRun_SharePtr(std::shared_ptr<ImageAllResult> p) = 0;
// 获取结果信息 返回0 成功 其他异常
virtual int GetCheckReuslt(std::shared_ptr<ImageDetResult> &pResult) = 0;
virtual int CheckImg(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult) = 0;
virtual int ReJsonResul(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult) = 0;
// 获取检测库 状态信息 返回CHECK_THREAD_RUN_STATUS
virtual int GetStatus() = 0;
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
virtual int UpdateConfig(void *pconfig, int nConfigType) = 0;
// 返回检测版本信息
virtual std::string GetVersion() = 0;
// 返回错误信息
virtual std::string GetErrorInfo() = 0;
};
#endif

@ -0,0 +1,432 @@
#ifndef _ImageDetConfig_HPP_
#define _ImageDetConfig_HPP_
#include <string>
#include <opencv2/opencv.hpp>
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
#include "DetLog.h"
class QX_Merge_Analysis;
#define QX_SAMLLIMG_WIDTH 160
#define QX_SAMLLIMG_HEIGHT 160
enum QX_Stauts
{
QX_Stauts_Analysis,
QX_Stauts_OK,
QX_Stauts_YS,
QX_Stauts_Draw,
};
// 缺陷结果信息
struct QX_ERROR_INFO_
{
int Idx;
int result;
std::string result_name;
cv::Rect roi;
int area;
int energy;
float JudgArea;
float JudgArea_second;
float flen;
int nconfig_qx_type;
std::string qx_name;
int maxValue;
int whiteOrBlack;
float grayDis;
float fUpIou;
float density; // Blob- 密度
std::vector<std::string> detLogList; // 检测日志
std::shared_ptr<DetLog> detlog;
std::vector<int> detRegionidxList; // 对应检测区域的 idx.
QX_Stauts qx_status;
QX_ERROR_INFO_()
{
Init();
}
~QX_ERROR_INFO_()
{
}
void Init()
{
whiteOrBlack = 0;
Idx = 0;
area = 0;
energy = 0;
JudgArea = 0;
JudgArea_second = 0;
flen = 0;
nconfig_qx_type = 0;
qx_name = "";
maxValue = 0;
grayDis = 0;
fUpIou = 0;
result = 0;
result_name = "OK";
density = 0;
cv::Rect roi = cv::Rect(0, 0, 0, 0);
detLogList.erase(detLogList.begin(), detLogList.end());
detLogList.clear();
detRegionidxList.clear();
detlog = std::make_shared<DetLog>();
qx_status = QX_Stauts_Analysis;
}
void print(std::string str = "")
{
std::cout << str << ": "
<< "Idx: " << Idx
<< ", Result: " << result << " " << result_name
<< ", ROI: (" << roi.x << ", " << roi.y << ", " << roi.width << ", " << roi.height << ")"
<< ", Area: " << area
<< ", Energy: " << energy
<< ", JudgArea: " << JudgArea
<< ", JudgArea second: " << JudgArea_second
<< ", density: " << density
<< ", Flen: " << flen
<< ", nconfig_qx_type: " << nconfig_qx_type
<< ", QX Name: " << qx_name
<< ", Max Value: " << maxValue
<< ", Gray Dis: " << grayDis
<< ", fUpIou: " << fUpIou
<< ", whiteOrBlack: " << whiteOrBlack
<< std::endl;
}
};
struct One_Image_CheckResult_
{
cv::Rect CutRoi; // 当前检测图片 对应的裁切区域
cv::Rect Param_CropRoi; // 参数模版 对应的裁切区域
std::shared_ptr<std::vector<QX_ERROR_INFO_>> pQx_ErrorList; // 缺陷错误信息
void print(std::string str = "")
{
std::cout << str << ": "
<< " CutRoi: (" << CutRoi.x << ", " << CutRoi.y << ", " << CutRoi.width << ", " << CutRoi.height << ")"
<< std::endl;
std::cout << str << ": "
<< " Param_CropRoi: (" << Param_CropRoi.x << ", " << Param_CropRoi.y << ", " << Param_CropRoi.width << ", " << Param_CropRoi.height << ")"
<< std::endl;
for (int i = 0; i < pQx_ErrorList->size(); i++)
{
pQx_ErrorList->at(i).print(std::to_string(i));
}
}
};
// 定位结果
struct Align_Result
{
bool bDet; // 检测状态 true 成功false 失败。
bool bUse; // 是否要使用。
bool bDraw; // 是否绘制
cv::Point bestMatch;
int offt_x; // 偏移值
int offt_y; // 偏移值
float fCropROI_Scale_ParmToDet_X; // 裁剪区域的缩放
float fCropROI_Scale_ParmToDet_Y; // 裁剪区域的缩放
std::vector<cv::Point> feature_PointList_DetImg; // 特征区域点 检查图上的特征点
cv::Rect Crop_Roi_DetImg; // 检测图片上的 裁切区域
cv::Rect Crop_Roi_ParmImg; // 参数图片上的 裁切区域
Align_Result()
{
Init();
}
void Init()
{
bDet = false;
bUse = false;
offt_x = 0;
offt_y = 0;
bestMatch = cv::Point(0, 0);
fCropROI_Scale_ParmToDet_X = 1;
fCropROI_Scale_ParmToDet_Y = 1;
feature_PointList_DetImg.clear();
Crop_Roi_DetImg = cv::Rect(0, 0, 0, 0);
Crop_Roi_ParmImg = cv::Rect(0, 0, 0, 0);
bDraw = false;
}
void copy(Align_Result tem)
{
this->bDet = tem.bDet;
this->bUse = tem.bUse;
this->offt_x = tem.offt_x;
this->offt_y = tem.offt_y;
this->fCropROI_Scale_ParmToDet_X = tem.fCropROI_Scale_ParmToDet_X;
this->fCropROI_Scale_ParmToDet_Y = tem.fCropROI_Scale_ParmToDet_Y;
this->bDraw = tem.bDraw;
this->bestMatch = tem.bestMatch;
this->Crop_Roi_DetImg = tem.Crop_Roi_DetImg;
this->Crop_Roi_ParmImg = tem.Crop_Roi_ParmImg;
this->feature_PointList_DetImg.assign(tem.feature_PointList_DetImg.begin(), tem.feature_PointList_DetImg.end());
}
// 从检测图的原始图片 映射到 参数的原始图
cv::Point Det_srcToParm_src_Point(cv::Point &p)
{
cv::Point dst_p;
dst_p.x = (p.x - offt_x) / fCropROI_Scale_ParmToDet_X;
dst_p.y = (p.y - offt_y) / fCropROI_Scale_ParmToDet_Y;
return dst_p;
}
cv::Rect Det_srcToParm_src_Rect(cv::Rect &roi)
{
cv::Rect dst_roi;
cv::Point src_pl = cv::Point(roi.x, roi.y);
cv::Point src_rb = cv::Point(roi.x + roi.width, roi.y + roi.height);
cv::Point p_lt = Det_srcToParm_src_Point(src_pl);
cv::Point p_rb = Det_srcToParm_src_Point(src_rb);
dst_roi.x = p_lt.x;
dst_roi.y = p_lt.y;
dst_roi.width = p_rb.x - p_lt.x;
dst_roi.height = p_rb.y - p_lt.y;
return dst_roi;
}
// 参数的原始图 映射到 检测图的原始图片
cv::Point Parm_srcToDet_src_Point(cv::Point &p)
{
cv::Point dst_p;
dst_p.x = p.x * fCropROI_Scale_ParmToDet_X + offt_x;
dst_p.y = p.y * fCropROI_Scale_ParmToDet_Y + offt_y;
return dst_p;
}
cv::Rect Parm_srcToDet_src_Rect(cv::Rect &roi)
{
cv::Rect dst_roi;
cv::Point src_pl = cv::Point(roi.x, roi.y);
cv::Point src_rb = cv::Point(roi.x + roi.width, roi.y + roi.height);
cv::Point p_lt = Parm_srcToDet_src_Point(src_pl);
cv::Point p_rb = Parm_srcToDet_src_Point(src_rb);
dst_roi.x = p_lt.x;
dst_roi.y = p_lt.y;
dst_roi.width = p_rb.x - p_lt.x;
dst_roi.height = p_rb.y - p_lt.y;
return dst_roi;
}
// 参数图片上的点 对应到 检测裁切后上的点
cv::Point Parm_srcToDet_Crop_Point(cv::Point &p)
{
cv::Point dst_p = Parm_srcToDet_src_Point(p);
dst_p.x -= Crop_Roi_DetImg.x;
dst_p.y -= Crop_Roi_DetImg.y;
return dst_p;
}
// 参数图片上的点 对应到 检测裁切后上的点
cv::Rect Parm_srcToDet_Crop_Rect(cv::Rect &roi)
{
cv::Rect dst_roi;
cv::Point src_pl = cv::Point(roi.x, roi.y);
cv::Point src_rb = cv::Point(roi.x + roi.width, roi.y + roi.height);
cv::Point p_lt = Parm_srcToDet_Crop_Point(src_pl);
cv::Point p_rb = Parm_srcToDet_Crop_Point(src_rb);
dst_roi.x = p_lt.x;
dst_roi.y = p_lt.y;
dst_roi.width = p_rb.x - p_lt.x;
dst_roi.height = p_rb.y - p_lt.y;
return dst_roi;
}
void CalOfftScal()
{
cv::Point src_pl = cv::Point(Crop_Roi_DetImg.x, Crop_Roi_DetImg.y);
cv::Point src_rb = cv::Point(Crop_Roi_DetImg.x + Crop_Roi_DetImg.width, Crop_Roi_DetImg.y + Crop_Roi_DetImg.height);
cv::Point param_pl = cv::Point(Crop_Roi_ParmImg.x, Crop_Roi_ParmImg.y);
cv::Point param_rb = cv::Point(Crop_Roi_ParmImg.x + Crop_Roi_ParmImg.width, Crop_Roi_ParmImg.y + Crop_Roi_ParmImg.height);
int a_x_1 = src_pl.x;
int a_x_2 = src_rb.x;
int b_x_1 = param_pl.x;
int b_x_2 = param_rb.x;
int diff_a_x = a_x_1 - a_x_2;
int diff_b_x = b_x_1 - b_x_2;
float fscale_x = 1;
if (diff_b_x != 0)
{
fscale_x = diff_a_x * 1.0f / diff_b_x;
}
int ofx = a_x_1 - fscale_x * b_x_1;
// printf("a_x_1 %d a_x_2 %d\n", a_x_1, a_x_2);
// printf("b_x_1 %d b_x_2 %d\n", b_x_1, b_x_2);
// printf("fscale_x %f ofx %d \n", fscale_x, ofx);
int a_y_1 = src_pl.y;
int a_y_2 = src_rb.y;
int b_y_1 = param_pl.y;
int b_y_2 = param_rb.y;
int diff_a_y = a_y_1 - a_y_2;
int diff_b_y = b_y_1 - b_y_2;
float fscale_y = 1;
if (diff_b_y != 0)
{
fscale_y = diff_a_y * 1.0f / diff_b_y;
}
int ofy = a_y_1 - fscale_y * b_y_1;
// printf("a_y_1 %d a_y_2 %d\n", a_y_1, a_y_2);
// printf("b_y_1 %d b_y_2 %d\n", b_y_1, b_y_2);
// printf("fscale_y %f ofy %d \n", fscale_y, ofy);
offt_x = ofx;
offt_y = ofy;
fCropROI_Scale_ParmToDet_X = fscale_x;
fCropROI_Scale_ParmToDet_Y = fscale_y;
}
void print()
{
printf("scale x %f y %f ,offt x %d y %d\n", fCropROI_Scale_ParmToDet_X, fCropROI_Scale_ParmToDet_Y, offt_x, offt_y);
}
};
// 边缘检测结果
struct EdgeDetResult
{
int nresult;
cv::Rect cutRoi;
cv::Mat shieldMask; // 在 屏蔽mask图片
cv::Mat shieldMask_Src; // 在原图上的屏蔽mask图片
cv::Mat edge_cutMask; // 边缘 图片 在裁切后的图片
std::shared_ptr<std::vector<cv::Rect>> pEdgeDet_roiList; // 边缘检测的区域
Align_Result m_align_Result;
int ninstruct;
EdgeDetResult()
{
nresult = -1;
cutRoi = cv::Rect(0, 0, 0, 0);
m_align_Result.Init();
ninstruct = 0;
pEdgeDet_roiList = std::make_shared<std::vector<cv::Rect>>();
}
};
// 产品相关的 基础检测结果
struct ProductBaseResult
{
std::string strproductName = ""; // 产品 ID
int nCamera_Num = 0;
std::shared_ptr<DetLog> detlog;
std::shared_ptr<QX_Merge_Analysis> pQX_Merge_Analysis;
// ProductBaseResult()
// {
// pQX_Merge_Analysis = QX_Merge_Analysis::GetInstance();
// pQX_Merge_Analysis->InitData();
// }
};
// 相机相关的 基础检测结果
struct MakeLine_Result
{
int nresult = 1;
cv::Rect markLine_Roi_X = cv::Rect(0, 0, 0, 0);
cv::Rect markLine_Roi_Y = cv::Rect(0, 0, 0, 0);
};
struct ZF_Result
{
int nresult = 1;
bool bShield_ZF = false; // 是否屏蔽字符
std::vector<cv::Rect> pZF_roiList; // 字符的区域
std::vector<cv::Point> ZF_centerPoint; // 字符的中心点位置
};
struct CameraBaseResult
{
enum ImageDet_Status
{
ImageDet_Status_None = 0,
ImageDet_Status_NoDet = 1,
ImageDet_Status_DetComplete = 2,
};
std::string strCameraName = ""; // 相机结果 ID
std::shared_ptr<EdgeDetResult> pEdgeDetResult; // 边缘检测结果
std::shared_ptr<MakeLine_Result> pMarkLineResult; // MarkLine检测结果
std::shared_ptr<ZF_Result> pZF_Result; // zf 检测结果
ImageDet_Status UpImg_Status = ImageDet_Status_None; // Up 画面
ImageDet_Status DPImg_Status = ImageDet_Status_None; // DP 画面
cv::Mat DP_MaskImg; // DP 画面 mask图片
cv::Mat UP_MaskImg; // UP 画面 mask图片
};
struct ImageDetconfig
{
cv::Mat ShieldMaskImg; // 屏蔽mask
cv::Mat UpMaskImg; // Up 画面 mask图片
cv::Mat DPMaskImg;
cv::Mat edge_maskImg;
bool bUseUpMaskImg;
std::shared_ptr<std::vector<cv::Rect>> pZF_roiList; // 字符的区域
std::shared_ptr<shareImage> pBaseImgCheckConfig;
Align_Result alignResult; // 定位结果
ImageDetconfig()
{
Init();
}
~ImageDetconfig()
{
}
void Init()
{
bUseUpMaskImg = false;
if (!ShieldMaskImg.empty())
{
ShieldMaskImg.release();
}
if (!UpMaskImg.empty())
{
UpMaskImg.release();
}
if (!DPMaskImg.empty())
{
DPMaskImg.release();
}
if (!edge_maskImg.empty())
{
edge_maskImg.release();
}
alignResult.Init();
}
};
struct ImageDetResult
{
bool bShield_ZF; // 是否要屏蔽字符区域
bool bUseUpImg; // 是否要使用 up img 进行过滤
cv::Mat AI_maskImg;
int Yx_result; // 异显检测状态
float fUP_IOU; // UP 画面 使用的 iou
std::shared_ptr<std::vector<cv::Rect>> pZF_roiList; // 字符的区域
std::shared_ptr<One_Image_CheckResult_> pOneImgDetResult; // 单图检测结果
std::shared_ptr<CheckResult> pBaseImgCheckResult;
ImageDetResult()
{
Init();
}
~ImageDetResult()
{
}
void Init()
{
bShield_ZF = false;
if (!AI_maskImg.empty())
{
AI_maskImg.release();
}
Yx_result = 0;
fUP_IOU = 0;
bUseUpImg = false;
}
};
#endif //_CORELOGICFACTORY_HPP_

@ -0,0 +1,158 @@
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef ImageMerge_H_
#define ImageMerge_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
using namespace std;
using namespace cv;
// 图片特征定位
class ImageMerge
{
public:
// 搜索方向
enum Edge_DirectSign
{
DirectSign_UP,
DirectSign_DOWN,
DirectSign_Left,
DirectSign_Right,
};
// 搜索边缘了下,黑还是白
enum Search_Value_Type
{
Search_Value_White,
Search_Value_Black,
};
// 边缘搜索参数
struct Edge_Search_Config
{
cv::Rect roi; // 边缘搜索区域
Search_Value_Type searchValueType; // 搜索边缘了下,黑还是白
Edge_DirectSign directSign; // 搜索方向
int nValueThreshold; // 灰度阈值
int nSearchCount; // 搜索点的个数 把roi 均分成多少个点。
int nSearchrange; // 搜索范围,一般为单数,如果 1表示 搜索当前点如果3表示 除了当前点,还有左右 点。5表示 从-2到2
int stepCount; // 每个搜索点的步数
int nLimit; // 连续搜索多个满足阈值的点后,停止搜索,当前搜索点 搜索成功。
std::string strchannel;
Edge_Search_Config()
{
roi = cv::Rect(0, 0, 0, 0);
directSign = DirectSign_UP;
searchValueType = Search_Value_White;
nValueThreshold = 25;
nSearchCount = 30;
nSearchrange = 1;
stepCount = 2;
nLimit = 3;
strchannel = "";
}
bool CheckConfigValid()
{
bool bRet = true;
if (roi.width <= 0 || roi.height <= 0)
{
printf("s1 \n");
return false;
}
if (searchValueType < Search_Value_White || searchValueType > Search_Value_Black)
{
printf("s2 \n");
return false;
}
if (directSign < 0 || directSign > 4)
{
printf("s3 \n");
return false;
}
if (nValueThreshold < 0 || nValueThreshold > 255)
{
printf("s4 \n");
return false;
}
if (nSearchCount < 0)
{
printf("s5 \n");
return false;
}
if (stepCount < 0)
{
printf("s6 \n");
return false;
}
if (nLimit < 0)
{
printf("s7 \n");
return false;
}
return true;
}
};
struct Line
{
cv::Point p1;
cv::Point p2;
Line()
{
p1 = cv::Point(0, 0);
p2 = cv::Point(0, 0);
}
};
public:
struct DetConfig
{
bool bSaveImg;
bool bSave_Process; // 存储过程图片
std::string strcam;
std::string strchannel;
DetConfig()
{
bSaveImg = false;
bSave_Process = false;
strcam = "";
strchannel = "";
}
};
public:
ImageMerge(/* args */);
~ImageMerge();
int CalMergeRoi(DetConfig *pDetConfig, cv::Mat &img1, const cv::Mat &img2);
int detMergeImg(cv::Mat &img1, const cv::Mat &img2);
private:
int GetRectAndPoint(const cv::Mat &img, cv::Rect &roi, cv::Point &merg_p_up, cv::Point &merg_p_down, bool bleft, std::string strcam, std::string strchannel);
// 边缘点搜索函数
int GetEdgePoint(const cv::Mat &img, Edge_Search_Config *pEdge_Search_Config, int &outP);
int GetLine(const cv::Mat &img, std::vector<cv::Point> &pointList, int lineNum, int xory, int &outP);
// 产品的位置
bool ProductSide_left(const cv::Mat &img);
private:
cv::Mat showimg;
bool bshowimg;
PRINT_LOG_ m_PrintLog;
bool m_bleft_img1;
cv::Rect m_roi_right_img;
cv::Rect m_roi_left_img;
cv::Rect m_roi_right_ALLimg;
cv::Rect m_roi_left_ALLimg;
bool m_bcalSucc;
cv::Size m_ALLImgSize;
private:
/* data */
};
#endif

@ -0,0 +1,162 @@
/*
//图片基本处理
*/
#ifndef ImageResultJudge_H_
#define ImageResultJudge_H_
#include "CheckConfigDefine.h"
#include <mutex>
#include <vector>
#include <thread>
#include <string>
#include <stdio.h>
#include <condition_variable>
#include "Define_Base.h"
#include "ImgCheckBase.h"
#include "ImageDetBase.h"
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
#include "ConfigBase.h"
#include "CheckConfigDefine.h"
#include "ImageDetConfig.h"
#include "Define_Product.hpp"
#include "CameraResult.h"
#include "DetLog.h"
#include "QX_Merge_Analysis.h"
class ImageResultJudge
{
private:
enum DrawType
{
Draw_rect,
Draw_circle,
Draw_str,
};
struct txtDrawBackgroundk
{
std::vector<cv::Rect> txtDrawRoi;
cv::Rect findNonOverlappingPos(
const cv::Rect &newRect,
int step = 5,
int maxRadius = 800)
{
// 如果本身就不重叠,直接返回
bool overlap = false;
for (const auto &r : txtDrawRoi)
{
if ((newRect & r).area() > 0)
{
overlap = true;
break;
}
}
if (!overlap)
return newRect;
// 螺旋搜索
for (int radius = step; radius <= maxRadius; radius += step)
{
for (int dx = -radius; dx <= radius; dx += step)
{
for (int dy = -radius; dy <= radius; dy += step)
{
cv::Rect candidate = newRect + cv::Point(dx, dy);
bool conflict = false;
for (const auto &r : txtDrawRoi)
{
if ((candidate & r).area() > 0)
{
conflict = true;
break;
}
}
if (!conflict)
{
return candidate; // 找到合适位置
}
}
}
}
printf("find fail ============= \n");
// 实在找不到,就返回原始位置
return newRect;
}
};
struct DrawInfo
{
cv::Mat drawImg;
DrawType type = Draw_rect;
std::vector<std::string> strlist;
cv::Point txtP = cv::Point(0, 0);
cv::Rect roi = cv::Rect(0, 0, 0, 0);
cv::Scalar color = cv::Scalar(255, 0, 255);
cv::Point cp = cv::Point(0, 0);
int dr = 0;
float txtsize = 0.8;
std::shared_ptr<txtDrawBackgroundk> txtbackgroundk;
};
public:
ImageResultJudge(/* args */);
~ImageResultJudge();
int SetAnalysisyConfig(AnalysisyConfigST *pAnalysisyConfig);
int ResultJudge(std::shared_ptr<ImageAllResult> pImageResult);
int UpdateMergedet(std::shared_ptr<CameraResult> pCheck_Result);
int MergeResult(std::shared_ptr<ImageAllResult> pImageResult, QX_Analysis_Result_List *ptemre);
int UpdateConfig(std::string strcameraName);
int DrawResult(std::shared_ptr<ImageAllResult> pImageResult);
private:
// 获取 缺陷在参数列表的位置
int GetParamidx();
int UpdateImgageScale();
int SetInDetConfig(std::string strcameraName);
int SetMergeConfig(std::string strcameraName);
// 参数缺陷类型转 结果参数类型
int ConfigTypeToResultType(int nconfigType);
cv::Rect GetCutRoi(cv::Rect &roi, const cv::Mat &img);
// 获取缺陷 对应的AI输入 输出图片,
int GetAIDetImg(std::shared_ptr<ImageAllResult> pImageResult, cv::Point pcenter, cv::Mat &AI_InImg, cv::Mat &AI_OutImg);
int sendTask(std::shared_ptr<DrawInfo> task);
std::shared_ptr<ImageResultJudge::DrawInfo> GetTask();
void ThreadDraw();
int DrawResultTask(std::shared_ptr<ImageResultJudge::DrawInfo> task);
// 等待 绘制完成
int WaiteDrawComplate();
int AnalysisResult_Pre(QX_ERROR_INFO_ *QX_info); // 弱化处理
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能
int ConfigTypeToQXAnalysis(int nconfigType);
private:
bool m_bExit;
float m_fImgage_Scale_X = 0.1;
float m_fImgage_Scale_Y = 0.1;
// 检测分析参数
AnalysisyConfigST *m_pAnalysisyConfig;
CommonConfigNodeST *m_pCommonAnalysisyConfig;
ALLChannelCheckFunction *m_pChannelFuntion; // 画面检测功能
BaseCheckFunction *m_pbaseCheckFunction; // 基础检测
RegionConfigST *m_pRegionAnalysisyParam; // 分析参数
BasicConfig *m_pBasicConfig;
// 检查缺陷对应参数中的位置。
int m_QxInParamListIdx[CONFIG_QX_NAME_count];
std::queue<std::shared_ptr<DrawInfo>> m_DrawInfoList;
std::mutex m_task_mutex_;
std::condition_variable m_task_cv_;
std::shared_ptr<std::thread> ptr_thread_Draw;
std::condition_variable m_drawComplate_cv_;
std::shared_ptr<QX_Merge_Analysis> m_pQX_Merge_Analysis;
};
#endif

@ -0,0 +1,44 @@
#ifndef IMAGE_STORAGE_H
#define IMAGE_STORAGE_H
#include <opencv2/opencv.hpp>
#include <string>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
class ImageStorage {
private:
std::queue<std::pair<cv::Mat, std::string>> imageQueue;
std::mutex queueMutex;
std::condition_variable cv;
std::thread storageThread;
static ImageStorage* instance; // 静态成员指针,存储单例对象
bool stopFlag;
// 私有构造函数和析构函数,防止外部创建实例
ImageStorage();
~ImageStorage();
// 存储线程的工作函数
void storeImages();
public:
// 获取单例实例
static ImageStorage* getInstance();
// 禁止拷贝构造和赋值
ImageStorage(const ImageStorage&) = delete;
ImageStorage& operator=(const ImageStorage&) = delete;
// 添加图片到队列
int addImage(const std::string &path,const cv::Mat &image,bool badd = false);
// 停止存储线程
void stop();
};
#endif // IMAGE_STORAGE_H

@ -0,0 +1,344 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-30 16:17:49
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef ImgCheckAnalysisy_H_
#define ImgCheckAnalysisy_H_
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <opencv2/opencv.hpp>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <thread>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "BlobBase.h"
#include "ImgCheckBase.h"
#include "ImageDetBase.h"
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
#include "CheckConfigDefine.h"
#include "ConfigBase.h"
#include "ImageDetConfig.h"
#include "OtherDetect.h"
#include "Define_Error.h"
#include "AI_Factory.h"
#include "ImageAllResult.h"
#include "Task.h"
#include "ImageStorage.h"
#include "AIClassify.h"
#include "AI_Second_Det.h"
#include "AI_Edge_QX_Det.h"
using namespace std;
using namespace cv;
enum AT_THRESHOLD_TYPE_
{
AT_THRESHOLD_TYPE_NULL,
AT_THRESHOLD_TYPE_READY,
AT_THRESHOLD_TYPE_BUSY,
AT_THRESHOLD_TYPE_COMPLETE,
};
// 全局静态变量, 记录图像灰度值异常累计数量
static int g_nImgBrightnessErrorCount = 0;
class ImgCheckAnalysisy : public ImgCheckBase
{
public:
ImgCheckAnalysisy();
~ImgCheckAnalysisy();
// 初始化参数 pconfig 参数指针 返回0 成功 其他异常
int RunStart(void *pconfig1);
// 设置检测数据,并开启检测 返回0 成AT_THRESHOLD_TYPE_READY功 其他异常
int SetDataRun_SharePtr(std::shared_ptr<ImageAllResult> p);
// 获取结果信息 返回0 成功 其他异常
int GetCheckReuslt(std::shared_ptr<ImageDetResult> &pResult);
int CheckImg(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult);
int ReJsonResul(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult);
// 获取检测库 状态信息 返回CHECK_THREAD_RUN_STATUS
int GetStatus();
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
int UpdateConfig(void *pconfig, int nConfigType);
std::string GetVersion();
std::string GetErrorInfo();
int creatsavedir();
private:
// 加载运行参数
int LoadRunConfig(void *p);
// 加载分析参数
int LoadCheckConfig(void *p);
/// @brief 初始化并且启动程序
/// @return
int InitRun(int nId);
/// @brief 开启检测
/// @return
int StartCheck();
/// @brief 设置空闲
/// @return
int SetIDLE();
private:
// 开启线程
int StartThread(int nId);
// 停止线程
int StopThread();
// 退出系统
int ExitSystem();
// 初始化模型
int InitModel();
double CalBlobHJ(cv::Mat &img, const cv::Mat &mask, cv::Rect &det_roi, cv::Rect &qx_roi, int expand = 10);
cv::Scalar calc_blob_info_withstats(cv::Mat &img, const cv::Mat &mask, cv::Rect &stats, cv::Size k_size = cv::Size(5, 5), int expand = 10, double threshold = 0.7);
// 检测
int CheckRun();
// 计算产品尺寸
int CalProductSize();
// 图片预处理
int ImgPreDet();
// 处理签的 预处理
int DetPreImage();
// 每个检测通道 都更新 屏蔽区域
int UpdateSheildMask(std::string strChannel, cv::Rect roi);
// 异显检测
int AI_Det_YX(const cv::Mat &cropImg);
// 缺失pol检测
int Detect_LackPol(const cv::Mat &cropImg);
std::string ConfigTypeToWebDetType(int nconfigType);
bool JudgeQXAnalysis(int nqx_configType, std::shared_ptr<DetLog> pQxlog);
// 设置新的检测参数
int SetNewConfig();
int GetParamidx(); // 获得参数索引
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能
private:
// 图片处理线程
std::shared_ptr<std::thread> ptr_thread_Run;
int Run(int nId); // 运行;
// 图片处理线程
std::shared_ptr<std::thread> ptr_thread_AI;
int set_cpu_id(const std::vector<int> &cpu_set_vec);
// 计算BLob 其他一些属性值。
int CalBlob_Other();
// 计算灰阶
int CalBLobMean_GrayDis();
// 分类
int GetClassImg(const cv::Mat &img, cv::Mat &AIdetImg, cv::Rect qx_roi, int detwidth, int detheight);
// 计算缺陷长度
float Cal_QXLen(cv::Mat qx_maskImg, int qx_type, float fsc_x, float fsc_y);
float CalImgScorl(cv::Mat det_img, cv::Mat up_img);
float CalImgScorl_t(cv::Mat det_img, cv::Mat up_img);
// 获取检测结果blob用于后续分析。
int GetCheckResultBLob();
// 亮的判断
int LDJudge(int nconfigtype, cv::Rect roi, float JudgeArea, int maxV, int hj, std::shared_ptr<DetLog> pQxlog);
// 使用 DP mask 进行二次判断
int UseDPMask(int L0, int nconfigtype, cv::Rect roi, float JudgeArea, int maxV, int hj, std::shared_ptr<DetLog> pQxlog);
// 更新亮点参数
int UPdateLDConfig();
// 获得所有blob
int GetALLBlob();
// 获得YX blob
int GetBLob_YX();
// 获得 缺pol blob
int GetBlob_LackPol();
// 获得 缺陷 blob
int GetBlob_QX();
// 获得 127cell blob
int GetBlob_127cell();
// 对AI mask图片进行 结果处理
int AIMaskDet();
// 轮廓处理
int Contours();
// 检测初始化
int CheckImgInit();
// 参数 核对
int ConfigCheck(cv::Mat img);
// 多线程方式处理
int AI_Detect_Thread();
// 多线程方式处理Other AI检测
int AI_Other_Det_Thread();
// 缺陷检测
int AI_Detect_QX();
// 127cell
int AI_Detect_127Cell();
// 缺陷分类
int AI_QX_Class_Thread();
// 多线程 任务运行管理器
int ThreadTask(int nId); // 运行;
// resize 图片
int ResizeImg();
// AI 推理任务函数
void TaskFun_AIDet(std::shared_ptr<TaskInfo> task);
// AI 推理任务函数
void TaskFun_AI_Other(std::shared_ptr<TaskInfo> task);
// 缺陷分类任务函数
void TaskFun_QxClass(std::shared_ptr<TaskInfo> task);
// 更新 检测区域
int Update_DetRoiList();
// 边缘检测
int Edge_Det();
// 临时绘制结果
int DrawResult_Step_1();
// 参数缺陷类型转 结果参数类型
int AIClassTypeToConfigType(int nAIQXType, cv::Rect qx_roi);
// 更新成像精度
int UpdateImgageScale();
// 把blob 汇总成 检测结果。
int BLobToDetResult();
// 二次计算缺陷面积
int ReCalQX_AreaAndLen(AI_SecondDet::DetConfigResult *pdetConfig);
// 创建检测 小图区域。
int CreatAIDetSmallRoi(const cv::Mat &detimg, std::shared_ptr<AIModel_Base> pAI_Model, std::vector<cv::Rect> &SmallList);
// 多区域分类
int AI_Classify_New(const cv::Mat &src_Img, cv::Rect qx_roi, float fjustarea, float *fmaxScore);
// 利用Up 画面过滤
float UseUpMaskAnalysis(cv::Rect teroi, const cv::Mat AIMaskImg, std::shared_ptr<DetLog> pQxlog);
// 缺陷是否要进行检测分析 缺陷是参数类型的缺陷
bool Judge_MarkLine_QX(int nqx_configType, cv::Rect detqx_Roi, std::shared_ptr<DetLog> pQxlog);
std::shared_ptr<AIFactory> AI_Factory;
private:
int m_nErrorCode; // 错误代码
bool m_bInitSucc; // 初始化状态
bool m_bExit; // 是否退出检测
int m_nThreadIdx; // 线程序号 //相机处理的顺序号,该序号 程序运行就已经固定
std::shared_ptr<AIMulThreadRunBase> runner;
// 所有的检测结果
std::shared_ptr<ImageAllResult> m_pImageAllResult;
std::shared_ptr<DetLog> m_pdetlog;
std::shared_ptr<One_Image_CheckResult_> m_pDetResult; // 检测结果 后续主要对pDetResult 继续分析
std::shared_ptr<shareImage> DetImgInfo_shareP;
// 检测结果
std::shared_ptr<CheckResult> m_CheckResult_shareP;
// 检测参数模块
ConfigBase *m_pConfig;
int m_nConfigIdx;
// 线程运行的一些参数
RunInfoST m_RunConfig;
float m_fImgage_Scale_X;
float m_fImgage_Scale_Y;
// 分析参数
AnalysisyConfigST m_AnalysisyConfig;
ChannelCheckFunction *m_pFuntion;
BaseCheckFunction *m_pbaseCheckFunction; // 基础检测
CommonConfigNodeST *m_pCommonAnalysisyConfig;
BasicConfig *m_pBasicConfig;
RegionConfigST *m_pRegionAnalysisyParam; // 分析参数
int m_QxInParamListIdx[CONFIG_QX_NAME_count];
cv::Rect m_CutRoi;
cv::Rect m_Crop_Roi_paramImg; // 裁切在参数模板图上的 位置。
std::string m_strCurDetCamChannel; // 当前处理的图片通道
std::string m_strCurDetChannel; // 当前处理的图片通道
int m_nRun_Status; // 运行状态:空闲,运行中,异常,。。。。。
int m_nCheckResultErrorCode;
Detect_ROI_Config m_DetRoiList; // 检测区域roi List
ERROR_DOTS_BLOBS blobs;
OtherDet_Config m_OtherDet_Config;
std::vector<QXImageResult> m_Draw_qxImageResult; // 缺陷小图结果
std::vector<cv::Rect> SmallRoiList;
int det_SmallImgNum;
std::string m_strRootPath_TA_cls;
std::string m_strRootPath_CA_cls;
std::string m_strSavePath_cls;
std::string m_strLastDate;
ImageStorage *m_pImageStorage;
AI_SecondDet m_SecondDet; // 二次分割检测
// AI 推理的所有结果, 可能会返回去。需要临时存储。
std::queue<std::shared_ptr<AIMulThreadRunBase::AITask>> m_AIMaskImgBLobQueue;
std::mutex mtx_AIMaskImgBLobQueue;
AIClassify m_AIClassify; // 缺陷分类
AI_Edge_QX_Det m_AIEdge_QX_Det; // 边缘缺陷检测
Task m_task;
std::shared_ptr<TaskInfo> m_AItask;
std::shared_ptr<TaskInfo> m_AI_Other_task; // 其他类型的AI推理
std::shared_ptr<TaskInfo> m_Classtask; // 缺陷分类任务
LD_ConfigT_ m_LDConfig;
LD_ConfigT_ m_LD_WTBConfig;
LD_ConfigT_ m_LD_HSConfig;
};
#endif

@ -0,0 +1,117 @@
#ifndef ImgCheckBase_H_
#define ImgCheckBase_H_
#include <string>
#include <memory>
#define ALL_INTERFACE_VERSION 6
#define MAX_GPU_NUM 4
enum CHECK_THREAD_RUN_STATUS
{
CHECK_THREAD_STATUS_IDLE, // 空闲 0
CHECK_THREAD_STATUS_READY, // 准备好了 1
CHECK_THREAD_STATUS_BUSY, // 运行中 2
CHECK_THREAD_STATUS_COMPLETE, // 检测完成 3
CHECK_THREAD_STATUS_ERROR, // 运行错误 4
};
// 检测工位序号
enum DETECT_WROK_IDX
{
DETECT_WROK_0, // 0工位
DETECT_WROK_1, // 1工位
DETECT_WROK_2, // 2工位
DETECT_WROK_COUNT,
};
struct RunInfoST
{
int nThreadIdx; // 线程号id
int nWorkIdx; // 工位号
int nDeviceId; // GPU 设备 号 0 或 1
int UseGPUList[MAX_GPU_NUM]; // 使用的GPU设备号
int nCpu_start_Idx; // 绑定cpu 核号,
int nCpu_num; // 8 至少需要 8个
bool bSaveCheckImg; // 是否存储
bool bRetest; // 是否是复测标志,复测不需要加载模型
int flag1;
int flag2;
std::string str1;
std::string str2;
RunInfoST()
{
nThreadIdx = 0;
nDeviceId = 0;
nWorkIdx = DETECT_WROK_0;
nCpu_start_Idx = 0;
nCpu_num = 8;
flag1 = 0;
flag2 = 0;
bRetest = false;
str1 = "";
str2 = "";
bSaveCheckImg = false;
for (int i = 0; i < MAX_GPU_NUM; i++)
{
UseGPUList[i] = -1;
}
UseGPUList[0] = 0;
UseGPUList[1] = 1;
}
void copy(RunInfoST tem)
{
for (int i = 0; i < MAX_GPU_NUM; i++)
{
this->UseGPUList[i] = tem.UseGPUList[i];
}
this->nDeviceId = tem.nDeviceId;
this->nThreadIdx = tem.nThreadIdx;
this->nWorkIdx = tem.nWorkIdx;
this->nCpu_start_Idx = tem.nCpu_start_Idx;
this->nCpu_num = tem.nCpu_num;
this->bSaveCheckImg = tem.bSaveCheckImg;
this->flag1 = tem.flag1;
this->flag2 = tem.flag2;
this->bRetest = tem.bRetest;
this->str1 = tem.str1;
this->str2 = tem.str2;
}
};
/*******************一般调用流程*************************************************************************************************************************/
/*******************1、初始化 UpdateConfig*************************************************************************************************************************/
/*******************2、初始化 Init 并开启 *************************************************************************************************************************/
/*******************3、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_IDLE 可以设置检测数据并开启检测 SetDataRun***************************************************/
/*******************4、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_COMPLETE 检测完成,可以获取检测结果 GetCheckReuslt 拷贝检测结果 自动把状态设为 CHECK_THREAD_STATUS_IDLE*****************************/
struct shareImage;
struct CheckResult;
class ALLImgCheckBase
{
protected:
ALLImgCheckBase() {}
public:
// delete camera interface
~ALLImgCheckBase() {}
static ALLImgCheckBase *GetInstance();
// 初始化参数 pconfig 参数指针 返回0 成功 其他异常
virtual int RunStart(void *pconfig1 = NULL) = 0;
// 设置检测数据,并开启检测 返回0 成功 其他异常
virtual int SetDataRun_SharePtr(std::shared_ptr<shareImage> p) = 0;
// 获取结果信息 返回0 成功 其他异常
virtual int GetCheckReuslt(std::shared_ptr<CheckResult> &pResult) = 0;
virtual int CheckImg(std::shared_ptr<shareImage> p, std::shared_ptr<CheckResult> &pResult) = 0;
// 获取检测库 状态信息 返回CHECK_THREAD_RUN_STATUS
virtual int GetStatus() = 0;
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
virtual int UpdateConfig(void *pconfig, int nConfigType) = 0;
// 返回检测版本信息
virtual std::string GetVersion() = 0;
// 返回错误信息
virtual std::string GetErrorInfo() = 0;
static ALLImgCheckBase *instance;
};
#endif

@ -0,0 +1,518 @@
/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2022-03-16 17:09:11
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-24 17:48:07
*/
/***********************************************/
/************ ***************/
/************金佰利检测算法参数定义**************/
/************ **************/
/**********************************************/
#ifndef _ImgCheckConfig_HPP_
#define _ImgCheckConfig_HPP_
#include <string>
#include <opencv2/opencv.hpp>
#include <unordered_map> // unordered_map
#define RESULT_VERSION 31
#define MAX_BLOB_NUM 200
// 输入模型图片尺寸
#define SRCIMG_WIDTH 14200
#define SRCIMG_HEIGHT 10640
#define CHECKIMG_HEIGHT 2000
#define CHECKIMG_WIDTH 4000
#define MASK_IMG_STEP 16
#define MASK_IMG_STARTVALUE 48
// 检测日志 等级
enum DET_LOG_LEVEL_
{
DET_LOG_LEVEL_0, // 极简信息
DET_LOG_LEVEL_1, // 包含检测关键信息
DET_LOG_LEVEL_2, // 关键信息+ 一般节点信息
DET_LOG_LEVEL_3, // 详细信息
};
struct VERSION_INFO
{
int ConfigVersion = 0;
int ResultVersion = RESULT_VERSION;
int InterfaceVersion = 0;
};
// 检测错误代码
enum ERROR_TYPE_
{
ERROR_TYPE_OK, // 0 疑是
ERROR_TYPE_AD_YX, // 1 AD-异常显示
ERROR_TYPE_Line_X, // 2 x line
ERROR_TYPE_Line_Y, // 3 y line
ERROR_TYPE_Line_fangge, // 3 y line
ERROR_TYPE_Rubbing_Mura, // 4
ERROR_TYPE_line_Broken, // 5 断线
ERROR_TYPE_ZARA, // 6 ZARA
ERROR_TYPE_MTX, // 7 MTX
ERROR_TYPE_POL_Cell, // 8 异物
ERROR_TYPE_LD, // 9 亮点
ERROR_TYPE_AD, // 10 暗点
ERROR_TYPE_BD, // 11 黑点
ERROR_TYPE_WD, // 12 白点
ERROR_TYPE_Scratch, // 13 划伤
ERROR_TYPE_Weak_Bright_Mura, // 14 白GAP
ERROR_TYPE_No_Label, // 15 缺POL
ERROR_TYPE_PS, // 16 PS
ERROR_TYPE_GRID_LINE, // 17 方格线
ERROR_TYPE_STEAM_POCKET, // 19 气泡
ERROR_TYPE_Dirty, // 19 脏污
ERROR_TYPE_Other, // 19 other
ERROR_TYPE_Cell_W, // 19 other
ERROR_TYPE_Cell_B, // 19 other
ERROR_TYPE_LackPol, // 缺失Pol
ERROR_TYPE_COUNT,
};
static const std::string QX_Result_Names[] =
{
"OK",
"AD_YX",
"X_Line",
"Y_Line",
"fangge",
"Rubbing_Mura",
"Broken_line",
"ZARA",
"MTX",
"POL_Cell",
"Bright_Point",
"Dark_Point",
"BLack_Point",
"White_Point",
"Scratch",
"Weak_Bright_Mura",
"No_Label",
"Bright_Mura_Exe",
"Sweak_Line_Dark",
"STEAM_POCKET",
"Dirty",
"other",
"Cell_W",
"Cell_B",
"LackPol"};
static const std::string QX_Result_Code[] =
{
"P1153",
"P6873",
"P3351",
"P3452",
"P3453",
"P1550",
"P3379",
"P1153",
"P1164",
"P1101",
"P1112",
"P1111",
"P1104",
"P1103",
"P1557",
"P1654",
"P2833",
"P1549",
"P1204",
"P2534",
"P2534",
"P1101",
"P1103",
"P1104",
"P8001",
};
// 检测检测参数类型
enum CHECK_CONFIG_TYPE_
{
CHECK_CONFIG_Run, // 运行参数
CHECK_CONFIG_Module, // 参数模块
CHECK_CONFIG_COUNT,
};
// 输入检测图片的
enum IMG_INPUT_
{
IMG_INPUT_SRC,
IMG_INPUT_COUNT,
};
// 输入检测缺陷小图
enum IMG_OUTPUT_
{
IMG_OUTPUT_RESIZE,
IMG_OUTPUT_COUNT,
};
// 输入图片的状态
enum IN_IMG_Status_
{
IN_IMG_Status_Start,
IN_IMG_Status_Other,
IN_IMG_Status_End,
IN_IMG_Status_OneImg,
};
// 检测模式
enum DET_MODE_
{
DET_MODE_NULL,
DET_MODE_EDGE,
DET_MODE_MergeImg,
DET_MODE_ZF,
DET_MODE_YX,
DET_MODE_UP,
DET_MODE_Det,
DET_MODE_MarkLine,
DET_MODE_ReJson,
};
#define MAX_REGION_NUM 20
// 一个检测项基本信息,包括图片序号,图片、开始时间
struct shareImage
{
int Det_Mode; // 检测模式
int Status;
bool bmergeImg; /// 是否合并图片
int camera_ID; // 相机ID
int img_id;
cv::Mat img;
cv::Mat img_B;
cv::Mat other_channel_Result_mask;
cv::Mat AI_maskImg; // 推理图片
std::string strSnowID; // 相机发古来的雪花码
long getImgTimeMs; // 获取图片的时间点
long readImg_start;
long readImg_end;
long time_PushIn;
long time_sendCheck;
long time_startCheck;
long time_EndCheck;
int imgtype;
cv::Rect cutRoi;
int ninstruct; // 运行指令
int nlogLevel; // 日志等级
std::string strCameraName; // 相机名称
std::string strImgProductID; // 产品名称
std::string strChannel; // 通道名称
std::string strImgName; // 图片名称
std::string imgstr;
std::string strParm_WorkCamName; // 对应的界面参数 的工位相机名称。 ==等价于 相机管理的 CODE
int nImgBigIdx;
int otherValue;
int otherValue_1;
std::string resultJson; // 检测结果 json 字符串
bool bDebugsaveImg; // 保存处理图片
std::unordered_map<std::string, int> runCommand; // 运行命令 map
shareImage()
{
Init();
}
~shareImage()
{
}
void Init()
{
if (!img.empty())
{
img.release();
}
if (!img_B.empty())
{
img_B.release();
}
if (!other_channel_Result_mask.empty())
{
other_channel_Result_mask.release();
}
if (!AI_maskImg.empty())
{
AI_maskImg.release();
}
Det_Mode = 0;
Status = 0;
nlogLevel = DET_LOG_LEVEL_0;
img_id = -1;
getImgTimeMs = 0;
time_PushIn = 0;
time_sendCheck = 0;
time_startCheck = 0;
time_EndCheck = 0;
readImg_start = 0;
readImg_end = 0;
imgtype = 0;
imgstr = "";
strSnowID = "";
camera_ID = 0;
strImgName = "";
strCameraName = "";
strImgProductID = "";
strChannel = "";
nImgBigIdx = 0;
cutRoi = cv::Rect(0, 0, 0, 0);
otherValue = 0;
ninstruct = 0;
resultJson = "";
strParm_WorkCamName = "";
bDebugsaveImg = false;
bmergeImg = false;
}
void InitImg(int ImgW, int imgH, bool Isgray = true)
{
if (Isgray)
{
img = cv::Mat(imgH, ImgW, CV_8UC1);
}
else
{
img = cv::Mat(imgH, ImgW, CV_8UC3);
}
}
};
// 检测结果基本信息
struct BasicResult
{
int img_id;
long checkUseTimeMs; // 所有时间
int64_t snowId; // 雪花ID
int imgtype;
std::string imgstr;
std::string strChannel;
void Init()
{
img_id = 0;
checkUseTimeMs = 0;
snowId = 0;
imgtype = 0;
imgstr = "";
strChannel = "";
}
void copy(BasicResult tem)
{
this->img_id = tem.img_id;
this->checkUseTimeMs = tem.checkUseTimeMs;
this->snowId = tem.snowId;
this->imgtype = tem.imgtype;
this->imgstr = tem.imgstr;
this->strChannel = tem.strChannel;
}
};
struct DetectInfo
{
int nresult;
std::string keyName;
std::string keyCode;
int num;
DetectInfo()
{
Init();
}
void Init()
{
nresult = 0;
num = 0;
keyName = "";
keyCode = "";
}
void copy(DetectInfo tem)
{
this->nresult = tem.nresult;
this->num = tem.num;
this->keyName = tem.keyName;
this->keyCode = tem.keyCode;
}
};
struct QXImageResult
{
int type; // 缺陷类型
std::string qx_Code; // 缺陷code
std::string strTypeName; // 缺陷名称
cv::Mat srcImg; // 缺陷原始图片
cv::Mat resizeImg; // 缺陷缩略图
cv::Mat AI_in_Img;
cv::Mat AI_out_img;
cv::Rect srcImgroi; // 相对原图的 框坐标;
cv::Rect CutImgroi; // 裁剪原图 框坐标;
cv::Rect resizeImgroi; // 相对相对小图 框坐标;
float x_pixel; // 缺陷坐标 像素
float y_pixel; // 缺陷坐标 像素
float x_mm; // 缺陷坐标 mm
float y_mm; // 缺陷坐标 mm
int idx;
float area;
float energy;
float hj;
float max_v;
float len;
float fScore;
int qx_type; // 缺陷的原因
float minDis_mm;
int qx_num;
float density; // 密度
QXImageResult()
{
Init();
}
void Init()
{
if (!srcImg.empty())
{
srcImg.release();
}
if (!resizeImg.empty())
{
resizeImg.release();
}
if (!AI_in_Img.empty())
{
AI_in_Img.release();
/* code */
}
if (!AI_out_img.empty())
{
AI_out_img.release();
/* code */
}
x_pixel = 0;
y_pixel = 0;
x_mm = 0;
y_mm = 0;
type = 0;
area = 0;
energy = 0;
hj = 0;
max_v = 0;
strTypeName = "";
qx_Code = "";
len = 0;
idx = 0;
fScore = 0;
qx_type = 0;
minDis_mm = 0;
qx_num = 0;
density = 0;
srcImgroi = cv::Rect(0, 0, 0, 0);
CutImgroi = cv::Rect(0, 0, 0, 0);
resizeImgroi = cv::Rect(0, 0, 0, 0);
}
};
// 结果信息
struct CheckResult
{
// 原始图片,输入检测的图片
int checkStatus;
int nDetStep; // 处理步骤
int nresult;
int nProductResult; // 产品结果
int nYS_result;
float productWidht_mm; // 产品宽度 毫米
float productHeight_mm; // 产品 高度 毫米
cv::Mat cutSrcimg;
cv::Mat resultimg;
cv::Mat SrcResultImg; // 结果
cv::Mat resultMaskImg; // AI mask Result
std::shared_ptr<shareImage> in_shareImage; // 输入图片信息
DetectInfo defectResultList[ERROR_TYPE_COUNT]; // 缺陷检测结果list
BasicResult basicResult; // 基本检测结果信息
std::vector<QXImageResult> qxImageResult; // 缺陷小图结果
std::vector<QXImageResult> YS_ImageResult; // 疑似小图结果
std::vector<std::string> det_LogList; // 检测日志
std::string strResultJson; // 缺陷结果 jason
bool bSaveALL;
int nflage1;
int nflage2;
CheckResult()
{
Init();
}
~CheckResult()
{
release();
}
void Init()
{
nProductResult = 0;
checkStatus = 0;
nDetStep = 0;
nresult = ERROR_TYPE_OK;
nYS_result = ERROR_TYPE_OK;
bSaveALL = false;
nflage1 = 0;
nflage2 = 0;
productWidht_mm = 0;
productHeight_mm = 0;
basicResult.Init();
strResultJson = "";
if (!resultimg.empty())
{
resultimg.release();
}
if (!cutSrcimg.empty())
{
cutSrcimg.release();
}
if (!SrcResultImg.empty())
{
SrcResultImg.release();
}
if (!resultMaskImg.empty())
{
resultMaskImg.release();
}
for (int i = 0; i < ERROR_TYPE_COUNT; i++)
{
defectResultList[i].Init();
}
std::vector<QXImageResult> tmp;
qxImageResult.swap(tmp);
YS_ImageResult.swap(tmp);
qxImageResult.erase(qxImageResult.begin(), qxImageResult.end());
YS_ImageResult.erase(YS_ImageResult.begin(), YS_ImageResult.end());
det_LogList.erase(det_LogList.begin(), det_LogList.end());
}
void release()
{
if (!resultimg.empty())
{
resultimg.release();
}
if (!cutSrcimg.empty())
{
cutSrcimg.release();
}
if (!SrcResultImg.empty())
{
SrcResultImg.release();
}
if (!resultMaskImg.empty())
{
resultMaskImg.release();
}
strResultJson = "";
std::vector<QXImageResult> tmp;
qxImageResult.swap(tmp);
YS_ImageResult.swap(tmp);
det_LogList.erase(det_LogList.begin(), det_LogList.end());
}
};
#endif //_CORELOGICFACTORY_HPP_

@ -0,0 +1,36 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-17 18:57:39
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef OtherDetBaseDefine_H_
#define OtherDetBaseDefine_H_
#include <string>
#include <iostream>
#include "CheckErrorCodeDefine.hpp"
#include "BlobBase.h"
using namespace std;
struct OtherDet_Config
{
int nDeviceId; // GPU 号
int nUserValue;
int nShowImg_Width;
int nShowImg_Height;
OtherDet_Config()
{
nDeviceId = 0;
nUserValue = 0;
nShowImg_Width = 100;
nShowImg_Height = 100;
}
};
#endif

@ -0,0 +1,73 @@
/*
//其他类的检测
*/
#ifndef OtherDetect_H_
#define OtherDetect_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "OtherDetBaseDefine.h"
#include "CheckErrorCodeDefine.hpp"
using namespace std;
using namespace cv;
// 基础类
class AIDetectBase
{
public:
AIDetectBase(/* args */);
~AIDetectBase();
int Init(OtherDet_Config *pOtherDet_Config);
protected:
OtherDet_Config *m_pOtherDet_Config;
bool m_bInitialized;
bool m_bModelSucc;
};
// 缺pol 检测
class LackPolDet : public AIDetectBase
{
public:
/// @brief 检测过程的参数
struct DetConfig
{
float fImgage_Scale_X;
float fImgage_Scale_Y;
bool bSaveResultImg; // 保存结果图片
std::string strChannel; // 通道名称
cv::Mat detMaskImg; // 检测区域图片
DetConfig()
{
Init();
}
void Init()
{
fImgage_Scale_X = 0.03f;
fImgage_Scale_Y = 0.03f;
bSaveResultImg = false;
strChannel = "";
}
void Print()
{
printf("bSaveResultImg %s strChannel %s\n",
BOOL_TO_STR(bSaveResultImg), strChannel.c_str());
}
};
public:
LackPolDet(/* args */);
~LackPolDet();
int InitModel_ALL();
int Detect(const cv::Mat &img, DetConfig *pDetConfig, cv::Mat &outMask);
private:
int Init_LackPol();
public:
private:
};
#endif

@ -0,0 +1,62 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-16 21:19:45
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef Product_H_
#define Product_H_
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <opencv2/opencv.hpp>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <thread>
#include <string>
#include <stdlib.h>
#include "Define_Product.hpp"
#include "CameraResult.h"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
using namespace std;
using namespace cv;
class Product
{
private:
/* data */
public:
Product(/* args */);
~Product();
std::shared_ptr<CameraResult> GetCameraResult(std::string strcameraName);
void AddLog(std::string str);
// 更新 送图状态
void UpdatePushStatus(int status);
// 是否全部检测完成
bool bCheckCamplate();
public:
// 相机结果
std::vector<std::shared_ptr<CameraResult>> m_pCameraResultList;
std::shared_ptr<ProductBaseResult> productBaseResult;
// 图片是否都送完了。
bool bIsImgComplete = false;
// 日志
std::vector<std::string> LogList;
std::mutex mtx_CameraResultList;
private:
std::mutex mtx_;
// 多线程安全
PRINT_LOG_ m_PrintLog;
};
#endif

@ -0,0 +1,324 @@
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef QX_Analysis_H_
#define QX_Analysis_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "CheckErrorCodeDefine.hpp"
using namespace std;
enum QX_ANALYSIS_NAME
{
QX_ANALYSIS_POL_CELL, // 异物
QX_ANALYSIS_AD, // 暗点
QX_ANALYSIS_Scratch, // 划伤
QX_ANALYSIS_LINE, // 线类
QX_ANALYSIS_MTX, // MTX
QX_ANALYSIS_ALL, // MTX&异物
QX_ANALYSIS_COUNT,
};
// 缺陷项对应在参数中的名称
static const std::string QX_ANALYSIS_NAME_Names[] =
{
"POL_Cell",
"AD",
"Scratch",
"LINE",
"MTX",
"POL_Cell&MTX"};
// 预处理参数
struct Pre_Analysisy_Param
{
float fAreaMin = 0; // 面积最小值
float fHJMin = 0; // 灰度最小值
float fLenMin = 0; // 长度最小值
float fMdMin = 0; // 密度最小值
};
// 记录缺陷信息
struct QX_Info
{
std::string camera_name;
std::string channel_name;
float area; // 面积
float energy; // 能量
float hj; // 灰阶
float length; // 长度
float density; // 密度
cv::Point2f plocatin_mm; // 位置mm
cv::Point2f plocatin_pixel; // 位置 像素
cv::Point2f pLocation_Product_mm; // 位置mm相对于产品的。位置
int blobIdx; // blob idx;
int result;
float fmindis;
int nmindis_BlobIdx;
cv::Point mindis_locatin_pixel; // 位置 像素
int nstatus;
int nqx_type;
float tem_dis;
float tem_dis_idx;
cv::Rect roi;
cv::Rect product_roi;
QX_Info()
{
Init();
}
void Init()
{
area = 0;
energy = 0;
hj = 0;
length = 0;
plocatin_mm = cv::Point2f(0, 0);
plocatin_pixel = cv::Point(0, 0);
blobIdx = 0;
result = 0;
fmindis = 0;
mindis_locatin_pixel = cv::Point(0, 0);
pLocation_Product_mm = cv::Point2f(0, 0);
nstatus = 0;
nqx_type = 0;
nmindis_BlobIdx = 0;
density = 0;
camera_name = "";
channel_name = "";
tem_dis = 0;
tem_dis_idx = 0;
roi = cv::Rect(0, 0, 0, 0);
product_roi = cv::Rect(0, 0, 0, 0);
}
void print(std::string str)
{
printf("%s blobIdx %d,result %d area %f energy %f hj %f length %f md %f x %f y %f x %f y %f \n",
str.c_str(), blobIdx, result, area, energy, hj, length, density, plocatin_mm.x, plocatin_mm.y, plocatin_pixel.x, plocatin_pixel.y);
printf("%s blobIdx %d,fmindis %f mindis_locatin_pixel x %d y %d \n",
str.c_str(), blobIdx, fmindis, mindis_locatin_pixel.x, mindis_locatin_pixel.y);
}
std::string GetInfo()
{
char buffer[64];
sprintf(buffer, "idx:%d A:%0.2f,HJ:%0.2f,Len:%0.2f,md:%0.2f,dis:%0.2f",
blobIdx, area, hj, length, density,tem_dis);
std::string str123 = buffer;
return str123;
}
};
struct QX_ALL_List
{
std::vector<QX_Info> qxList;
QX_ALL_List()
{
Init();
}
void Init()
{
qxList.erase(qxList.begin(), qxList.end());
qxList.clear();
// config.Init();
}
};
struct QX_channel_List
{
std::shared_ptr<DetLog> pChannelDetlog;
std::shared_ptr<DetLog> pChannelDetlog2;
std::string channel_name;
std::vector<QX_Info> qxList;
QX_channel_List()
{
Init();
}
void Init()
{
qxList.erase(qxList.begin(), qxList.end());
qxList.clear();
channel_name = "";
// config.Init();
}
void Initstatus()
{
for (int i = 0; i < qxList.size(); i++)
{
qxList[i].nqx_type = 0;
qxList[i].nstatus = 0;
qxList[i].tem_dis = 0;
qxList[i].tem_dis_idx = -1;
}
}
bool preDet(int i, Pre_Analysisy_Param param, std::string &strinfo)
{
strinfo = "";
bool return_value = true;
if (qxList[i].area < param.fAreaMin)
{
return_value = false;
strinfo += "A:false";
}
if (qxList[i].hj < param.fHJMin)
{
return_value = false;
strinfo += "HJ:false";
}
if (qxList[i].density < param.fMdMin)
{
return_value = false;
strinfo += "md:false";
}
if (qxList[i].length < param.fLenMin)
{
return_value = false;
strinfo += "Len:false";
}
return return_value;
}
void claDis()
{
for (int i = 0; i < qxList.size(); i++)
{
if (qxList[i].nstatus != 1)
{
continue;
}
double mindis = 99999999999;
int mindix = -1;
for (int j = 0; j < qxList.size(); j++)
{
if (i == j || qxList[j].nstatus != 1)
{
continue;
}
float dis = CheckUtil::calDis(qxList[i].pLocation_Product_mm, qxList[j].pLocation_Product_mm);
if (dis < mindis)
{
mindis = dis;
mindix = j;
}
}
if (mindix != -1)
{
qxList[i].tem_dis = mindis;
qxList[i].tem_dis_idx = mindix;
}
}
}
};
struct ALL_Qx_DataList
{
std::vector<QX_channel_List> channelqxList;
ALL_Qx_DataList()
{
Init();
}
void Init()
{
channelqxList.erase(channelqxList.begin(), channelqxList.end());
channelqxList.clear();
}
};
struct QXAnalysis_Config
{
bool bok;
int num;
float dis;
float len;
int hj;
float density;
float area;
float sum_area;
QXAnalysis_Config()
{
Init();
}
void Init()
{
bok = false;
num = 0;
dis = 0;
len = 0;
area = 0;
hj = 0;
sum_area = 0;
density = 0;
}
void print(std::string str)
{
printf("%s bok %d num %d area %f dis %f len %f hj %d md %f\n", str.c_str(), bok, num, area, dis, len, hj, density);
}
};
struct ALL_QX_ParamList
{
std::vector<QXAnalysis_Config> configlsit;
ALL_QX_ParamList()
{
Init();
}
void Init()
{
configlsit.erase(configlsit.begin(), configlsit.end());
configlsit.clear();
// config.Init();
}
};
enum QX_ERROR_TYPE_
{
QX_ERROR_TYPE_OK,
QX_ERROR_TYPE_AREA,
QX_ERROR_TYPE_NUM,
QX_ERROR_TYPE_DIS,
QX_ERROR_TYPE_Len,
QX_ERROR_TYPE_NUM_RGB255,
};
struct QX_RESULT
{
std::string camera_name;
std::string channel_name;
int blobIdx; // blob idx;
int error_Type; // 错误原因
int qx_Num; // 缺陷的数量
float mindis;
float flen;
cv::Point qx_MisDis_point_pixel; // 缺陷 间的最小距离
QX_RESULT()
{
Init();
}
void Init()
{
blobIdx = -1;
error_Type = 0;
qx_Num = 0;
flen = 0;
mindis = 0;
qx_MisDis_point_pixel = cv::Point(0, 0);
camera_name = "";
channel_name = "";
}
void print(std::string str)
{
printf("%s blobIdx %d error_Type %d qx_Num %d min dis %f flen %f x %d y %d \n",
str.c_str(), blobIdx, error_Type, qx_Num, mindis, flen, qx_MisDis_point_pixel.x, qx_MisDis_point_pixel.y);
}
};
struct QX_Analysis_Result_List
{
std::vector<QX_RESULT> resultList;
QX_Analysis_Result_List()
{
Init();
}
void Init()
{
resultList.erase(resultList.begin(), resultList.end());
resultList.clear();
// config.Init();
}
};
#endif

@ -0,0 +1,146 @@
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef QX_Merge_Analysis_H_
#define QX_Merge_Analysis_H_
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include <mutex>
#include <thread>
#include <condition_variable>
#include "CheckErrorCodeDefine.hpp"
#include "CheckConfigDefine.h"
#include "QX_Analysis.h"
using namespace std;
#define QX_MEREGE_CONFIG_CAMERA_NAME "left"
class QX_Merge_Analysis
{
public:
enum RUN_STATUS_
{
RUN_STATUS_NULL,
RUN_STATUS_IDLE,
RUN_STATUS_READY,
RUN_STATUS_BUSY,
RUN_STATUS_COMPLETE,
};
struct tem_AD_QX_Info
{
int qxidx = 0;
int channelidx = 0;
};
struct AD_Channel_Info_
{
cv::Rect roi;
cv::Point2f location_product_mm;
int num;
float fdis;
int dist_idx;
int num_2s;
int num_3s;
int num_1s;
vector<tem_AD_QX_Info> numIdxList;
vector<tem_AD_QX_Info> num_2sIdxList;
vector<tem_AD_QX_Info> num_3sIdxList;
AD_Channel_Info_()
{
roi = cv::Rect(0, 0, 0, 0);
location_product_mm = cv::Point2f(0, 0);
num = 0;
fdis = 999999999999;
dist_idx = 0;
num_1s = 0;
num_2s = 0;
num_3s = 0;
numIdxList.clear();
num_2sIdxList.clear();
num_3sIdxList.clear();
}
std::string GetInfo()
{
char buffer[256];
sprintf(buffer, "roi:[%d,%d,%d,%d] location [%f %f]num:%d fdis:%.2f dist_idx:%d num_1s:%d num_2s:%d num_3s:%d",
roi.x, roi.y, roi.width, roi.height, location_product_mm.x, location_product_mm.y,
num, fdis, dist_idx, num_1s, num_2s, num_3s);
return std::string(buffer);
}
};
public:
QX_Merge_Analysis();
~QX_Merge_Analysis();
static std::shared_ptr<QX_Merge_Analysis> GetInstance();
int Clear();
int AddCamer(std::string cameraName);
int InitData();
int GetReusult(QX_Analysis_Result_List *&presult);
void SetConfig(std::string cameraName, int qxidx, QXAnalysis_Config config);
void InitConfig(std::string cameraName);
void SetbaseCheckFunction(std::string cameraName, ALLChannelCheckFunction *pChannelFuntion, BaseCheckFunction *pbaseCheckFunction);
int ConfigTypeToQXAnalysis(int nconfigType);
bool Idx(int qxidx);
bool AddQxInfo(int qxidx, QX_Info qxinfo, std::shared_ptr<DetLog> plog, std::shared_ptr<DetLog> pchannelLog);
bool setSendStatus(std::string cameraName, RUN_STATUS_ status);
bool waitComplete(int timeoutMs = 15000);
std::shared_ptr<DetLog> m_pMergedetlog;
ALLChannelCheckFunction *m_pChannelFuntion;
BaseCheckFunction *m_pbaseCheckFunction;
private:
std::shared_ptr<std::thread>
ptr_thread_Run;
int Run(int nId); // 运行;
// 开启线程
int StartThread(int nId);
// 停止线程
int StopThread();
int StartAnalysis();
int Analysis_single_Config(QXAnalysis_Config *pconfig, QX_channel_List *pqxList, int qx_type, std::shared_ptr<DetLog> pchannelLog);
int Analysis_QXtype(ALL_Qx_DataList *pALLTypeqxList, int qx_idx);
int Analysis_Channel(QX_channel_List *pChannelqxList, int qx_idx);
int Judge_OK_Config();
int Judge_NG_Config();
int Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx);
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName);
double DistanceBetweenRectCenters(const cv::Rect &rect1, const cv::Rect &rect2, float fx, float fy);
private:
ALL_Qx_DataList m_QXList[QX_ANALYSIS_COUNT];
ALL_QX_ParamList m_ConfigList[QX_ANALYSIS_COUNT];
std::mutex mtx_QXList;
std::mutex mtx_ConfigList;
std::mutex mtx_status;
std::condition_variable cv_status;
RUN_STATUS_ m_status;
std::unordered_map<std::string, RUN_STATUS_> m_statusList;
std::unordered_map<std::string, std::shared_ptr<DetLog>> m_pdetlogList;
QX_Analysis_Result_List m_reultList;
bool m_bExit; // 是否退出检测
std::vector<AD_Channel_Info_> AD_list;
private:
};
#endif

@ -0,0 +1,97 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-16 10:14:05
* @LastEditors: xiewenji 527774126@qq.com
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef Task_H_
#define Task_H_
#include <string>
#include <opencv2/opencv.hpp>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <atomic>
#include <memory>
enum TaskName
{
Task_AI,
Task_AI_Other,
Task_Class,
Task_Count,
};
enum TaskStep
{
TaskStep_Idle,
TaskStep_Waite,
TaskStep_run,
TaskStep_compate,
};
struct TaskInfo
{
TaskName taskname;
TaskStep status; // 运行状态
int nresult; // 运行结果
// 🔑 新增变量
std::mutex mtx;
std::condition_variable cv;
// 设置状态,线程安全
void SetStatus(TaskStep newStatus)
{
{
std::lock_guard<std::mutex> lock(mtx);
status = newStatus;
}
cv.notify_all(); // 通知等待者
}
bool isComplate()
{
bool bcom = false;
{
std::lock_guard<std::mutex> lock(mtx);
if (status == TaskStep_compate)
{
bcom = true;
}
}
return bcom;
}
// 等待任务完成
void waitComplate()
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [this]
{ return status == TaskStep_compate; });
}
};
using namespace std;
class Task
{
public:
Task();
~Task();
int sendTask(std::shared_ptr<TaskInfo> task);
std::shared_ptr<TaskInfo> GetTask();
private:
std::queue<std::shared_ptr<TaskInfo>> m_tasks_;
std::mutex m_task_mutex_;
std::condition_variable m_task_cv_;
private:
public:
private:
private:
};
#endif

@ -0,0 +1,106 @@
#pragma once
#include <cstdint>
#include <chrono>
#include <stdexcept>
#include <mutex>
class snowflake_nonlock
{
public:
void lock()
{
}
void unlock()
{
}
};
template<int64_t Twepoch, typename Lock = snowflake_nonlock>
class snowflake
{
using lock_type = Lock;
static constexpr int64_t TWEPOCH = Twepoch;
static constexpr int64_t WORKER_ID_BITS = 5L;
static constexpr int64_t DATACENTER_ID_BITS = 5L;
static constexpr int64_t MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1;
static constexpr int64_t MAX_DATACENTER_ID = (1 << DATACENTER_ID_BITS) - 1;
static constexpr int64_t SEQUENCE_BITS = 12L;
static constexpr int64_t WORKER_ID_SHIFT = SEQUENCE_BITS;
static constexpr int64_t DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
static constexpr int64_t TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
static constexpr int64_t SEQUENCE_MASK = (1 << SEQUENCE_BITS) - 1;
using time_point = std::chrono::time_point<std::chrono::steady_clock>;
time_point start_time_point_ = std::chrono::steady_clock::now();
int64_t start_millsecond_ = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
int64_t last_timestamp_ = -1;
int64_t workerid_ = 0;
int64_t datacenterid_ = 0;
int64_t sequence_ = 0;
lock_type lock_;
public:
snowflake() = default;
snowflake(const snowflake&) = delete;
snowflake& operator=(const snowflake&) = delete;
void init(int64_t workerid, int64_t datacenterid)
{
if (workerid > MAX_WORKER_ID || workerid < 0) {
throw std::runtime_error("worker Id can't be greater than 31 or less than 0");
}
if (datacenterid > MAX_DATACENTER_ID || datacenterid < 0) {
throw std::runtime_error("datacenter Id can't be greater than 31 or less than 0");
}
workerid_ = workerid;
datacenterid_ = datacenterid;
}
int64_t nextid()
{
std::lock_guard<lock_type> lock(lock_);
//std::chrono::steady_clock cannot decrease as physical time moves forward
auto timestamp = millsecond();
if (last_timestamp_ == timestamp)
{
sequence_ = (sequence_ + 1)&SEQUENCE_MASK;
if (sequence_ == 0)
{
timestamp = wait_next_millis(last_timestamp_);
}
}
else
{
sequence_ = 0;
}
last_timestamp_ = timestamp;
return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT)
| (datacenterid_ << DATACENTER_ID_SHIFT)
| (workerid_ << WORKER_ID_SHIFT)
| sequence_;
}
private:
int64_t millsecond() const noexcept
{
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time_point_);
return start_millsecond_ + diff.count();
}
int64_t wait_next_millis(int64_t last) const noexcept
{
auto timestamp = millsecond();
while (timestamp <= last)
{
timestamp = millsecond();
}
return timestamp;
}
};

@ -0,0 +1,358 @@
#include "AIClassify.h"
#include "AICommonDefine.h"
bool compare_Piece(const AI_PIECE_INFO &a, const AI_PIECE_INFO &b)
{
return a.abs_L < b.abs_L;
}
AIClassify::AIClassify()
{
}
AIClassify::~AIClassify()
{
}
cv::Rect AIClassify::GetCutRoi(cv::Rect roi, const cv::Mat &img, int nwidth, int nheight)
{
cv::Rect cutroi;
int pc_x = roi.x + roi.width * 0.5;
int pc_y = roi.y + roi.height * 0.5;
bool bresize = false;
if (roi.width < nwidth && roi.height < nheight)
{
cutroi.width = nwidth;
cutroi.x = pc_x - nwidth * 0.5;
cutroi.height = nheight;
cutroi.y = pc_y - nheight * 0.5;
}
else
{
// 宽 高
if (roi.width > roi.height)
{
cutroi.width = roi.width + 20;
cutroi.x = roi.x - 10;
float fsx = nheight * 1.0f / nwidth;
cutroi.height = cutroi.width * fsx;
cutroi.y = pc_y - cutroi.height * 0.5;
}
else
{
cutroi.height = roi.height + 20;
cutroi.y = roi.y - 10;
float fsy = nwidth * 1.0f / nheight;
cutroi.width = cutroi.height * fsy;
cutroi.x = pc_x - cutroi.width * 0.5;
}
bresize = true;
}
if (cutroi.x < 0)
{
cutroi.x = 0;
}
if (cutroi.y < 0)
{
cutroi.y = 0;
}
if (cutroi.x + cutroi.width >= img.cols)
{
cutroi.x = img.cols - cutroi.width;
if (cutroi.x < 0)
{
cutroi.x = 0;
if (cutroi.x + cutroi.width >= img.cols)
{
cutroi.width = img.cols;
}
}
}
if (cutroi.y + cutroi.height >= img.rows)
{
cutroi.y = img.rows - cutroi.height;
if (cutroi.y < 0)
{
cutroi.y = 0;
if (cutroi.y + cutroi.height >= img.rows)
{
cutroi.height = img.rows;
}
}
}
return cutroi;
}
int AIClassify::GetDetRoiList(const cv::Mat &src_Img, cv::Rect qx_roi, std::vector<cv::Rect> &samllRoiList, int nwidth, int nheight)
{
// qx_roi.x = 10;
// qx_roi.y = src_Img.rows - 10;
// qx_roi.width = src_Img.rows - 150;
// qx_roi.height = 8;
int Min_SizeWH = 160;
int Max_sizeWH = 400;
// 块之间重叠度
int overlap = 100;
// 单边的块数最多
int Edge_Piece_single_Num = 7;
// 总的块数最多支持 9个。
int Edge_Piece_Sum_Num = 9;
int qx_w = qx_roi.width;
int qx_h = qx_roi.height;
// 长边、短边
int long_side = qx_w;
int short_side = qx_h;
if (qx_w >= qx_h)
{
long_side = qx_w;
short_side = qx_h;
}
else
{
long_side = qx_h;
short_side = qx_w;
}
// printf("img %d %d qx %d %d \n", src_Img.cols, src_Img.rows, long_side, short_side);
std::vector<AI_PIECE_INFO> pieceList;
if (long_side <= Min_SizeWH)
{
AI_PIECE_INFO tem;
tem.len = long_side;
tem.num = 1;
tem.long_num = 1;
tem.short_num = 1;
tem.abs_L = 0;
pieceList.push_back(tem);
}
else
{
// 1、从长边开始计算
for (int i = 1; i <= Edge_Piece_single_Num; i++)
{
int piece_len = std::ceil(long_side * 1.0f / i);
int piece_overlap_len = std::ceil(piece_len + (i - 1) / i * overlap);
int long_Piece_Num = i;
int short_Piece_Num = std::ceil(short_side * 1.0f / piece_overlap_len);
int sum_Piece_Num = long_Piece_Num * short_Piece_Num;
// printf("piece size %d %d long Num %d short Num %d sum %d \n", piece_len, piece_overlap_len, long_Piece_Num, short_Piece_Num, sum_Piece_Num);
if (sum_Piece_Num > Edge_Piece_Sum_Num)
{
continue;
}
AI_PIECE_INFO tem;
tem.len = piece_overlap_len;
tem.num = sum_Piece_Num;
tem.long_num = long_Piece_Num;
tem.short_num = short_Piece_Num;
tem.abs_L = std::abs(piece_overlap_len - Max_sizeWH);
pieceList.push_back(tem);
}
}
std::sort(pieceList.begin(), pieceList.end(), compare_Piece);
// for (int i = 0; i < pieceList.size(); i++)
// {
// pieceList.at(i).print(std::to_string(i));
// }
if (pieceList.size() <= 0)
{
printf("Select Roi fail\n");
return 1;
}
AI_PIECE_INFO selectPiece;
selectPiece.len = pieceList.at(0).len;
selectPiece.num = pieceList.at(0).num;
selectPiece.long_num = pieceList.at(0).long_num;
selectPiece.short_num = pieceList.at(0).short_num;
selectPiece.abs_L = pieceList.at(0).abs_L;
// selectPiece.print("select");
int W_Piece_Num = selectPiece.long_num;
int H_Piece_Num = selectPiece.short_num;
if (qx_w >= qx_h)
{
W_Piece_Num = selectPiece.long_num;
H_Piece_Num = selectPiece.short_num;
}
else
{
W_Piece_Num = selectPiece.short_num;
H_Piece_Num = selectPiece.long_num;
}
int Piece_len = selectPiece.len;
if (Piece_len < Min_SizeWH)
{
Piece_len = Min_SizeWH;
}
/////////////////、计算宽度方向 块的个数 和 重叠 ///////////////////////
// 块的个数
int nBlocknum_x = W_Piece_Num;
int use_MinOverlap_Width = 0;
// 计算重叠率
if (nBlocknum_x > 1)
{
// 有多个块,要判断 块的重叠是否满足要求
int nSumLen_x = nBlocknum_x * Piece_len; //
float fOverlap_x = (nSumLen_x - qx_w) * 1.0f / (nBlocknum_x - 1);
use_MinOverlap_Width = int(fOverlap_x);
}
/////////////////、计算高度方向 块的个数 和 重叠 ///////////////////////
// 块的个数
int nBlocknum_y = H_Piece_Num;
int use_MinOverlap_Height = 0;
// 计算重叠率
if (nBlocknum_y > 1)
{
// 有多个块,要判断 块的重叠是否满足要求
int nSumLen_y = nBlocknum_y * Piece_len; //
float fOverlap_y = (nSumLen_y - qx_h) * 1.0f / (nBlocknum_y - 1);
use_MinOverlap_Height = int(fOverlap_y);
}
int start_x = qx_roi.x;
int start_y = qx_roi.y;
int end_x = qx_roi.width + qx_roi.x;
int end_y = qx_roi.height + qx_roi.y;
// 有效图片 宽 高
int det_width = qx_roi.width;
int det_height = qx_roi.height;
int AI_Img_width = Piece_len;
int AI_Img_height = Piece_len;
if (nBlocknum_x == 1)
{
int sx = AI_Img_width - det_width;
int sub_x = 0;
if (sx > 0)
{
sub_x = sx / 2;
}
start_x -= sub_x;
if (start_x < 0)
{
start_x = 0;
}
}
int cut_sy = qx_roi.y;
int cut_ey = qx_roi.y + Piece_len;
if (nBlocknum_y == 1)
{
int sy = AI_Img_width - det_height;
int sub_y = 0;
if (sy > 0)
{
sub_y = sy / 2;
}
start_y -= sub_y;
if (start_y < 0)
{
start_y = 0;
}
}
cut_sy = start_y;
cut_ey = start_y + AI_Img_height;
if (cut_ey >= src_Img.rows)
{
cut_ey = src_Img.rows;
cut_sy = cut_ey - AI_Img_height;
}
for (int iy = 0; iy < nBlocknum_y; iy++)
{
int nleny = end_y - cut_ey;
int cut_sx = start_x;
int cut_ex = start_x + AI_Img_width;
if (cut_ex >= src_Img.cols)
{
cut_ex = src_Img.cols;
cut_sx = cut_ex - AI_Img_width;
}
for (int ix = 0; ix < nBlocknum_x; ix++)
{
cv::Rect roi;
roi.x = cut_sx;
roi.y = cut_sy;
roi.width = AI_Img_width;
roi.height = AI_Img_height;
samllRoiList.push_back(roi);
// 剩余长度
int nlenx = end_x - cut_ex;
if (nlenx > AI_Img_width)
{
cut_sx = cut_sx + AI_Img_width - use_MinOverlap_Width;
cut_ex = cut_sx + AI_Img_width;
}
else
{
cut_sx = end_x - AI_Img_width;
cut_ex = cut_sx + AI_Img_width;
}
}
if (nleny > AI_Img_height)
{
cut_sy = cut_sy + AI_Img_height - use_MinOverlap_Height;
cut_ey = cut_sy + AI_Img_height;
}
else
{
cut_sy = end_y - AI_Img_height;
cut_ey = cut_sy + AI_Img_height;
}
}
// 如果是偶数个,则需要再加个一个。
int sumblob = nBlocknum_y * nBlocknum_x;
if (sumblob % 2 == 0)
{
cv::Rect temRoi = GetCutRoi(qx_roi, src_Img, nwidth, nheight);
samllRoiList.push_back(temRoi);
}
if (false)
{
cv::Mat showimg = src_Img.clone();
if (showimg.channels() == 1)
{
cv::cvtColor(showimg, showimg, cv::COLOR_GRAY2BGR);
}
cv::rectangle(showimg, qx_roi, cv::Scalar(255, 255, 0), 5);
for (size_t i = 0; i < samllRoiList.size(); i++)
{
cv::rectangle(showimg, samllRoiList.at(i), cv::Scalar(255, 0, 0));
}
static int idx = 0;
cv::imwrite(std::to_string(idx++) + "tem_piece.png", showimg);
}
// getchar();
return 0;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,337 @@
#include "AI_Edge_QX_Det.h"
#include "CheckErrorCodeDefine.hpp"
AI_Edge_QX_Det::AI_Edge_QX_Det()
{
m_bInitSucc = false;
m_strSaveImgRootPath = "/home/aidlux/BOE/CELL_ET/Edge_QX/";
CheckUtil::CreateDir(m_strSaveImgRootPath);
m_strSaveImgRootPath_OK = m_strSaveImgRootPath + "ok/";
CheckUtil::CreateDir(m_strSaveImgRootPath_OK);
m_strSaveImgRootPath_Qx = m_strSaveImgRootPath + "qx/";
CheckUtil::CreateDir(m_strSaveImgRootPath_Qx);
m_pImageStorage = ImageStorage::getInstance();
m_nImge_num = 0;
m_strCamChannel = "";
AI_Factory = AIFactory::GetInstance();
}
AI_Edge_QX_Det::~AI_Edge_QX_Det()
{
}
int AI_Edge_QX_Det::SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, bool isALLzeros, DetConfig *pDetConfig, int idx, int nruntype)
{
// printf("nruntype %d %d %d\n", nruntype, pDetConfig->pdege_Det_config->bsave_all, pDetConfig->pdege_Det_config->bsave_qx);
// m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_QX_Det ", "nruntype %d %d %d\n", nruntype, pDetConfig->pdege_Det_config->bsave_all, pDetConfig->pdege_Det_config->bsave_qx);
// 正常模式
if (nruntype == 0)
{
if (pDetConfig->pdege_Det_config->bsave_all || pDetConfig->pdege_Det_config->bsave_qx)
{
// printf("==s1 \n");
}
else
{
// printf("==s2 \n");
return 0;
}
if (pDetConfig->pdege_Det_config->bsave_qx && isALLzeros)
{
// printf("==s3 \n");
return 0;
}
}
else
{
// 只存 有问题的。
if (nruntype == 1 && isALLzeros)
{
// printf("==s4 \n");
return 0;
}
}
// printf("==s5\n");
// 循环存储
int flage = 1; // 0:正常 1:OK 2:qx
if (isALLzeros)
{
flage = 1;
}
else
{
flage = 2;
}
std::string str_root;
str_root = GetImgSaveName(flage) + "_" + std::to_string(idx);
// printf("str_root = %s \n", str_root.c_str());
int re = 0;
if (!inImg.empty())
{
std::string strIn = str_root + "_in.png";
if (nruntype == 0)
{
re = m_pImageStorage->addImage(strIn, inImg);
}
else
{
cv::imwrite(strIn, inImg);
}
}
if (re == 0)
{
std::string strmask = str_root + "_in_mask.png";
if (nruntype == 0)
{
if (!outImg.empty())
{
m_pImageStorage->addImage(strmask, outImg, true); // 强制 存储
}
}
else
{
cv::imwrite(strmask, outImg);
}
}
return 0;
}
std::string AI_Edge_QX_Det::GetImgSaveName(int flag)
{
std::string str_root;
if (flag == 0)
{
str_root = m_strSaveImgRootPath;
}
else if (flag == 1)
{
str_root = m_strSaveImgRootPath_OK;
}
else
{
str_root = m_strSaveImgRootPath_Qx;
}
str_root += m_strCamChannel + "_" + std::to_string(m_nImge_num);
return str_root;
}
int AI_Edge_QX_Det::Detect(const cv::Mat &img, cv::Mat &detmask, DetConfig *pDetConfig, std::shared_ptr<DetLog> pdetlog)
{
static int n_count = 0;
int nRuntype = 0; // 0:检测 1:测试。。。。。
m_pdetlog = pdetlog;
if (pDetConfig->ninstruct == 767)
{
nRuntype = 1;
}
else if (pDetConfig->ninstruct == 768)
{
nRuntype = 2;
}
bool bdege = false;
// 二次求面积长度 功能关闭
if (!pDetConfig->pdege_Det_config->bOpen)
{
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_QX_Det ", "function colse");
return 1;
}
// if (!m_bInitialized || !m_bModelSucc)
// {
// m_pTemCheck->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_QX_Det ", "m_bModelSucc error");
// return 1;
// }
std::shared_ptr<AIModel_Base> m_pAIDeal = AI_Factory->AI_defect_Edge_QX;
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_QX_Det ", "AI start %s", pDetConfig->strCamChannel.c_str());
m_strCamChannel = pDetConfig->strCamChannel;
n_count++;
if (n_count > 1000)
{
m_nImge_num = 0;
}
m_nImge_num = n_count;
// printf("pDetConfig->ninstruct ========== %d channel %s imgname %d \n", pDetConfig->ninstruct, m_strCamChannel.c_str(), m_nImge_num);
cv::Mat showImg;
cv::Mat cut_show_R;
cv::Mat cut_show_G;
cv::Mat cut_show_B;
cv::Mat edge_mask;
std::vector<cv::Mat> cut_show_channels;
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_QX_Det ", "nruntype %d %d\n", pDetConfig->pdege_Det_config->bsave_all, pDetConfig->pdege_Det_config->bsave_qx);
if (bdege || nRuntype != 0)
{
showImg = img.clone();
cut_show_R = showImg(pDetConfig->CutRoi).clone();
cut_show_B = showImg(pDetConfig->CutRoi).clone();
cut_show_G = showImg(pDetConfig->CutRoi).clone();
cut_show_B += detmask * 0.2;
edge_mask = cv::Mat::zeros(detmask.size(), CV_8UC1);
}
for (int i = 0; i < pDetConfig->pEdgeDet_roiList->size(); i++)
{
cv::Rect r = pDetConfig->pEdgeDet_roiList->at(i);
cv::Mat outMask;
if (!CheckUtil::RoiInImg(r, img))
{
continue;
}
cv::Mat detimg = img(r).clone();
if (bdege || nRuntype != 0)
{
cv::rectangle(showImg, r, cv::Scalar(255, 0, 0));
}
int re = m_pAIDeal->AIDet(detimg, outMask);
if (re != 0)
{
continue;
}
if (outMask.empty())
{
continue;
}
bool isAllZero = true;
if (cv::countNonZero(outMask) > 0)
{
isAllZero = false;
if (bdege || nRuntype != 0)
{
outMask.copyTo(showImg(r), outMask);
}
}
SaveProcessImg(detimg, outMask, isAllZero, pDetConfig, i, nRuntype);
// if (!isAllZero)
// {
// cv::imwrite("edge_AI_outMask.png", outMask);
// cv::imwrite("edge_AI_pre_detmask(r).png", detmask(r));
// }
cv::Point p_smallImg_lt;
cv::Point p_smallImg_rb;
p_smallImg_lt.x = 0;
p_smallImg_lt.y = 0;
p_smallImg_rb.x = r.width;
p_smallImg_rb.y = r.height;
cv::Point p_mask_lt;
cv::Point p_mask_rb;
p_mask_lt.x = r.x - pDetConfig->CutRoi.x;
p_mask_lt.y = r.y - pDetConfig->CutRoi.y;
p_mask_rb.x = p_mask_lt.x + r.width;
p_mask_rb.y = p_mask_lt.y + r.height;
if (p_mask_lt.x < 0)
{
p_smallImg_lt.x = -p_mask_lt.x;
p_mask_lt.x = 0;
}
if (p_mask_lt.y < 0)
{
p_smallImg_lt.y = -p_mask_lt.y;
p_mask_lt.y = 0;
}
if (p_mask_rb.x > detmask.cols)
{
p_smallImg_rb.x -= (p_mask_rb.x - detmask.cols);
p_mask_rb.x = detmask.cols;
}
if (p_mask_rb.y > detmask.rows)
{
p_smallImg_rb.y -= (p_mask_rb.y - detmask.rows);
p_mask_rb.y = detmask.rows;
}
cv::Rect mask_roi;
mask_roi.x = p_mask_lt.x;
mask_roi.y = p_mask_lt.y;
mask_roi.width = p_mask_rb.x - p_mask_lt.x;
mask_roi.height = p_mask_rb.y - p_mask_lt.y;
cv::Rect smallImg_roi;
smallImg_roi.x = p_smallImg_lt.x;
smallImg_roi.y = p_smallImg_lt.y;
smallImg_roi.width = p_smallImg_rb.x - p_smallImg_lt.x;
smallImg_roi.height = p_smallImg_rb.y - p_smallImg_lt.y;
if (!CheckUtil::RoiInImg(smallImg_roi, outMask))
{
continue;
}
if (!CheckUtil::RoiInImg(mask_roi, detmask))
{
continue;
}
outMask *= 0.5;
if (nRuntype != 0)
{
outMask(smallImg_roi).copyTo(edge_mask(mask_roi), outMask(smallImg_roi));
cv::rectangle(cut_show_G, mask_roi, cv::Scalar(255, 0, 0));
}
else
{
if (pDetConfig->pdege_Det_config->type == Function_Edge_Det::Edge_type_Add)
{
outMask(smallImg_roi).copyTo(detmask(mask_roi), outMask(smallImg_roi));
}
else if (pDetConfig->pdege_Det_config->type == Function_Edge_Det::Edge_type_And)
{
cv::bitwise_and(detmask(mask_roi), outMask(smallImg_roi), detmask(mask_roi));
}
else
{
outMask(smallImg_roi).copyTo(detmask(mask_roi));
}
}
}
if (nRuntype != 0)
{
cut_show_R += edge_mask * 0.5;
std::vector<cv::Mat> chs = {cut_show_B, cut_show_G, cut_show_R};
cv::Mat merged;
cv::merge(chs, merged);
cv::resize(merged, merged, cv::Size(merged.cols * 0.5, merged.rows * 0.5));
std::string str = GetImgSaveName(0) + "_mask.png";
cv::imwrite(str, merged);
// std::cout<<str;
// getchar();
}
if (bdege)
{
cut_show_R += edge_mask * 0.5;
std::vector<cv::Mat> chs = {cut_show_B, cut_show_G, cut_show_R};
cv::Mat merged;
cv::merge(chs, merged);
cv::resize(merged, merged, cv::Size(merged.cols * 0.5, merged.rows * 0.5));
std::string str = GetImgSaveName(0) + "_mask.png";
cv::imwrite(str, merged);
str = GetImgSaveName(0) + "_showImg.png";
cv::imwrite(str, showImg);
}
return 0;
}

@ -0,0 +1,377 @@
#include "AI_Edge_Algin.h"
#include "CheckErrorCodeDefine.hpp"
#include "AI_Mark_Det.h"
AI_Mark_Det::AI_Mark_Det()
{
m_bModelSucc = false;
CheckUtil::CreateDir("/home/aidlux/BOE/CELL_ET/MarkLine/");
m_pImageStorage = ImageStorage::getInstance();
m_Show_Area = 0;
m_Show_Len = 0;
m_Len_P1 = cv::Point(0, 0);
m_Len_P2 = cv::Point(0, 0);
AI_Factory = AIFactory::GetInstance();
}
AI_Mark_Det::~AI_Mark_Det()
{
}
int AI_Mark_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
{
m_pdetlog = pDetConfig->pdetlog;
printf("AI_Mark_Det::Detect \n");
cv::Rect searchroi = pDetConfig->searchroi;
if (searchroi.x < 0)
{
searchroi.x = 0;
}
if (searchroi.y < 0)
{
searchroi.y = 0;
}
if (searchroi.x + searchroi.width > img.cols)
{
searchroi.width = img.cols - searchroi.x;
}
if (searchroi.y + searchroi.width > img.rows)
{
searchroi.height = img.rows - searchroi.y;
}
// 每个小矩形的大小
int rectWidth = 512;
int rectHeight = 512;
// 重叠区域大小
int overlap = 50;
// 计算步长
int stepX = rectWidth - overlap;
int stepY = rectHeight - overlap;
int x_start = searchroi.x;
int x_end = searchroi.x + searchroi.width;
int y_start = searchroi.y;
int y_end = searchroi.y + searchroi.height;
if (searchroi.width < 512)
{
int cx = searchroi.x + searchroi.width * 0.5;
x_start = cx - rectWidth * 0.5;
x_end = x_start + rectWidth;
}
if (searchroi.height < 512)
{
int cy = searchroi.y + searchroi.height * 0.5;
y_start = cy - rectHeight * 0.5;
y_end = y_start + rectHeight;
}
if (x_start < 0)
{
x_start = 0;
}
if (y_start < 0)
{
y_start = 0;
}
if (y_start + searchroi.height > img.rows)
{
y_start = img.rows - searchroi.height;
}
if (x_start + searchroi.width > img.cols)
{
x_start = img.cols - searchroi.width;
}
if (y_end > img.rows)
{
y_end = img.rows;
}
if (x_end > img.cols)
{
x_end = img.cols;
}
// cv::Mat showImg;
// if (true)
// {
// cv::cvtColor(detSrcImg, showImg, cv::COLOR_GRAY2BGR);
// }
int cut_y_s = y_start;
int cut_y_e = cut_y_s + rectHeight;
int cut_x_s = x_start;
int cut_x_e = cut_x_s + rectWidth;
bool bb_y = false;
bool bb_x = false;
int w = x_end - x_start;
int h = y_end - y_start;
if (w < 512)
{
if (x_start == 0)
{
x_end = x_start + 512;
if (x_end > img.cols)
{
return 1;
}
}
else
{
x_start = x_end - 512;
if (x_start < 0)
{
return 1;
}
}
}
if (h < 512)
{
if (y_start == 0)
{
y_end = y_start + 512;
if (y_end > img.rows)
{
return 1;
}
}
else
{
y_start = y_end - 512;
if (y_start < 0)
{
return 1;
}
}
}
w = x_end - x_start;
h = y_end - y_start;
if (w < rectWidth)
{
return 1;
}
if (h < rectHeight)
{
return 1;
}
cv::Rect allroi(x_start, y_start, w, h);
cv::Mat allmask = cv::Mat(h, w, CV_8UC1, cv::Scalar(0));
// printf("y_start %d y_end %d\n", y_start, y_end);
// printf("x_start %d x_end %d\n", x_start, x_end);
std::shared_ptr<AIModel_Base> pAI_Model = AI_Factory->AI_defect_MarkLine;
static int ki = 0;
//
for (int y = y_start; y < y_end; y += stepY)
{
cut_y_s = y;
cut_y_e = cut_y_s + rectHeight;
if (cut_y_e > y_end)
{
cut_y_e = y_end;
cut_y_s = y_end - rectHeight;
bb_y = true;
}
bb_x = false;
for (int x = x_start; x < x_end; x += stepX)
{
cut_x_s = x;
cut_x_e = cut_x_s + rectWidth;
if (cut_x_e > x_end)
{
cut_x_e = x_end;
cut_x_s = x_end - rectWidth;
bb_x = true;
}
// 定义小矩形
cv::Rect smallRect(cut_x_s, cut_y_s, rectWidth, rectHeight);
cv::Rect maskrect = smallRect;
maskrect.x -= x_start;
maskrect.y -= y_start;
if (!CheckUtil::RoiInImg(smallRect, img))
{
// printf("img %d %d= \n", img.cols, img.rows);
// CheckUtil::printROI(smallRect, "smallRect");
continue;
}
cv::Mat outmask;
cv::Mat temdet = img(smallRect).clone();
if (m_bModelSucc)
{
int re = pAI_Model->AIDet(temdet, outmask);
// m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "AI Model POL");
// 推理是否成功
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_2, "AI_Mark_Det ", "Error POL AI Model Error");
continue;
}
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_2, "AI_Mark_Det ", "Error POL AI Model Error");
continue;
}
if (outmask.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_2, "AI_Mark_Det ", "Error POL AI Error");
continue;
}
// printf("AI_Mark_Det::Detect ========3333============ \n");
// printf("img %d %d= \n", allmask.cols, allmask.rows);
// CheckUtil::printROI(maskrect, "maskrect---");
outmask.copyTo(allmask(maskrect), outmask);
if (pDetConfig->bDebugsaveimg || pDetConfig->bDetSaveImg)
{
std::string str12 = "/home/aidlux/BOE/CELL_ET/MarkLine/" + pDetConfig->strCamName + "_" + std::to_string(ki) + "_in.png";
std::string strmask = "/home/aidlux/BOE/CELL_ET/MarkLine/" + pDetConfig->strCamName + "_" + std::to_string(ki) + "_in_mask.png";
if (pDetConfig->bDebugsaveimg)
{
str12 = pDetConfig->strCamName + "_" + std::to_string(ki) + "_in.png";
strmask = pDetConfig->strCamName + "_" + std::to_string(ki) + "_in_mask.png";
}
ki++;
if (ki > 999999)
{
ki = 0;
}
cv::imwrite(str12, img(smallRect));
cv::imwrite(strmask, outmask);
}
if (bb_x)
{
break;
/* code */
}
}
if (bb_y)
{
break;
}
}
bool bf = false;
cv::Rect markroi = CheckUtil::getLargestContourROI(allmask, bf);
if (bf)
{
pDetConfig->nresult = 0;
pDetConfig->markRoi = markroi;
if (pDetConfig->bDebugsaveimg || pDetConfig->bDetSaveImg)
{
std::string str12 = "/home/aidlux/BOE/CELL_ET/MarkLine/Check_big_" + pDetConfig->strCamName + "_in.png";
std::string strmask = "/home/aidlux/BOE/CELL_ET/MarkLine/Check_big_" + pDetConfig->strCamName + "_in_mask.png";
if (pDetConfig->bDebugsaveimg)
{
str12 = "Check_big_" + pDetConfig->strCamName + "_" + std::to_string(ki) + "_in.png";
strmask = "Check_big_" + pDetConfig->strCamName + "_" + std::to_string(ki) + "_in_mask.png";
}
// CheckUtil::printROI(allroi, "allroi");
// printf("-------------------1111 33 img %d %d\n", img.cols, img.rows);
cv::Mat detimg = img(allroi).clone();
// printf("-------------------1111 33 \n");
cv::rectangle(detimg, pDetConfig->markRoi, cv::Scalar(180), 3);
// printf("-------------------1111 444\n");
cv::imwrite(str12, detimg);
cv::imwrite(strmask, allmask);
}
pDetConfig->markRoi.x += x_start;
pDetConfig->markRoi.y += y_start;
}
else
{
}
return 0;
}
int AI_Mark_Det::Det_img(const cv::Mat &img, DetConfigResult *pDetConfig)
{
return 0;
}
int AI_Mark_Det::Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig)
{
return 0;
}
int AI_Mark_Det::SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig)
{
// if (inImg.empty() || outImg.empty())
// {
// return 1;
// }
// static int saveimgIdx_pol = 0;
// static int saveimgIdx_ad = 0;
// // 循环存储
// std::string str_Root = "/home/aidlux/BOE/Second/";
// if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell)
// {
// saveimgIdx_pol++;
// if (saveimgIdx_pol > 1000)
// {
// saveimgIdx_pol = 0;
// }
// str_Root += "POL/POl_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_pol);
// }
// if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
// {
// saveimgIdx_ad++;
// if (saveimgIdx_ad > 1000)
// {
// saveimgIdx_ad = 0;
// }
// str_Root += "AD/AD_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_ad);
// }
// std::string strIn = str_Root + +"_in.png";
// int re = 0;
// if (!inImg.empty())
// {
// re = m_pImageStorage->addImage(strIn, inImg);
// }
// if (re == 0)
// {
// std::string strmask = str_Root + "_in_mask.png";
// if (!outImg.empty())
// {
// m_pImageStorage->addImage(strmask, outImg, true); // 强制 存储
// }
// std::string stroldmask = str_Root + "_old_mask.png";
// if (!oldmask.empty())
// {
// m_pImageStorage->addImage(stroldmask, oldmask, true); // 强制 存储
// }
// }
return 0;
}

@ -0,0 +1,564 @@
#include "AI_Edge_Algin.h"
#include "CheckErrorCodeDefine.hpp"
#include "AI_Second_Det.h"
AI_SecondDet::AI_SecondDet()
{
m_bModelSucc_AD = false;
m_bModelSucc_POL = false;
CheckUtil::CreateDir("/home/aidlux/BOE/CELL_ET/Second/POL/");
CheckUtil::CreateDir("/home/aidlux/BOE/CELL_ET/Second/AD/");
m_pImageStorage = ImageStorage::getInstance();
m_Show_Area = 0;
m_Show_Len = 0;
m_Len_P1 = cv::Point(0, 0);
m_Len_P2 = cv::Point(0, 0);
AI_Factory = AIFactory::GetInstance();
}
AI_SecondDet::~AI_SecondDet()
{
}
int AI_SecondDet::Detect(const cv::Mat &img, const cv::Mat &mask, DetConfigResult *pDetConfig)
{
m_pdetlog = pDetConfig->pdetlog;
// 二次求面积长度 功能关闭
if (!pDetConfig->pfunction_secondDet->bOpen)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "function colse");
return 1;
}
// cv::Mat temimg = mask.clone();
// cv::rectangle(temimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0));
cv::Rect AIroi = GetCutRoi(pDetConfig->qx_roi, img);
if (AIroi.width <= 0 || AIroi.height <= 0)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error Size");
return 1;
}
if (!CheckUtil::RoiInImg(AIroi, img))
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error ROI");
return 1;
}
float min_set_param_area = 0;
float max_set_param_area = 9999;
if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell)
{
min_set_param_area = pDetConfig->pfunction_secondDet->pol_area_min;
max_set_param_area = pDetConfig->pfunction_secondDet->pol_area_max;
}
if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
{
min_set_param_area = pDetConfig->pfunction_secondDet->andian_area_min;
max_set_param_area = pDetConfig->pfunction_secondDet->andian_area_max;
}
float oldarea_mm2 = pDetConfig->old_Area * pDetConfig->fImgage_Scale_X * pDetConfig->fImgage_Scale_Y;
if (oldarea_mm2 < min_set_param_area || oldarea_mm2 > max_set_param_area)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "error Area %0.2f out[%0.2f %0.2f] ", oldarea_mm2, min_set_param_area, max_set_param_area);
return 1;
}
if (oldarea_mm2 < pDetConfig->min_DetArea)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error Area %0.2f < det param %0.2f ", oldarea_mm2, pDetConfig->min_DetArea);
return 1;
}
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "succ Area %0.2f >= min det param %0.2f and in [%0.2f %0.2f] ", oldarea_mm2, pDetConfig->min_DetArea, min_set_param_area, max_set_param_area);
}
cv::Mat detimg = img(AIroi).clone();
cv::Mat outimg;
int re12 = 0;
//
if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell)
{
if (pDetConfig->pfunction_secondDet->pol_saveProcessImg)
{
printf("mask %d %d \n", mask.cols, mask.rows);
printf("AIroi %d %d %d %d\n", AIroi.x, AIroi.y, AIroi.width, AIroi.height);
detimg123 = mask(AIroi).clone();
printf("1111mask %d %d \n", mask.cols, mask.rows);
}
re12 = Det_Pol(detimg, pDetConfig);
}
if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
{
if (pDetConfig->pfunction_secondDet->andian_saveProcessImg)
{
// printf("mask %d %d \n", mask.cols, mask.rows);
// printf("AIroi %d %d %d %d\n", AIroi.x, AIroi.y, AIroi.width, AIroi.height);
detimg123 = mask(AIroi).clone();
// printf("2222mask %d %d \n", mask.cols, mask.rows);
}
re12 = Det_AD(detimg, pDetConfig);
}
if (re12 != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE_POL /AD", "Error ");
return 1;
}
return 0;
}
cv::Rect AI_SecondDet::GetCutRoi(cv::Rect &roi, const cv::Mat &img)
{
std::shared_ptr<AIModel_Base> pAI_Model = AI_Factory->AI_defect_RE_POL;
cv::Size sz;
sz.width = pAI_Model->input_0.width;
sz.height = pAI_Model->input_0.height;
int Dst_Width = sz.width;
int Dst_Height = sz.height;
cv::Rect cutroi = cv::Rect(0, 0, 0, 0);
if (Dst_Width >= img.cols || Dst_Height >= img.rows)
{
return cutroi;
}
if (roi.width >= Dst_Width || roi.height >= Dst_Height)
{
return cutroi;
}
int centerX = roi.x + roi.width / 2;
int centerY = roi.y + roi.height / 2;
// 构造一个以中心为中心的 128x128 矩形
int halfSize = Dst_Width / 2; // 128 / 2
int newX = centerX - halfSize;
int newY = centerY - halfSize;
int newWidth = Dst_Width;
int newHeight = Dst_Height;
// 检查矩形是否越界
if (newX < 0)
{
newX = 0;
}
if (newY < 0)
{
newY = 0;
}
if (newX + newWidth > img.cols)
{
newX = img.cols - newWidth;
}
if (newY + newHeight > img.rows)
{
newY = img.rows - newHeight;
}
// 创建新的矩形
cv::Rect newRect(newX, newY, newWidth, newHeight);
int add = 3;
// 重新计算 roi 在新的矩形中的位置
int newRoiX = roi.x - newRect.x - add;
int newRoiY = roi.y - newRect.y - add;
int newRoiWidth = roi.width + 2 * add;
int newRoiHeight = roi.height + 2 * add;
// 确保新的 roi 在新的矩形内
if (newRoiX < 0)
{
newRoiX = 0;
}
if (newRoiY < 0)
{
newRoiY = 0;
}
if (newRoiX + newRoiWidth > newRect.width)
{
newRoiWidth = newRect.width - newRoiX;
}
if (newRoiY + newRoiHeight > newRect.height)
{
newRoiHeight = newRect.height - newRoiY;
}
// 更新 roi
roi = cv::Rect(newRoiX, newRoiY, newRoiWidth, newRoiHeight);
// 返回新的矩形
return newRect;
}
int AI_SecondDet::Det_Pol(const cv::Mat &img, DetConfigResult *pDetConfig)
{
std::shared_ptr<AIModel_Base> pAI_Model = AI_Factory->AI_defect_RE_POL;
int re = 0;
cv::Mat outimg;
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " POL start");
re = pAI_Model->AIDet(img, outimg);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error POL AI Model Error");
return 1;
}
if (outimg.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error POL AI Error");
return 1;
}
cv::Mat AnalysisyImg = outimg(pDetConfig->qx_roi).clone();
m_Show_Area = pDetConfig->old_Area;
m_Show_Len = pDetConfig->old_len;
// 开始分析mask;
re = Analysisy(AnalysisyImg, pDetConfig);
m_Len_P1.x += pDetConfig->qx_roi.x;
m_Len_P1.y += pDetConfig->qx_roi.y;
m_Len_P2.x += pDetConfig->qx_roi.x;
m_Len_P2.y += pDetConfig->qx_roi.y;
// 存储中间过程图片
if (pDetConfig->pfunction_secondDet->pol_saveProcessImg)
{
if (true)
{
cv::rectangle(outimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0));
cv::rectangle(detimg123, pDetConfig->qx_roi, cv::Scalar(128, 0, 0));
cv::line(outimg, m_Len_P1, m_Len_P2, cv::Scalar(128, 0, 0));
{
char buffer[128];
sprintf(buffer, " oA %d -> nA %d ",
pDetConfig->old_Area, m_Show_Area);
std::string st1 = buffer;
cv::Point p(0, 10);
cv::putText(outimg, st1, p, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0);
sprintf(buffer, " oL %0.2f -> nL %0.2f ",
pDetConfig->old_len, m_Show_Len);
st1 = buffer;
cv::Point p2(0, 20);
cv::putText(outimg, st1, p2, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0);
}
}
SaveProcessImg(img, outimg, detimg123, pDetConfig);
}
return re;
}
int AI_SecondDet::Det_AD(const cv::Mat &img, DetConfigResult *pDetConfig)
{
std::shared_ptr<AIModel_Base> pAI_Model = AI_Factory->AI_defect_RE_AD;
int re = 0;
cv::Mat outimg;
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " AD start");
re = pAI_Model->AIDet(img, outimg);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error AD AI Model Error");
return 1;
}
if (outimg.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error AD AI Error");
return 1;
}
if (!CheckUtil::RoiInImg(pDetConfig->qx_roi, outimg))
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "qx roi Error");
return 1;
}
cv::Mat AnalysisyImg = outimg(pDetConfig->qx_roi).clone();
m_Show_Area = pDetConfig->old_Area;
m_Show_Len = pDetConfig->old_len;
// 开始分析mask;
re = Analysisy(AnalysisyImg, pDetConfig);
m_Len_P1.x += pDetConfig->qx_roi.x;
m_Len_P1.y += pDetConfig->qx_roi.y;
m_Len_P2.x += pDetConfig->qx_roi.x;
m_Len_P2.y += pDetConfig->qx_roi.y;
if (pDetConfig->pfunction_secondDet->andian_saveProcessImg)
{
if (true)
{
cv::rectangle(outimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0));
cv::rectangle(detimg123, pDetConfig->qx_roi, cv::Scalar(128, 0, 0));
cv::line(outimg, m_Len_P1, m_Len_P2, cv::Scalar(128, 0, 0));
{
char buffer[128];
sprintf(buffer, " oA %d -> nA %d ",
pDetConfig->old_Area, m_Show_Area);
std::string st1 = buffer;
cv::Point p(0, 10);
cv::putText(outimg, st1, p, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0);
sprintf(buffer, " oL %0.2f -> nL %0.2f ",
pDetConfig->old_len, m_Show_Len);
st1 = buffer;
cv::Point p2(0, 20);
cv::putText(outimg, st1, p2, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0);
}
}
SaveProcessImg(img, outimg, detimg123, pDetConfig);
}
return re;
}
int AI_SecondDet::Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig)
{
// 存储轮廓
std::vector<std::vector<cv::Point>> contours;
// 存储每个轮廓的层级
std::vector<cv::Vec4i> hierarchy;
// 寻找轮廓
cv::findContours(maskImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
double maxArea = 0;
int maxIndex = -1;
// 遍历每个轮廓,计算面积并找出最大的面积
for (size_t i = 0; i < contours.size(); i++)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxIndex = i;
}
}
if (maxIndex < 0)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "second mask is error");
return 1;
/* code */
}
bool barea = false;
bool blen = false;
int oldArea = pDetConfig->old_Area;
float oldLen = pDetConfig->old_len;
if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell)
{
barea = pDetConfig->pfunction_secondDet->pol_Open_area;
blen = pDetConfig->pfunction_secondDet->pol_Open_len;
}
if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
{
barea = pDetConfig->pfunction_secondDet->andian_Open_area;
blen = pDetConfig->pfunction_secondDet->andian_Open_len;
}
// 计算面积
// if (barea)
{
int maxContourPixelCount = 0;
if (maxIndex >= 0)
{
cv::Mat mask = cv::Mat::zeros(maskImg.size(), CV_8UC1);
cv::drawContours(mask, contours, maxIndex, cv::Scalar(255), cv::FILLED); // 绘制轮廓填充区域
maxContourPixelCount = cv::countNonZero(mask); // 计算填充区域的像素个数
}
m_Show_Area = maxContourPixelCount;
if (barea)
{
if (maxContourPixelCount > 0 && maxContourPixelCount < oldArea)
{
pDetConfig->new_Area = maxContourPixelCount;
}
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Use New Area :old area %d (pixel) new %d", oldArea, pDetConfig->new_Area);
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " Not Use Area :old area %d (pixel) new %d", oldArea, maxContourPixelCount);
}
}
// else
// {
// m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Cal Area is Close");
// }
// 计算长度
// if (blen)
{
cv::RotatedRect rect = cv::minAreaRect(contours[maxIndex]);
// 获取最小外接矩形的尺寸
float width = rect.size.width;
float height = rect.size.height;
Point2f vertices[4];
rect.points(vertices);
if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
{
float len1 = sqrt((vertices[0].x - vertices[1].x) * (vertices[0].x - vertices[1].x) +
(vertices[0].y - vertices[1].y) * (vertices[0].y - vertices[1].y));
float len2 = sqrt((vertices[2].x - vertices[1].x) * (vertices[2].x - vertices[1].x) +
(vertices[2].y - vertices[1].y) * (vertices[2].y - vertices[1].y));
if (len1 > len2)
{
m_Len_P1.x = vertices[0].x;
m_Len_P1.y = vertices[0].y;
m_Len_P2.x = vertices[1].x;
m_Len_P2.y = vertices[1].y;
}
else
{
m_Len_P1.x = vertices[2].x;
m_Len_P1.y = vertices[2].y;
m_Len_P2.x = vertices[1].x;
m_Len_P2.y = vertices[1].y;
}
}
else
{
m_Len_P1.x = vertices[2].x;
m_Len_P1.y = vertices[2].y;
m_Len_P2.x = vertices[0].x;
m_Len_P2.y = vertices[0].y;
}
vector<Point2f> newcont;
for (int i = 0; i < 4; ++i)
{
Point2f p;
p.x = vertices[i].x * pDetConfig->fImgage_Scale_X;
p.y = vertices[i].y * pDetConfig->fImgage_Scale_Y;
newcont.push_back(p);
}
vector<vector<Point2f>> contours_New;
contours_New.push_back(newcont);
// Recreate the rotated rectangle with scaled vertices
RotatedRect scaledRect = minAreaRect(contours_New[0]);
// Calculate scaled width and height
width = scaledRect.size.width;
height = scaledRect.size.height;
float new_len = width;
if (width > 0 && height > 0)
{
if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
{
if (width > height)
{
new_len = width;
}
else
{
new_len = height;
}
}
else
{
new_len = sqrt(width * width + height * height);
}
}
else
{
if (width > height)
{
new_len = width;
}
else
{
new_len = height;
}
}
// printf("oldLen %f new_len %f \n", oldLen, new_len);
m_Show_Len = new_len;
if (blen)
{
if (new_len > 0 && new_len < oldLen)
{
pDetConfig->new_len = new_len;
}
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", "Use New Len :old Len %f (mm) new %f", oldLen, pDetConfig->new_len);
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", " Not Use Len :old Len %f (mm) new %f", oldLen, new_len);
}
}
// else
// {
// m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", "Cal Len is Close");
// }
return 0;
}
int AI_SecondDet::SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig)
{
if (inImg.empty() || outImg.empty())
{
return 1;
}
static int saveimgIdx_pol = 0;
static int saveimgIdx_ad = 0;
// 循环存储
std::string str_Root = "/home/aidlux/BOE/CELL_ET/Second/";
if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell)
{
saveimgIdx_pol++;
if (saveimgIdx_pol > 1000)
{
saveimgIdx_pol = 0;
}
str_Root += "POL/POl_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_pol);
}
if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
{
saveimgIdx_ad++;
if (saveimgIdx_ad > 1000)
{
saveimgIdx_ad = 0;
}
str_Root += "AD/AD_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_ad);
}
std::string strIn = str_Root + +"_in.png";
int re = 0;
if (!inImg.empty())
{
re = m_pImageStorage->addImage(strIn, inImg);
}
if (re == 0)
{
std::string strmask = str_Root + "_in_mask.png";
if (!outImg.empty())
{
m_pImageStorage->addImage(strmask, outImg, true); // 强制 存储
}
std::string stroldmask = str_Root + "_old_mask.png";
if (!oldmask.empty())
{
m_pImageStorage->addImage(stroldmask, oldmask, true); // 强制 存储
}
}
return 0;
}

@ -0,0 +1,157 @@
#include "AI_ZF_Det.h"
#include "CheckErrorCodeDefine.hpp"
static bool compareContourAreas123(const vector<Point> &contour1, const vector<Point> &contour2)
{
double i = contourArea(contour1);
double j = contourArea(contour2);
return (i > j);
}
AI_ZF_Det::AI_ZF_Det()
{
m_bModelSucc = false;
CheckUtil::CreateDir("/home/aidlux/BOE/CELL_ET/zf/");
m_pImageStorage = ImageStorage::getInstance();
m_Show_Area = 0;
m_Show_Len = 0;
m_Len_P1 = cv::Point(0, 0);
m_Len_P2 = cv::Point(0, 0);
AI_Factory = AIFactory::GetInstance();
}
AI_ZF_Det::~AI_ZF_Det()
{
}
int AI_ZF_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
{
std::shared_ptr<AIModel_Base> pAI_Model = AI_Factory->AI_defect_zf;
m_pdetlog = pDetConfig->pdetlog;
cv::Size sz;
sz.width = pAI_Model->input_0.width;
sz.height = pAI_Model->input_0.height;
cv::Mat inImg;
cv::Mat AIoutimg;
cv::resize(img, inImg, sz, 0, 0, cv::INTER_AREA);
pAI_Model->AIDet(inImg, AIoutimg);
if (pDetConfig->bDebugsaveimg)
{
if (!inImg.empty())
{
cv::imwrite("ZF_img_In.png", inImg);
}
if (!AIoutimg.empty())
{
cv::imwrite("ZF_img_out.png", AIoutimg);
}
}
{
float fx = img.cols * 1.0f / AIoutimg.cols;
float fy = img.rows * 1.0f / AIoutimg.rows;
// 轮廓检测
std::vector<std::vector<cv::Point>> contours;
findContours(AIoutimg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 根据面积大小对轮廓进行排序
sort(contours.begin(), contours.end(), compareContourAreas123);
int kd = 0;
for (size_t i = 0; i < contours.size(); ++i)
{
// 获取当前轮廓的边界矩形
cv::Rect boundingRect = cv::boundingRect(contours[i]);
cv::Rect roi;
roi.x = boundingRect.x * fx;
roi.y = boundingRect.y * fy;
roi.width = boundingRect.width * fx;
roi.height = boundingRect.height * fy;
pDetConfig->pZF_Result->pZF_roiList.push_back(roi);
kd++;
if (kd >= 2)
{
break;
}
}
}
return 0;
}
int AI_ZF_Det::Det_img(const cv::Mat &img, DetConfigResult *pDetConfig)
{
return 0;
}
int AI_ZF_Det::Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig)
{
return 0;
}
int AI_ZF_Det::SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig)
{
// if (inImg.empty() || outImg.empty())
// {
// return 1;
// }
// static int saveimgIdx_pol = 0;
// static int saveimgIdx_ad = 0;
// // 循环存储
// std::string str_Root = "/home/aidlux/BOE/Second/";
// if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell)
// {
// saveimgIdx_pol++;
// if (saveimgIdx_pol > 1000)
// {
// saveimgIdx_pol = 0;
// }
// str_Root += "POL/POl_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_pol);
// }
// if (pDetConfig->qx_type == CONFIG_QX_NAME_AD)
// {
// saveimgIdx_ad++;
// if (saveimgIdx_ad > 1000)
// {
// saveimgIdx_ad = 0;
// }
// str_Root += "AD/AD_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_ad);
// }
// std::string strIn = str_Root + +"_in.png";
// int re = 0;
// if (!inImg.empty())
// {
// re = m_pImageStorage->addImage(strIn, inImg);
// }
// if (re == 0)
// {
// std::string strmask = str_Root + "_in_mask.png";
// if (!outImg.empty())
// {
// m_pImageStorage->addImage(strmask, outImg, true); // 强制 存储
// }
// std::string stroldmask = str_Root + "_old_mask.png";
// if (!oldmask.empty())
// {
// m_pImageStorage->addImage(stroldmask, oldmask, true); // 强制 存储
// }
// }
return 0;
}

@ -0,0 +1,740 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-24 11:03:35
* @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 "ALLImgCheckAnalysisy.hpp"
#include "CheckUtil.hpp"
#include "Define.h"
#include "AI_Factory.h"
double calculateDistanceBetweenRectCenters(const cv::Rect &rect1, const cv::Rect &rect2, float fx, float fy)
{
// 计算矩形1的中心点
cv::Point center1(rect1.x + rect1.width / 2, rect1.y + rect1.height / 2);
// 计算矩形2的中心点
cv::Point center2(rect2.x + rect2.width / 2, rect2.y + rect2.height / 2);
center1.x *= fx;
center1.y *= fy;
center2.x *= fx;
center2.y *= fy;
// 计算中心点之间的欧几里得距离
double distance = cv::norm(center1 - center2);
return distance;
}
ALLImgCheckAnalysisy::ALLImgCheckAnalysisy()
{
m_strTest = "";
}
ALLImgCheckAnalysisy::~ALLImgCheckAnalysisy()
{
StopThread();
}
int ALLImgCheckAnalysisy::RunStart(void *pconfig1)
{
// 1、参数版本核对
int re = CheckConfigVersion(pconfig1);
if (re != 0)
{
printf("*************CheckConfigVersion error %d*************** \n", re);
m_nErrorCode = INIT_CameraCheck_Error;
return m_nErrorCode;
}
m_pParamName = ParmNameChange::getInstance();
m_pParamName->m_nWorkIdx = m_RunConfig.nWorkIdx;
// 2、初始化相机类
re = InitCameraCheckAnalysisy();
if (re != 0)
{
printf("*************InitCameraCheckAnalysisy error %d*************** \n", re);
m_nErrorCode = INIT_CameraCheck_Error;
return m_nErrorCode;
}
re = InitRun();
if (CHECK_OK != re)
{
m_nErrorCode = re;
return m_nErrorCode;
}
re = InitAIFactory();
if (CHECK_OK != re)
{
m_nErrorCode = re;
return m_nErrorCode;
}
m_nErrorCode = CHECK_OK;
printf(">>>> ALLImgCheckAnalysisy Start Succ \n");
m_nErrorCode = CHECK_OK;
m_bInitSucc = true;
return m_nErrorCode;
}
int ALLImgCheckAnalysisy::SetDataRun_SharePtr(std::shared_ptr<shareImage> p)
{
int re = PushInImg_New(p);
if (re != 0)
{
printf("SetDataRun_SharePtr======================= re %d \n", re);
}
return re;
}
int ALLImgCheckAnalysisy::GetCheckReuslt(std::shared_ptr<CheckResult> &pResult)
{
std::unique_lock<std::mutex> lk(mtx_CheckResult); // 使用 unique_lock
CheckResult_cond.wait(lk, [this]
{ return !m_CheckResultList.empty(); }); // 等待直到数据队列非空
pResult = m_CheckResultList.front(); // 从队列中取出数
m_CheckResultList.pop();
lk.unlock();
return 0;
}
int ALLImgCheckAnalysisy::ReJson(std::shared_ptr<shareImage> p, std::shared_ptr<CheckResult> &pResult)
{
return 0;
}
int ALLImgCheckAnalysisy::CheckImg(std::shared_ptr<shareImage> p, std::shared_ptr<CheckResult> &pResult)
{
return 0;
}
int ALLImgCheckAnalysisy::GetStatus()
{
return 0;
}
int ALLImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType)
{
int re = 0;
RunInfoST *tempconfig;
switch (nConfigType)
{
case CHECK_CONFIG_Run:
tempconfig = (RunInfoST *)pconfig;
m_RunConfig.copy(*tempconfig);
break;
case CHECK_CONFIG_Module:
m_pConfigManager = (ConfigManagerBase *)pconfig;
break;
default:
break;
}
return 0;
}
std::string ALLImgCheckAnalysisy::GetVersion()
{
return std::string("BOE_2.0.5");
}
std::string ALLImgCheckAnalysisy::GetErrorInfo()
{
std::string result = "";
return result;
}
int ALLImgCheckAnalysisy::ErrorReturn(std::shared_ptr<shareImage> p)
{
std::shared_ptr<CheckResult> result = std::make_shared<CheckResult>();
result->in_shareImage = p;
result->checkStatus = 1;
result->nresult = -CHECK_ERROR_PushImg_ID_Error;
result->basicResult.img_id = p->img_id;
result->basicResult.imgtype = p->imgtype;
result->basicResult.imgstr = p->imgstr;
result->basicResult.strChannel = p->strChannel;
// printf("ErrorReturn==== %s %s\n", p->strImgProductID.c_str(), p->strChannel.c_str());
{
std::lock_guard<std::mutex> lock(mtx_CheckResult);
m_CheckResultList.push(result);
}
CheckResult_cond.notify_all();
return 0;
}
std::shared_ptr<Product> ALLImgCheckAnalysisy::GetProduct(std::string strProduct)
{
std::lock_guard<std::mutex> lock(mtx_ProductList);
for (int i = 0; i < m_ProductList.size(); i++)
{
// printf("ddd %s \n", m_ProductList.at(i)->productBaseResult->strproductName.c_str());
if (m_ProductList.at(i)->productBaseResult->strproductName == strProduct)
{
return m_ProductList.at(i);
}
}
return std::shared_ptr<Product>();
}
int ALLImgCheckAnalysisy::InitAIFactory()
{
std::shared_ptr<AIFactory> AI_Factory;
AI_Factory = AIFactory::GetInstance();
GPU_Config gpu;
int num = 0;
for (int i = 0; i < MAX_GPU_NUM; i++)
{
gpu.UseGPUList[i] = m_RunConfig.UseGPUList[i];
if (gpu.UseGPUList[i] >= 0)
{
num++;
}
}
if (num == 0)
{
gpu.UseGPUList[0] = 0;
gpu.UseGPUList[1] = 1;
}
for (int i = 0; i < MAX_GPU_NUM; i++)
{
printf("=====InitAIFactory gpu %d %d \n", i, gpu.UseGPUList[i]);
}
AI_Factory->InitALLAIModle(gpu);
return 0;
}
int ALLImgCheckAnalysisy::LoadRunConfig(void *p)
{
return 0;
}
int ALLImgCheckAnalysisy::LoadCheckConfig(void *p)
{
return 0;
}
int ALLImgCheckAnalysisy::InitRun()
{
int re;
re = StartThread();
if (CHECK_OK != re)
{
return re;
}
return 0;
}
int ALLImgCheckAnalysisy::StartCheck()
{
return 0;
}
int ALLImgCheckAnalysisy::SetIDLE()
{
return 0;
}
int ALLImgCheckAnalysisy::CheckConfigVersion(void *pconfig1)
{
int re = 0;
VERSION_INFO *pVersionconfig = (VERSION_INFO *)pconfig1;
if (pVersionconfig == NULL)
{
m_nErrorCode = CHECK_ERROR_VERSION; // 参数或接口版本问题
return m_nErrorCode;
}
int v1 = ALL_INTERFACE_VERSION;
int v2 = CONFIGBASE_VERSION;
int v3 = RESULT_VERSION;
printf("**************************** ALL_INTERFACE_VERSION so: %d in:%d CONFIGBASE_VERSION so:%d in:%d RESULT_VERSION so:%d in:%d\n",
v1, pVersionconfig->InterfaceVersion, v2, pVersionconfig->ConfigVersion, v3, pVersionconfig->ResultVersion);
// 版本控制
if (pVersionconfig->InterfaceVersion != ALL_INTERFACE_VERSION ||
pVersionconfig->ConfigVersion != CONFIGBASE_VERSION ||
pVersionconfig->ResultVersion != RESULT_VERSION)
{
m_nErrorCode = CHECK_ERROR_VERSION; // 参数或接口版本问题
return m_nErrorCode;
}
return 0;
}
int ALLImgCheckAnalysisy::StartThread()
{
m_bExit = false;
{ // 开启检测线程
ptr_thread_Run = std::make_shared<std::thread>(std::bind(&ALLImgCheckAnalysisy::Run, this));
}
return 0;
}
int ALLImgCheckAnalysisy::StopThread()
{
m_bExit = true;
if (ptr_thread_Run != nullptr)
{
if (ptr_thread_Run->joinable())
{
ptr_thread_Run->join();
}
}
return 0;
}
int ALLImgCheckAnalysisy::ExitSystem()
{
return 0;
}
int ALLImgCheckAnalysisy::InitCameraCheckAnalysisy()
{
m_pCameraCheckAnalysisyList.clear();
// m_pQX_Merge_Analysis->Clear();
for (const auto &config : m_pConfigManager->Config_instances_)
{
std::cout << "key: " << config.first << std::endl;
std::shared_ptr<CameraCheckAnalysisy> p = std::make_shared<CameraCheckAnalysisy>();
p->m_RunConfig.copy(m_RunConfig);
p->m_pConfig = config.second;
int re = p->Init(config.first);
if (re != 0)
{
std::cout << "Init CameraCheckAnalysisy " << config.first << " Failed" << std::endl;
return -1;
}
m_pCameraCheckAnalysisyList[config.first] = p;
// m_pQX_Merge_Analysis->AddCamer(config.first);
}
if (m_pCameraCheckAnalysisyList.size() < 0)
{
printf("ALLImgCheckAnalysisy::InitCameraCheckAnalysisy error camera config is null \n");
return 1;
/* code */
}
printf("ALLImgCheckAnalysisy::InitCameraCheckAnalysisy end \n");
// getchar();
return 0;
}
int ALLImgCheckAnalysisy::InitData()
{
return 0;
}
int ALLImgCheckAnalysisy::Det_Product(std::shared_ptr<Product> &product)
{
// m_pQX_Merge_Analysis->InitData();
// 处理每个相机
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
{
std::lock_guard<std::mutex> lock(product->mtx_CameraResultList); //
for (auto &ptr : product->m_pCameraResultList)
{
if (ptr->GetCheckStep() == Check_Step_NODet)
{
m_pCameraCheckAnalysisyList[ptr->cameraBaseResult->strCameraName]->StartCheck(ptr);
}
}
}
// 判断每个相机是否都处理完了。
bool bdetComplete = product->bCheckCamplate();
// 处理完成,退出循环
if (bdetComplete)
{
break;
}
}
// 联合分析
// AnalysiyAll(0);
MergeShowImg(product);
SetProductResult(product);
printf(">>>>>>>>>>>>>>>Det_Product****************det End************\n");
return 0;
}
std::shared_ptr<Product> ALLImgCheckAnalysisy::GetProduct()
{
std::unique_lock<std::mutex> lk(mtx_ProductList); // 使用 unique_lock
ProductList_cond.wait(lk, [this]
{ return !m_ProductList.empty(); }); // 等待直到数据队列非空
std::shared_ptr<Product> tem = m_ProductList.at(0);
lk.unlock();
return tem;
}
int ALLImgCheckAnalysisy::AnalysiyAll(int productIdx)
{
return 0;
}
int ALLImgCheckAnalysisy::SetProductResult(std::shared_ptr<Product> product)
{
int nDetCamNum = product->m_pCameraResultList.size();
// 相机2的起始位置
bool bNG = false;
for (int icam = 0; icam < nDetCamNum; icam++)
{
std::shared_ptr<CameraResult> pcam = product->m_pCameraResultList.at(icam);
for (int i = 0; i < pcam->ImageALLDetResultList.size(); i++)
{
std::shared_ptr<CheckResult> pCheckResult = pcam->ImageALLDetResultList.at(i)->result;
if (pCheckResult->qxImageResult.size() > 0)
{
bNG = true;
}
if (bNG)
{
break;
}
}
if (bNG)
{
break;
}
}
if (bNG)
{
for (int icam = 0; icam < nDetCamNum; icam++)
{
std::shared_ptr<CameraResult> pcam = product->m_pCameraResultList.at(icam);
for (int i = 0; i < pcam->ImageALLDetResultList.size(); i++)
{
std::shared_ptr<CheckResult> pCheckResult = pcam->ImageALLDetResultList.at(i)->result;
pCheckResult->nProductResult = 1;
}
}
}
return 0;
}
int ALLImgCheckAnalysisy::SetSetComplet_New(std::shared_ptr<Product> product, int nerror)
{
if (product)
{
int nDetCamNum = product->m_pCameraResultList.size();
for (int icam = 0; icam < nDetCamNum; icam++)
{
std::shared_ptr<CameraResult> pcam = product->m_pCameraResultList.at(icam);
for (int i = 0; i < pcam->ImageALLDetResultList.size(); i++)
{
std::shared_ptr<CheckResult> pCheckResult = pcam->ImageALLDetResultList.at(i)->result;
{
std::lock_guard<std::mutex> lock123(mtx_CheckResult);
m_CheckResultList.push(pCheckResult);
}
CheckResult_cond.notify_all();
}
}
}
return 0;
}
int ALLImgCheckAnalysisy::PushInImg_New(std::shared_ptr<shareImage> p)
{
if (!m_bInitSucc)
{
printf("Init fail exit \n");
return CHECK_ERROR_Config_Null;
}
p->strParm_WorkCamName = m_pParamName->GetWebConfigCamName_DetImgCamName(p->strCameraName);
std::string strlog = "";
m_strTest += " PushInImg->SN:";
m_strTest += p->strImgProductID;
m_strTest += " Channel:";
m_strTest += p->strChannel;
m_strTest += " CameraID:";
m_strTest += p->strCameraName;
m_strTest += " WorkCamName:";
m_strTest += p->strParm_WorkCamName;
std::string strBase = "";
strBase += " PushInImg->SN:";
strBase += p->strImgProductID;
strBase += " camera:";
strBase += p->strCameraName;
strBase += " WorkCamName:";
strBase += p->strParm_WorkCamName;
strBase += " Channel:";
strBase += p->strChannel;
printf("strBase %s p->Status %d\n", strBase.c_str(), p->Status);
std::shared_ptr<Product> product;
{
std::string strcameraName = p->strParm_WorkCamName;
// 判断 相机名称是否存在
if (!m_pCameraCheckAnalysisyList.count(strcameraName) && -1 != p->Status)
{
return CHECK_ERROR_Camear_ID_Error;
}
product = GetProduct(p->strImgProductID);
bool ProductID_Exist = false; // 是否存在当前产品ID
strlog += "productID ";
if (product)
{
strlog += "exist";
ProductID_Exist = true;
}
// 产品ID存在
if(ProductID_Exist)
{
// 模式为第一张图,返回异常
if(IN_IMG_Status_Start == p->Status)
{
cout << "---ProductID_Exist && IN_IMG_Status_Start == p->Status---" << endl;
return CHECK_ERROR_PRODUCT_ID_EXIST;
}
// 图片都已经完了的状态
if(product->bIsImgComplete)
{
cout << "---ProductID_Exist && product->bIsImgComplete is true---" << endl;
ErrorReturn(p);
return CHECK_ERROR_PRODUCT_ID_EXIST;
}
}
// 产品ID不存在
else
{
strlog += "isnot exist";
//设置其他m_ProductList送图状态设置为结束
cout << "-------set m_ProductList other product to end-------" << endl ;
for(auto &tem:m_ProductList){
tem->bIsImgComplete = true;
}
}
// 产品不存在 新建一个
if (!product)
{
std::lock_guard<std::mutex> lock(mtx_ProductList);
{
if (m_ProductList.size() > 50)
{
return CHECK_ERROR_PushImg_ListSize;
}
}
strlog += " | create new product";
product = std::make_shared<Product>();
product->productBaseResult->strproductName = p->strImgProductID;
m_ProductList.push_back(product);
std::string strTimg = CheckUtil::getCurTimeHMS();
product->productBaseResult->detlog->bPrintStr = true;
product->productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "add new product %s %s ", p->strImgProductID.c_str(), strTimg.c_str());
}
else
{
strlog += " | product: ";
strlog += product->productBaseResult->strproductName;
// printf("Product Is %s \n", product->productBaseResult->strproductName.c_str());
}
// 送入图的状态 结束
if(-1 == p->Status)
{
strlog += " | p->Status == -1, set product complete";
product->bIsImgComplete = true;
}
// 送入图的状态 不是结束
else
{
strlog += " | create new camera result";
// 对应相机的 检测结果
std::shared_ptr<CameraResult> pCamera = product->GetCameraResult(strcameraName);
if (pCamera.get() == nullptr)
{
strlog += " | CHECK_ERROR_Camear_ID_Error";
product->productBaseResult->detlog->bPrintStr = true;
product->productBaseResult->detlog->AddCheckstr(PrintLevel_1, "PushInImg end", "%s", strlog.c_str());
ErrorReturn(p);
return CHECK_ERROR_Camear_ID_Error;
}
// 添加产品信息
pCamera->AddDetImage(p);
}
product->UpdatePushStatus(p->Status);
if (IN_IMG_Status_End == p->Status)
{
strlog += " | p->Status == IN_IMG_Status_End, set product complete";
product->bIsImgComplete = true;
m_strTest += "\n";
product->AddLog(m_strTest);
m_strTest = "";
}
product->productBaseResult->detlog->bPrintStr = true;
product->productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg end", "%s", strlog.c_str());
ProductList_cond.notify_all();
}
return 0;
}
cv::Mat ALLImgCheckAnalysisy::hconcatWithFirstBase(const cv::Mat &img1, const cv::Mat &img2,
int interpolation = cv::INTER_LINEAR)
{
// 如果高度相同,直接拼接
if (img1.rows == img2.rows)
{
cv::Mat result;
cv::hconcat(img1, img2, result);
return result;
}
// 计算缩放比例
double scale = static_cast<double>(img1.rows) / img2.rows;
// 调整img2的高度
cv::Mat img2_resized;
cv::resize(img2, img2_resized, cv::Size(), scale, scale, interpolation);
// 拼接
cv::Mat result;
cv::hconcat(img1, img2_resized, result);
return result;
}
int ALLImgCheckAnalysisy::MergeShowImg(std::shared_ptr<Product> product)
{
int nDetCamNum = product->m_pCameraResultList.size();
// printf("MergeShowImg %s \n", product->productBaseResult->strproductName.c_str());
// 2个相机才操作
if (nDetCamNum == 2)
{
std::shared_ptr<CameraResult> pcam_0 = product->m_pCameraResultList.at(0);
std::shared_ptr<CameraResult> pcam_1 = product->m_pCameraResultList.at(1);
for (int i = 0; i < pcam_0->ImageALLDetResultList.size(); i++)
{
std::shared_ptr<CheckResult> pCheckResult_0 = pcam_0->ImageALLDetResultList.at(i)->result;
// printf("cam %s channel %s \n", pcam_0->cameraBaseResult->strCameraName.c_str(),
// pCheckResult_0->in_shareImage->strChannel.c_str());
for (int j = 0; j < pcam_1->ImageALLDetResultList.size(); j++)
{
std::shared_ptr<CheckResult> pCheckResult_1 = pcam_1->ImageALLDetResultList.at(j)->result;
if (pCheckResult_1->in_shareImage->strChannel == pCheckResult_0->in_shareImage->strChannel)
{
// printf("cam %s channel %s \n", pcam_1->cameraBaseResult->strCameraName.c_str(),
// pCheckResult_1->in_shareImage->strChannel.c_str());
if (!pCheckResult_0->resultimg.empty() && !pCheckResult_1->resultimg.empty())
{
cv::Mat meregeimg;
if (pCheckResult_0->in_shareImage->strCameraName == "left")
{
meregeimg = hconcatWithFirstBase(pCheckResult_0->resultimg, pCheckResult_1->resultimg);
}
else
{
meregeimg = hconcatWithFirstBase(pCheckResult_1->resultimg, pCheckResult_0->resultimg);
}
pCheckResult_0->resultimg = meregeimg;
pCheckResult_1->resultimg = meregeimg;
}
break;
}
}
}
}
return 0;
}
int ALLImgCheckAnalysisy::Run()
{
while (!m_bExit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
std::shared_ptr<Product> product = GetProduct();
int re = Det_Product(product);
// // 检测失败
// if (re != 0)
// {
// continue;
// }
SetSetComplet_New(product, re);
// 更新 产品队列
{
std::lock_guard<std::mutex> lock(mtx_ProductList); //
if (!m_ProductList.empty())
{
m_ProductList.erase(m_ProductList.begin());
}
}
}
return 0;
}
int ALLImgCheckAnalysisy::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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,250 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-13 20:39:37
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-24 14:17:12
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/CameraResult.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "CameraResult.h"
CameraResult::CameraResult()
{
cameraBaseResult = std::make_shared<CameraBaseResult>();
detlog = std::make_shared<DetLog>();
time_start = 0;
}
CameraResult::~CameraResult()
{
}
void CameraResult::AddLog(std::string str)
{
LogList.push_back(str);
}
int CameraResult::AddDetImage(std::shared_ptr<shareImage> p)
{
if (time_start == 0)
{
time_start = CheckUtil::getcurTime();
/* code */
}
std::shared_ptr<ImageAllResult> imgResult = std::make_shared<ImageAllResult>();
imgResult->cameraBaseResult = cameraBaseResult;
imgResult->productBaseResult = productBaseResult;
if (p->Det_Mode == DET_MODE_ReJson)
{
bJson = true;
}
imgResult->AddDetImage(p);
{
std::lock_guard<std::mutex> lock_cam(mtx_DetImageList);
ImageALLDetResultList.push_back(imgResult);
}
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
if (p->strChannel == "L255")
{
bHave_L255 = true;
}
if (p->strChannel == "Down-Particle")
{
bHave_DP = true;
}
if (p->strChannel == "Up-Particle")
{
bHave_Up = true;
}
}
std::string strTimg = CheckUtil::getCurTimeHMS();
detlog->bPrintStr = false;
detlog->AddCheckstr(PrintLevel_0, "PushInImg", " product %s Cam %s add new image channel = %s sum img %ld %s",
productBaseResult->strproductName.c_str(),
cameraBaseResult->strCameraName.c_str(), imgResult->strChannel.c_str(), ImageALLDetResultList.size(), strTimg.c_str());
return 0;
}
bool CameraResult::bCheckCamplate()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
if (checkStep == Check_Step_Complete)
{
return true;
}
return false;
}
Check_Step CameraResult::GetCheckStep()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
return checkStep;
}
void CameraResult::SetCheckStep(Check_Step step)
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
checkStep = step;
}
bool CameraResult::getImgPushComplate()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
return bIsImgComplete;
}
void CameraResult::setImgPushComplate()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
bIsImgComplete = true;
}
bool CameraResult::IsHaveL255()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
return bHave_L255;
}
bool CameraResult::Have_EdgeImg(std::string strConfig_Channel)
{
std::lock_guard<std::mutex> lock_cam(mtx_DetImageList);
for (auto ptr : ImageALLDetResultList)
{
if (ptr->IsChannel(strConfig_Channel))
{
return true;
}
}
return false;
}
void CameraResult::SetHaveL255(bool b)
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
bHave_L255 = b;
}
bool CameraResult::IsHaveDP()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
return bHave_DP;
}
void CameraResult::SetHaveDP(bool b)
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
bHave_DP = b;
}
bool CameraResult::IsHaveUp()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
return bHave_Up;
}
void CameraResult::SetHaveUp(bool b)
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
bHave_Up = b;
}
std::shared_ptr<ImageAllResult> CameraResult::GetNoDetImg()
{
std::lock_guard<std::mutex> lock_cam(mtx_DetImageList);
// 优先 up 然后是 dp
for (auto ptr : ImageALLDetResultList)
{
if (ptr->IsChannel("Up-Particle"))
{
if (ptr->IsNotDet())
{
return ptr;
}
}
}
for (auto ptr : ImageALLDetResultList)
{
if (ptr->IsChannel("Down-Particle"))
{
if (ptr->IsNotDet())
{
bool bok = true;
if (ptr->config_update.wait_UP &&
cameraBaseResult->UpImg_Status != CameraBaseResult::ImageDet_Status_DetComplete)
{
bok = false;
}
if (bok)
{
return ptr;
}
}
}
}
for (auto ptr : ImageALLDetResultList)
{
// 参数更新过了
if (ptr->config_update.bUpdate)
{
// 未检测的
if (ptr->IsNotDet())
{
bool bok = true;
// // 等待DP DP 没有 检测完成
if (ptr->config_update.wait_DP &&
cameraBaseResult->DPImg_Status != CameraBaseResult::ImageDet_Status_DetComplete)
{
bok = false;
}
if (ptr->config_update.wait_UP &&
cameraBaseResult->UpImg_Status != CameraBaseResult::ImageDet_Status_DetComplete)
{
bok = false;
}
if (bok)
{
return ptr;
}
}
}
}
return nullptr;
}
std::shared_ptr<ImageAllResult> CameraResult::GetL255DetImg()
{
std::lock_guard<std::mutex> lock_cam(mtx_DetImageList);
for (auto ptr : ImageALLDetResultList)
{
if (ptr->IsChannel("L255"))
{
return ptr;
}
}
return nullptr;
}
std::shared_ptr<ImageAllResult> CameraResult::GetEdgeChannel(std::string strConfig_Channel)
{
std::lock_guard<std::mutex> lock_cam(mtx_DetImageList);
for (auto ptr : ImageALLDetResultList)
{
if (ptr->IsChannel(strConfig_Channel))
{
return ptr;
}
}
return nullptr;
}

@ -0,0 +1,35 @@
#include "CheckErrorCodeDefine.hpp"
std::string GetErrorCodeInfo(int nErrorCode)
{
std::string str = "";
switch (nErrorCode)
{
case CHECK_OK:
str = "OK";
break;
case CHECK_ERROR_VERSION:
str = "interface version or config version error";
break;
case CHECK_ERROR_Config_Null:
str = "prt* config is null";
break;
case CHECK_ERROR_Config_Value:
str = "config value error";
break;
case CHECK_ERROR_Path_NULL:
str = "file Path is Null";
break;
case CHECK_ERROR_Mask_Empty:
str = "mask Image is empty";
break;
case CHECK_ERROR_Config_cutRoi:
str = "config Rect Value error";
break;
case CHECK_ERROR_CheckImg_Empty:
str = "check image is empty";
break;
default:
break;
}
return str;
}

@ -0,0 +1,173 @@
#include "CheckResultJson.h"
Json::Value CheckResultJson::toJsonValue()
{
Json::Value root;
{
root["cutRoi"]["x"] = m_pOneImgDetResult->CutRoi.x;
root["cutRoi"]["y"] = m_pOneImgDetResult->CutRoi.y;
root["cutRoi"]["width"] = m_pOneImgDetResult->CutRoi.width;
root["cutRoi"]["height"] = m_pOneImgDetResult->CutRoi.height;
}
{
root["Param_CropRoi"]["x"] = m_pOneImgDetResult->Param_CropRoi.x;
root["Param_CropRoi"]["y"] = m_pOneImgDetResult->Param_CropRoi.y;
root["Param_CropRoi"]["width"] = m_pOneImgDetResult->Param_CropRoi.width;
root["Param_CropRoi"]["height"] = m_pOneImgDetResult->Param_CropRoi.height;
}
for (int i = 0; i < m_pOneImgDetResult->pQx_ErrorList->size(); i++)
{
QX_ERROR_INFO_ *p = &m_pOneImgDetResult->pQx_ErrorList->at(i);
Json::Value value;
{
value["Idx"] = p->Idx;
value["result"] = p->result;
value["result_Name"] = p->result_name;
value["roi"]["x"] = p->roi.x;
value["roi"]["y"] = p->roi.y;
value["roi"]["width"] = p->roi.width;
value["roi"]["height"] = p->roi.height;
value["area"] = p->area;
value["energy"] = p->energy;
value["JudgArea"] = p->JudgArea;
value["JudgArea_second"] = p->JudgArea_second;
value["flen"] = p->flen;
value["nconfig_qx_type"] = p->nconfig_qx_type;
value["qx_name"] = p->qx_name;
value["maxValue"] = p->maxValue;
value["grayDis"] = p->grayDis;
value["fUpIou"] = p->fUpIou;
value["density"] = p->density;
// return root;
for (int jr = 0; jr < p->detRegionidxList.size(); jr++)
{
value["regionlist"].append(p->detRegionidxList[jr]);
}
}
root["Qx"].append(value);
}
return root;
}
void CheckResultJson::toObjectFromValue(Json::Value root)
{
m_pOneImgDetResult = std::make_shared<One_Image_CheckResult_>();
m_pOneImgDetResult->pQx_ErrorList = std::make_shared<std::vector<QX_ERROR_INFO_>>();
// std::cout << root << std::endl;
{
auto value = root["cutRoi"];
if (value.isObject())
{
m_pOneImgDetResult->CutRoi.x = root["cutRoi"]["x"].asInt();
m_pOneImgDetResult->CutRoi.y = root["cutRoi"]["y"].asInt();
m_pOneImgDetResult->CutRoi.width = root["cutRoi"]["width"].asInt();
m_pOneImgDetResult->CutRoi.height = root["cutRoi"]["height"].asInt();
}
}
{
auto value = root["Param_CropRoi"];
if (value.isObject())
{
m_pOneImgDetResult->Param_CropRoi.x = root["Param_CropRoi"]["x"].asInt();
m_pOneImgDetResult->Param_CropRoi.y = root["Param_CropRoi"]["y"].asInt();
m_pOneImgDetResult->Param_CropRoi.width = root["Param_CropRoi"]["width"].asInt();
m_pOneImgDetResult->Param_CropRoi.height = root["Param_CropRoi"]["height"].asInt();
}
}
{
if (root.isMember("Qx"))
{
const Json::Value &errorList = root["Qx"];
for (const auto &errorJson : errorList)
{
QX_ERROR_INFO_ tem;
tem.Idx = errorJson["Idx"].asInt();
// tem.result = errorJson["result"].asInt();
// tem.result_name = errorJson["result_Name"].asString();
tem.roi.x = errorJson["roi"]["x"].asInt();
tem.roi.y = errorJson["roi"]["y"].asInt();
tem.roi.width = errorJson["roi"]["width"].asInt();
tem.roi.height = errorJson["roi"]["height"].asInt();
tem.area = errorJson["area"].asInt();
tem.energy = errorJson["energy"].asInt();
tem.JudgArea = errorJson["JudgArea"].asFloat();
if (errorJson["JudgArea_second"])
{
tem.JudgArea_second = errorJson["JudgArea_second"].asFloat();
}
else
{
tem.JudgArea_second = tem.JudgArea;
}
tem.flen = errorJson["flen"].asFloat();
tem.nconfig_qx_type = errorJson["nconfig_qx_type"].asInt();
tem.qx_name = errorJson["qx_name"].asString();
tem.maxValue = errorJson["maxValue"].asInt();
tem.grayDis = errorJson["grayDis"].asFloat();
tem.fUpIou = errorJson["fUpIou"].asFloat();
tem.density = errorJson["density"].asFloat();
const Json::Value &regionvalue = errorJson["regionlist"];
if (regionvalue.isArray())
{
// std::cout<<regionvalue<<std::endl;
for (const auto &region : regionvalue)
{
tem.detRegionidxList.push_back(region.asInt());
}
}
m_pOneImgDetResult->pQx_ErrorList->push_back(tem);
// tem.print(std::to_string(m_pOneImgDetResult->pQx_ErrorList->size()));
}
}
}
}
int CheckResultJson::GetConfig(std::string strJson, std::shared_ptr<One_Image_CheckResult_> &pOneImgDetResult)
{
Json::CharReader *reader = readerBuilder.newCharReader();
string errs;
bool parsingSuccessful = reader->parse(strJson.c_str(), strJson.c_str() + strJson.size(), &root, &errs);
delete reader;
if (!parsingSuccessful)
{
cout << "Failed to parse JSON string: " << errs << endl;
return 1;
}
toObjectFromValue(root);
pOneImgDetResult = m_pOneImgDetResult;
return 0;
}
std::string CheckResultJson::GetResultString(std::shared_ptr<One_Image_CheckResult_> &pOneImgDetResult)
{
m_pOneImgDetResult = pOneImgDetResult;
if (m_pOneImgDetResult == nullptr || m_pOneImgDetResult->pQx_ErrorList == nullptr)
{
return "";
}
Json::Value root = toJsonValue();
Json::StreamWriterBuilder writerBuilder;
std::string jsonString = Json::writeString(writerBuilder, root);
return jsonString;
}

@ -0,0 +1,700 @@
/*
* FileName:CoreLogicFactory.cpp
* Version:V1.0
* Description:
* Created On:Mon Sep 10 11:13:16 UTC 2018
* Modified date:
* Author:Sky
*/
#include "CheckUtil.hpp"
#include <sys/time.h>
#include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <sstream>
#include <sys/statfs.h>
#include <stdlib.h>
#include <fstream>
#include <thread>
#include "snowflake.hpp"
int _sysmkdir_2(const std::string &dir)
{
int ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (ret && errno == EEXIST)
{
// printf("dir[%s] already exist.\n", dir.c_str());
}
else if (ret)
{
printf("create dir[%s] error: %d %s\n", dir.c_str(), ret, strerror(errno));
return -1;
}
else
{
printf("create dir[%s] success.\n", dir.c_str());
}
return 0;
}
std::string __getParentDir_2(const std::string &dir)
{
std::string pdir = dir;
if (pdir.length() < 1 || (pdir[0] != '/'))
{
return "";
}
while (pdir.length() > 1 && (pdir[pdir.length() - 1] == '/'))
pdir = pdir.substr(0, pdir.length() - 1);
pdir = pdir.substr(0, pdir.find_last_of('/'));
return pdir;
}
long CheckUtil::getcurTime()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000;
}
std::string CheckUtil::getCurrentDate()
{
struct timeval tv;
gettimeofday(&tv, NULL); // 获取当前时间
// 将 tv_sec 转换为 time_t 类型代表自1970年1月1日起的秒数
time_t raw_time = tv.tv_sec;
// 使用 localtime 将 time_t 转换为 tm 结构体
struct tm *time_info = localtime(&raw_time);
// 使用字符串流格式化为 "YYYY-MM-DD"
std::ostringstream oss;
oss << (time_info->tm_year + 1900) << "-" // tm_year 是从1900年开始的
<< (time_info->tm_mon + 1) << "-" // tm_mon 是从0开始的
<< time_info->tm_mday; // tm_mday 是当前月的天数
return oss.str(); // 返回日期字符串
}
std::string CheckUtil::getCurTimeHMS()
{
struct timeval tv;
gettimeofday(&tv, NULL); // 获取当前时间
time_t raw_time = tv.tv_sec;
struct tm *time_info = localtime(&raw_time);
int millisec = tv.tv_usec / 1000; // 微秒转毫秒
std::ostringstream oss;
oss << std::setfill('0') << std::setw(2) << time_info->tm_hour << ":"
<< std::setfill('0') << std::setw(2) << time_info->tm_min << ":"
<< std::setfill('0') << std::setw(2) << time_info->tm_sec << "."
<< std::setfill('0') << std::setw(3) << millisec;
return oss.str(); // 返回格式 "HH:MM:SS.mmm"
}
std::string CheckUtil::Op_float2String(float nvalue)
{
char buffer[20];
sprintf(buffer, "%.1f", nvalue);
std::string st1 = buffer;
return st1;
}
int64_t CheckUtil::getSnowId()
{
using snowflake_t = snowflake<1534832906275L, std::mutex>;
static snowflake_t uuid;
static bool bInit = false;
if (!bInit)
{
uuid.init(1, 1);
bInit = true;
}
return uuid.nextid();
return 0;
}
bool CheckUtil::JudgRect(cv::Rect roi, int img_w, int img_h)
{
if (img_w <= 0 || img_h <= 0)
{
return false;
}
if (roi.x < 0 || roi.x >= img_w)
{
return false;
}
if (roi.width <= 0 || roi.width >= img_w)
{
return false;
}
if (roi.y < 0 || roi.y >= img_h)
{
return false;
}
if (roi.height <= 0 || roi.height >= img_h)
{
return false;
}
if (roi.x + roi.width >= img_w)
{
return false;
}
if (roi.y + roi.height >= img_h)
{
return false;
}
return true;
}
bool CheckUtil::JudgRect_SZ(cv::Rect roi, int w, int h)
{
if (roi.x < 0 || roi.x >= w)
{
return false;
}
if (roi.width <= 0 || roi.width != w)
{
return false;
}
if (roi.y < 0 || roi.y >= h)
{
return false;
}
if (roi.height <= 0 || roi.height != h)
{
return false;
}
return true;
}
bool CheckUtil::compareIgnoreCase(const std::string &str1, const std::string &str2)
{
// 将 str1 和 str2 转换为小写后进行比较
std::string lower_str1 = str1;
std::string lower_str2 = str2;
// 使用 std::transform 将字符串转换为小写
std::transform(lower_str1.begin(), lower_str1.end(), lower_str1.begin(), ::tolower);
std::transform(lower_str2.begin(), lower_str2.end(), lower_str2.begin(), ::tolower);
// 比较两个转换后的字符串
return lower_str1 == lower_str2;
}
bool CheckUtil::RoiInImg(cv::Rect roi, cv::Mat img)
{
if (roi.width <= 0 || roi.height <= 0)
{
return false;
}
if ((roi & cv::Rect(0, 0, img.cols, img.rows)) == roi)
{
return true;
}
return false;
}
int CheckUtil::printROI(cv::Rect roi, std::string str)
{
printf("%s x %d y %d w %d h %d\n", str.c_str(), roi.x, roi.y, roi.width, roi.height);
return 0;
}
float CheckUtil::CalIoU(cv::Rect rect1, cv::Rect rect2)
{
// 计算交集区域
cv::Rect intersection = rect1 & rect2;
// 计算并集区域
cv::Rect union_rect = rect1 | rect2;
// 计算交集区域和并集区域的面积
double intersection_area = intersection.area();
double union_area = union_rect.area();
// 计算IoU值
double iou = intersection_area / union_area;
return iou;
}
float CheckUtil::CalIoU_t(cv::Rect rect1, cv::Rect rect2)
{
// 计算交集区域
cv::Rect intersection = rect1 & rect2;
// 计算并集区域
cv::Rect union_rect = rect1;
// 计算交集区域和并集区域的面积
double intersection_area = intersection.area();
double union_area = union_rect.area();
// 计算IoU值
double iou = intersection_area / union_area;
return iou;
}
int CheckUtil::CheckRect(cv::Rect &roi, int img_w, int img_h)
{
if (roi.x < 0 || roi.x >= img_w)
{
roi.x = 0;
}
if (roi.y < 0 || roi.y >= img_h)
{
roi.y = 0;
}
if (roi.width <= 0 || roi.width > img_w)
{
roi.width = 1;
}
if (roi.height <= 0 || roi.height > img_h)
{
roi.height = 1;
}
if (roi.x + roi.width > img_w)
{
roi.x = img_w - roi.width;
if (roi.x < 0)
{
roi.x = 0;
roi.width = img_w;
}
}
if (roi.y + roi.height > img_h)
{
roi.y = img_h - roi.height;
if (roi.y < 0)
{
roi.y = 0;
roi.height = img_h;
}
}
return 0;
}
int CheckUtil::SizeRect(cv::Rect &roi, int img_w, int img_h, int addw, int addh)
{
if (roi.width + 2 * addw > img_w)
{
return 1;
}
if (roi.height + 2 * addh > img_h)
{
return 1;
}
int sx = roi.x - addw;
int ex = roi.x + roi.width + addw;
if (sx < 0)
{
sx = 0;
}
if (ex > img_w)
{
ex = img_w;
}
int sy = roi.y - addh;
int ey = roi.y + roi.height + addh;
if (sy < 0)
{
sy = 0;
}
if (ey > img_h)
{
ey = img_h;
}
roi.x = sx;
roi.width = ex - sx;
roi.y = sy;
roi.height = ey - sy;
return 0;
}
int CheckUtil::CalHj(const cv::Mat &img, const cv::Mat &mask, int b_value)
{
cv::Mat imgf;
if (img.type() != CV_32F)
img.convertTo(imgf, CV_32F);
else
imgf = img;
// 2. 减去常数并取绝对值
cv::Mat absDiff = cv::abs(imgf - b_value);
// 3. 用 mask 计算平均值
cv::Scalar meanValue123 = cv::mean(absDiff, mask);
int nonZeroCount = cv::countNonZero(mask);
// printf("===========1== hj %f nonZeroCount %d\n", meanValue123[0], nonZeroCount);
if (nonZeroCount > 100)
{
cv::Mat element;
if (nonZeroCount > 1500)
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(11, 11));
}
else if (nonZeroCount > 1000)
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7));
}
else if (nonZeroCount > 500)
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
}
else
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
}
// 进行腐蚀操作
cv::Mat erodedMask;
cv::erode(mask, erodedMask, element);
int nonZeroCount111 = cv::countNonZero(erodedMask);
if (nonZeroCount111 > 100)
{
meanValue123 = cv::mean(absDiff, erodedMask);
// printf("========2===== hj %f nonZeroCount %d\n", meanValue123[0], nonZeroCount111);
}
}
// if (meanValue123[0] > 100)
// {
// // 打印 32F 像素值
// for (int i = 0; i < absDiff.rows; ++i)
// {
// for (int j = 0; j < absDiff.cols; ++j)
// {
// std::cout << "Pixel value at (" << i << ", " << j << "): "
// << absDiff.at<float>(i, j) << std::endl;
// }
// }
// }
return meanValue123[0];
}
int CheckUtil::CalHj(const cv::Mat &img, const cv::Mat &mask, const cv::Mat &backgroundimg)
{
cv::Mat imgf;
if (img.type() != CV_32F)
img.convertTo(imgf, CV_32F);
else
imgf = img;
cv::Scalar meanValue = cv::mean(backgroundimg);
int b_value = meanValue[0];
// 2. 减去常数并取绝对值
cv::Mat absDiff = cv::abs(imgf - b_value);
// 3. 用 mask 计算平均值
cv::Scalar meanValue123 = cv::mean(absDiff, mask);
return meanValue123[0];
}
float CheckUtil::CalRoi2RoiPre(cv::Rect rect1, cv::Rect rect2)
{
// 计算交集区域
cv::Rect intersection = rect1 & rect2;
// 计算并集区域
cv::Rect union_rect = rect1;
// 计算交集区域和并集区域的面积
double intersection_area = intersection.area();
double union_area = union_rect.area();
double iou = 0;
if (union_area != 0)
{
iou = intersection_area / union_area;
}
// 计算IoU值
return iou;
}
float CheckUtil::CalImgBrightness(cv::Mat imgRoi)
{
if (imgRoi.empty())
{
return 0.0f;
}
cv::Mat mat_mean, mat_stddev;
cv::meanStdDev(imgRoi, mat_mean, mat_stddev); // 求灰度图像的均值、均方差
float m = mat_mean.at<double>(0, 0);
return m;
}
float CheckUtil::Cal2PointAngle(cv::Point p_left, cv::Point p_right)
{
double angle = std::atan2(p_left.y - p_right.y, p_right.x - p_left.x);
return angle * 180 / 3.1415926;
}
cv::Rect CheckUtil::getLargestContourROI(const cv::Mat &binaryImg, bool &found)
{
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
// 查找轮廓
cv::findContours(binaryImg.clone(), contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
found = false;
if (contours.empty())
{
return cv::Rect(); // 返回空Rect
}
// 找到面积最大的轮廓
double maxArea = 0;
int maxAreaIdx = -1;
for (size_t i = 0; i < contours.size(); i++)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxAreaIdx = i;
}
}
// 如果没有找到有效轮廓比如所有轮廓面积都为0
if (maxAreaIdx == -1 || maxArea <= 0)
{
return cv::Rect();
}
found = true;
// 返回最大轮廓的边界矩形
return cv::boundingRect(contours[maxAreaIdx]);
}
std::string CheckUtil::GetRectString(cv::Rect rect)
{
std::string str = "[" + std::to_string(rect.x) + "," + std::to_string(rect.y) + "," + std::to_string(rect.width) + "," + std::to_string(rect.height) + "]";
return str;
}
int CheckUtil::CreateDir(const std::string &dir)
{
int ret = 0;
if (dir.empty())
return -1;
std::string pdir;
if ((ret = _sysmkdir_2(dir)) == -1)
{
pdir = __getParentDir_2(dir);
if ((ret = CreateDir(pdir)) == 0)
{
ret = CreateDir(dir);
}
}
return ret;
}
bool CheckUtil::bcalDis(cv::Point p1, cv::Point p2, int disT)
{
double dis = std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
if (dis < disT)
return true;
return false;
}
double CheckUtil::calDis(cv::Point2f p1, cv::Point2f p2)
{
double dis = std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
return dis;
}
void CheckUtil::PrintRect(cv::Rect roi, std::string str)
{
printf("%s x %d y %d w %d h %d \n", str.c_str(), roi.x, roi.y, roi.width, roi.height);
}
int CheckUtil::cutSmallImg(cv::Mat img, std::vector<cv::Rect> &samllRoiList, cv::Rect config_roi, int config_SmallImg_Width, int config_SmallImg_Height, int config_MinOverlap_Width, int config_MinOverlap_Height)
{
if (img.empty())
{
printf("error >>>> img.empty \n");
return 1;
/* code */
}
if (!RoiInImg(config_roi, img))
{
printf("error >>>> roi != img size \n");
return 2;
}
if (config_SmallImg_Width <= 0 ||
config_SmallImg_Height <= 0 ||
config_SmallImg_Width > img.cols ||
config_SmallImg_Height > img.rows)
{
printf("error >>>>config_SmallImg_Width %d config_SmallImg_Height %d \n ", config_SmallImg_Width, config_SmallImg_Height);
return 3;
}
if (config_MinOverlap_Width < 0 ||
config_MinOverlap_Height < 0 ||
config_MinOverlap_Width > img.cols ||
config_MinOverlap_Height > img.rows ||
config_MinOverlap_Width >= config_SmallImg_Width ||
config_MinOverlap_Height >= config_SmallImg_Height)
{
printf("error >>>>config_MinOverlap_Width %d config_MinOverlap_Height %d \n ", config_MinOverlap_Width, config_MinOverlap_Height);
return 4;
}
int AI_Img_width = config_SmallImg_Width;
int AI_Img_height = config_SmallImg_Height;
int start_x = config_roi.x;
int start_y = config_roi.y;
int end_x = config_roi.width + config_roi.x;
int end_y = config_roi.height + config_roi.y;
// 有效图片 宽 高
int det_width = config_roi.width;
int det_height = config_roi.height;
if (AI_Img_width > det_width || AI_Img_height > det_height)
{
printf("error >>>>config_SmallImg_Width %d != roi width %d \n ", config_SmallImg_Width, det_width);
printf("error >>>>config_SmallImg_Height %d != roi height %d \n ", config_SmallImg_Height, det_height);
return 5;
}
// printf("config_SmallImg_Width %d config_SmallImg_Height %d \n ", config_SmallImg_Width, config_SmallImg_Height);
// printf("config_MinOverlap_Width %d config_MinOverlap_Height %d \n ", config_MinOverlap_Width, config_MinOverlap_Height);
/////////////////、计算宽度方向 块的个数 和 重叠 ///////////////////////
// 可分为多少块 宽度度方向
float fBlocknum_x = det_width * 1.0f / AI_Img_width;
// 块的个数
int nBlocknum_x = std::ceil(fBlocknum_x);
// 如果 有重叠要求
if (config_MinOverlap_Width >= 0)
{
float fconfig_BlocknuNum_x = (det_width - AI_Img_width) * 1.0f / (config_SmallImg_Width - config_MinOverlap_Width) + 1;
int nconfig_BlocknuNum_x = std::ceil(fconfig_BlocknuNum_x);
if (nBlocknum_x < nconfig_BlocknuNum_x)
{
nBlocknum_x = nconfig_BlocknuNum_x;
}
}
int use_MinOverlap_Width = 0;
// 计算重叠率
if (nBlocknum_x > 1)
{
// 有多个块,要判断 块的重叠是否满足要求
int nSumLen_x = nBlocknum_x * AI_Img_width; //
float fOverlap_x = (nSumLen_x - det_width) * 1.0f / (nBlocknum_x - 1);
use_MinOverlap_Width = int(fOverlap_x);
}
// printf("nBlocknum_x %d use_MinOverlap_Width %d \n", nBlocknum_x, use_MinOverlap_Width);
/////////////////、计算高度方向 块的个数 和 重叠 ///////////////////////
// 可分为多少块 高度方向
float fBlocknum_y = det_height * 1.0f / AI_Img_height;
// 块的个数
int nBlocknum_y = std::ceil(fBlocknum_y);
// 如果 有重叠要求
if (config_MinOverlap_Height >= 0)
{
float fconfig_BlocknuNum_y = (det_height - AI_Img_height) * 1.0f / (config_SmallImg_Height - config_MinOverlap_Height) + 1;
int nconfig_BlocknuNum_y = std::ceil(fconfig_BlocknuNum_y);
if (nBlocknum_y < nconfig_BlocknuNum_y)
{
nBlocknum_y = nconfig_BlocknuNum_y;
}
}
int use_MinOverlap_Height = 0;
// 计算重叠率
if (nBlocknum_y > 1)
{
// 有多个块,要判断 块的重叠是否满足要求
int nSumLen_y = nBlocknum_y * AI_Img_height; //
float fOverlap_y = (nSumLen_y - det_height) * 1.0f / (nBlocknum_y - 1);
use_MinOverlap_Height = int(fOverlap_y);
}
// printf("nBlocknum_y %d use_MinOverlap_Height %d \n", nBlocknum_y, use_MinOverlap_Height);
int cut_sy = start_y;
int cut_ey = start_y + AI_Img_height;
for (int iy = 0; iy < nBlocknum_y; iy++)
{
int nleny = end_y - cut_ey;
int cut_sx = start_x;
int cut_ex = start_x + AI_Img_width;
for (int ix = 0; ix < nBlocknum_x; ix++)
{
cv::Rect roi;
roi.x = cut_sx;
roi.y = cut_sy;
roi.width = AI_Img_width;
roi.height = AI_Img_height;
samllRoiList.push_back(roi);
// 剩余长度
int nlenx = end_x - cut_ex;
if (nlenx > AI_Img_width)
{
cut_sx = cut_sx + AI_Img_width - use_MinOverlap_Width;
cut_ex = cut_sx + AI_Img_width;
}
else
{
cut_sx = end_x - AI_Img_width;
cut_ex = cut_sx + AI_Img_width;
}
}
if (nleny > AI_Img_height)
{
cut_sy = cut_sy + AI_Img_height - use_MinOverlap_Height;
cut_ey = cut_sy + AI_Img_height;
}
else
{
cut_sy = end_y - AI_Img_height;
cut_ey = cut_sy + AI_Img_height;
}
}
return 0;
}
cv::Point2f CheckUtil::transformPoint(const cv::Point2f &point, const cv::Mat &transform_matrix)
{
// 验证变换矩阵有效性
if (transform_matrix.empty() || transform_matrix.rows != 2 || transform_matrix.cols != 3)
{
std::cerr << "Error: Invalid transformation matrix! Returning original point." << std::endl;
return point;
}
// 使用矩阵乘法进行点变换
cv::Mat point_mat = (cv::Mat_<double>(3, 1) << point.x, point.y, 1);
cv::Mat result_mat = transform_matrix * point_mat;
return cv::Point2f(result_mat.at<double>(0), result_mat.at<double>(1));
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,147 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-13 20:39:37
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-24 14:17:55
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/CameraResult.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "ImageAllResult.h"
ImageAllResult::ImageAllResult()
{
detlog = std::make_shared<DetLog>();
pDetResult = std::make_shared<One_Image_CheckResult_>();
}
ImageAllResult::~ImageAllResult()
{
}
void ImageAllResult::AddLog(std::string str)
{
LogList.push_back(str);
}
ImageAllResult::DetStep ImageAllResult::getStep()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
return m_step;
}
void ImageAllResult::setStep(DetStep step)
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
m_step = step;
}
bool ImageAllResult::IsNotDet()
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
if (m_step == DetStep_NotDet)
{
return true;
}
return false;
}
bool ImageAllResult::IsChannel(std::string strChannelName)
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
if (strChannel == strChannelName)
{
return true;
}
return false;
}
int ImageAllResult::AddDetImage(std::shared_ptr<shareImage> p)
{
{
std::lock_guard<std::mutex> lock_cam(mtx_Det);
result = std::make_shared<CheckResult>();
p->time_PushIn = CheckUtil::getcurTime();
result->in_shareImage = p;
result->checkStatus = 1;
result->nDetStep = 0;
result->nresult = -1;
result->basicResult.img_id = p->img_id;
result->basicResult.imgtype = p->imgtype;
result->basicResult.imgstr = p->imgstr;
result->basicResult.strChannel = p->strChannel;
strChannel = p->strChannel;
if (strChannel == "Up-Particle")
{
cameraBaseResult->UpImg_Status = CameraBaseResult::ImageDet_Status_NoDet;
}
if (strChannel == "Down-Particle")
{
cameraBaseResult->DPImg_Status = CameraBaseResult::ImageDet_Status_NoDet;
}
}
// 需要指定 黑白画面
if (strChannel == "BTW" ||
strChannel == "WTB" ||
strChannel == "TBW" ||
strChannel == "HB3" ||
strChannel == "HB4")
{
bWhiteOrBlackImg = true;
}
strBaseInfo = productBaseResult->strproductName + " cam " + cameraBaseResult->strCameraName + " channel " + strChannel;
if (p->Det_Mode == DET_MODE_ReJson)
{
m_CheckResultJson.GetConfig(p->resultJson, pDetResult);
fscale_detToresult_x = 1;
fscale_detToresult_y = 1;
// 图片
if (!p->img.empty())
{
detImg = p->img;
/* code */
}
else
{
if (pDetResult->CutRoi.width > 0 && pDetResult->CutRoi.height > 0)
{
detImg = cv::Mat::zeros(pDetResult->CutRoi.height, pDetResult->CutRoi.width, CV_8UC1);
}
else
{
detImg = cv::Mat::zeros(1000, 2000, CV_8UC1);
}
}
{
cv::Size sz;
sz.width = RESIZE_IMAGE_WIDTH;
float fw = RESIZE_IMAGE_WIDTH * 1.0f / detImg.cols;
sz.height = int(detImg.rows * fw);
cv::resize(detImg, resultImg, sz);
if (resultImg.channels() == 1)
{
cv::cvtColor(resultImg, resultImg, cv::COLOR_GRAY2BGR);
}
result->resultimg = resultImg;
result->cutSrcimg = detImg;
fscale_detToresult_x = resultImg.cols * 1.0f / detImg.cols;
fscale_detToresult_y = resultImg.rows * 1.0f / detImg.rows;
}
// pDetResult->print("result");
// getchar();
}
return 0;
}

@ -0,0 +1,14 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2022-09-26 16:27:27
* @LastEditors: sueRimn
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp
*/
#include "ImageDetBase.h"
#include "ImgCheckAnalysisy.hpp"
ImgCheckBase *ImgCheckBase::GetInstance()
{
return (ImgCheckBase *)new ImgCheckAnalysisy();
}

@ -0,0 +1,9 @@
#include "ImageDetConfig.h"
#include "QX_Merge_Analysis.h"
#include <iostream>
// ProductBaseResult::ProductBaseResult()
// {
// pQX_Merge_Analysis = QX_Merge_Analysis::GetInstance();
// pQX_Merge_Analysis->InitData();
// }

@ -0,0 +1,801 @@
#include "ImageMerge.h"
#include "CheckUtil.hpp"
#include "CheckErrorCodeDefine.hpp"
ImageMerge::ImageMerge()
{
bshowimg = false;
m_bcalSucc = false;
}
ImageMerge::~ImageMerge() {}
int ImageMerge::CalMergeRoi(DetConfig *pDetConfig, cv::Mat &img1, const cv::Mat &img2)
{
// cv::imwrite("merge1.png", img1);
// cv::imwrite("merge2.png", img2);
m_bcalSucc = false;
std::cout << img1.size() << std::endl;
std::cout << img2.size() << std::endl;
// if (img1.size() != img2.size())
// {
// return -1;
// }
long t1, t2;
t1 = CheckUtil::getcurTime();
int re = 0;
cv::Rect Left_Roi;
cv::Rect Right_Roi;
bool bleft = ProductSide_left(img1);
cv::Mat leftImg = img1;
cv::Mat rightImg = img2;
m_bleft_img1 = bleft;
if (bleft)
{
leftImg = img1;
rightImg = img2;
}
else
{
leftImg = img2;
rightImg = img1;
}
int max_len = img1.cols;
if (img2.cols > max_len)
{
max_len = img2.cols;
}
m_ALLImgSize.width = max_len * 2;
m_ALLImgSize.height = rightImg.rows;
// cv::Mat AllImg = cv::Mat::zeros(rightImg.rows, max_len * 2, rightImg.type());
{
cv::Rect Left_Tem_Roi;
cv::Point Left_Tem_Point_Up;
cv::Point Left_Tem_Point_Donw;
cv::Rect Right_Tem_Roi;
cv::Point Right_Tem_Point_Up;
cv::Point Right_Tem_Point_Donw;
// left Img
{
re = GetRectAndPoint(leftImg, Left_Tem_Roi, Left_Tem_Point_Up, Left_Tem_Point_Donw, true, pDetConfig->strcam, pDetConfig->strchannel + "left");
if (re != 0)
{
// m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg GetRectAndPoint TAA error %d", strcam.c_str(), re);
return 1;
}
re = GetRectAndPoint(rightImg, Right_Tem_Roi, Right_Tem_Point_Up, Right_Tem_Point_Donw, false, pDetConfig->strcam, pDetConfig->strchannel + "right");
if (re != 0)
{
return 1;
}
cv::Rect roi_right;
roi_right.x = 0;
roi_right.y = 0;
roi_right.height = rightImg.rows;
roi_right.width = rightImg.cols;
m_roi_right_img = roi_right;
m_roi_right_ALLimg = roi_right;
// rightImg(roi_right).copyTo(AllImg(roi_right));
int hlen_left = Left_Tem_Point_Donw.y - Left_Tem_Point_Up.y;
int hlen_right = Right_Tem_Point_Donw.y - Right_Tem_Point_Up.y;
float fhscle = hlen_right * 1.0f / hlen_left;
int dy = Right_Tem_Point_Up.y - Left_Tem_Point_Up.y;
cv::Rect allroi = Left_Tem_Roi;
allroi.height *= fhscle;
allroi.x = Right_Tem_Roi.x + Right_Tem_Roi.width;
allroi.y += dy;
// cv::Size sz;
// sz.width = allroi.width;
// sz.height = allroi.height;
m_roi_left_img = Left_Tem_Roi;
m_roi_left_ALLimg = allroi;
// cv::resize(leftImg(Left_Tem_Roi), AllImg(allroi), sz);
}
}
m_bcalSucc = true;
re = detMergeImg(img1, img2);
if (re != 0)
{
return 1;
}
// img1 = AllImg;
t2 = CheckUtil::getcurTime();
//cv::imwrite(pDetConfig->strcam + pDetConfig->strchannel + "_merg.png", img1);
// m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg use time %ld ms", pDetConfig->strcam.c_str(), t2 - t1);
return 0;
}
int ImageMerge::detMergeImg(cv::Mat &img1, const cv::Mat &img2)
{
if (m_bcalSucc == false)
{
return -1;
}
cv::Mat AllImg = cv::Mat::zeros(m_ALLImgSize.height, m_ALLImgSize.width, img1.type());
cv::Mat leftImg = img1;
cv::Mat rightImg = img2;
if (m_bleft_img1)
{
leftImg = img1;
rightImg = img2;
}
else
{
leftImg = img2;
rightImg = img1;
}
rightImg(m_roi_right_img).copyTo(AllImg(m_roi_right_ALLimg));
cv::Size sz;
sz.width = m_roi_left_ALLimg.width;
sz.height = m_roi_left_ALLimg.height;
cv::resize(leftImg(m_roi_left_img), AllImg(m_roi_left_ALLimg), sz);
img1 = AllImg;
return 0;
}
int ImageMerge::GetRectAndPoint(const cv::Mat &img, cv::Rect &roi, cv::Point &merg_p_up, cv::Point &merg_p_down, bool bleft, std::string strcam, std::string strchannel)
{
bshowimg = true;
int A_line_up = 0;
int A_line_down = 0;
Edge_Search_Config config;
if (bshowimg)
{
if (img.channels() != 1)
{
showimg = img.clone();
}
else
{
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
}
}
config.nSearchCount = 10;
config.strchannel = strchannel;
config.directSign = DirectSign_UP;
if (bleft)
{
config.roi = cv::Rect(0, 0, 200, img.rows * 0.8);
}
else
{
config.roi = cv::Rect(img.cols - 200, 0, 200, img.rows * 0.8);
}
int re123 = GetEdgePoint(img, &config, A_line_up);
if (re123 != 0)
{
printf("DirectSign_UP::111111111111GetEdgePoint111111 A_line_up %d\n", re123);
return 1;
}
config.directSign = DirectSign_DOWN;
config.strchannel = strchannel + "ccc";
config.roi = cv::Rect(0, img.rows * 0.2, 200, img.rows * 0.8 - 1);
if (bleft)
{
config.roi = cv::Rect(0, img.rows * 0.2, 200, img.rows * 0.8 - 1);
}
else
{
config.roi = cv::Rect(img.cols - 200, img.rows * 0.2, 200, img.rows * 0.8 - 1);
}
re123 = GetEdgePoint(img, &config, A_line_down);
if (re123 != 0)
{
printf("DirectSign_UP::111111111111GetEdgePoint111111 A_line_down %d\n", re123);
return 1;
}
{
if (bshowimg)
{
cv::line(showimg, cv::Point(0, A_line_down), cv::Point(img.cols, A_line_down), cv::Scalar(0, 255, 0), 2);
cv::line(showimg, cv::Point(0, A_line_up), cv::Point(img.cols, A_line_up), cv::Scalar(0, 255, 0), 2);
cv::imwrite(strcam + strchannel + "_line.png", showimg);
}
}
// printf("DirectSign_UP::111111111111111111 re123 %d\n", re123);
// getchar();
cv::Mat small, smallbin;
cv::resize(img, small, cv::Size(600, 1500));
cv::threshold(small, smallbin, 80, 255,
cv::THRESH_BINARY);
/* 3. contours */
std::vector<std::vector<cv::Point>> contours;
cv::findContours(smallbin, contours,
cv::RETR_EXTERNAL,
cv::CHAIN_APPROX_SIMPLE);
if (contours.empty())
return 1;
/* 4. max contour */
double maxArea = 0;
int idx = -1;
for (int i = 0; i < contours.size(); i++)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
idx = i;
}
}
if (idx < 0)
return 1;
cv::Rect rSmall = cv::boundingRect(contours[idx]);
/* 5. map to original */
float sx = (float)img.cols / smallbin.cols;
float sy = (float)img.rows / smallbin.rows;
cv::Rect rectInSrc;
rectInSrc.x = int(rSmall.x * sx) - 50;
rectInSrc.y = int(rSmall.y * sy) - 50;
rectInSrc.width = int(rSmall.width * sx) + 100;
rectInSrc.height = int(rSmall.height * sy) + 100;
if (rectInSrc.y >= A_line_up)
{
rectInSrc.y = A_line_up - 5;
}
if (rectInSrc.y + rectInSrc.height <= A_line_down)
{
rectInSrc.height = A_line_down + 5 - rectInSrc.y;
}
if (rectInSrc.x < 0)
rectInSrc.x = 0;
if (rectInSrc.y < 0)
rectInSrc.y = 0;
if (rectInSrc.x + rectInSrc.width > img.cols)
rectInSrc.width = img.cols - rectInSrc.x;
if (rectInSrc.y + rectInSrc.height > img.rows)
{
rectInSrc.height = img.rows - rectInSrc.y;
}
merg_p_up.y = A_line_up;
merg_p_up.x = img.cols;
merg_p_down.y = A_line_down;
merg_p_down.x = img.cols;
roi = rectInSrc;
if (bshowimg)
{
cv::rectangle(showimg, rectInSrc, cv::Scalar(0, 0, 255), 2);
cv::imwrite(strcam + strchannel + "_rect.png", showimg);
}
return 0;
}
int ImageMerge::GetEdgePoint(const cv::Mat &img, Edge_Search_Config *pEdge_Search_Config, int &outP)
{
bool bdbuge = false;
bdbuge = bshowimg;
if (img.empty())
{
return -11;
}
if (img.channels() != 1)
{
printf("*****************************channels\n");
return -12;
}
// 检查roi;
if (!CheckUtil::RoiInImg(pEdge_Search_Config->roi, img))
{
return -13;
}
if (!pEdge_Search_Config->CheckConfigValid())
{
return -14;
}
std::vector<cv::Point> pointList;
bool search_UP_DOWN = false;
cv::Rect roi = pEdge_Search_Config->roi;
int sx = roi.x;
int ex = roi.x + roi.width;
int sy = roi.y;
int ey = roi.y + roi.height;
int nSearchLen = roi.width; // 搜索区域的长度
int nCurPoint_Step = pEdge_Search_Config->stepCount; // 当前点搜索的步长
// 搜索小范围确认
int nhalfrang = (int)pEdge_Search_Config->nSearchrange / 2;
int nrange_start = 0 - nhalfrang;
int nrange_end = 0 - nhalfrang;
int num = 0;
while (true)
{
num++;
nrange_end++;
if (num >= pEdge_Search_Config->nSearchrange)
{
break;
}
}
// 判断方向
switch (pEdge_Search_Config->directSign)
{
case DirectSign_UP:
search_UP_DOWN = true;
nSearchLen = roi.width;
sx = roi.x;
ex = roi.x + roi.width;
sy = roi.y;
ey = roi.y + roi.height;
nCurPoint_Step = pEdge_Search_Config->stepCount;
break;
case DirectSign_DOWN:
search_UP_DOWN = true;
nSearchLen = roi.width;
nCurPoint_Step = -pEdge_Search_Config->stepCount;
sx = roi.x;
ex = roi.x + roi.width;
sy = roi.y + roi.height - 1;
ey = roi.y;
break;
case DirectSign_Left:
nSearchLen = roi.height;
search_UP_DOWN = false;
nCurPoint_Step = pEdge_Search_Config->stepCount;
sx = roi.x;
ex = roi.x + roi.width;
sy = roi.y;
ey = roi.y + roi.height;
break;
case DirectSign_Right:
nSearchLen = roi.height;
search_UP_DOWN = false;
nCurPoint_Step = -pEdge_Search_Config->stepCount;
sx = roi.x + roi.width - 1;
ex = roi.x;
sy = roi.y;
ey = roi.y + roi.height;
break;
default:
break;
}
// 搜索 点数
int nSearchPointNum = pEdge_Search_Config->nSearchCount;
// 搜素点的间隔
int nSearchPointStep = 1;
if (nSearchPointNum > 1)
{
nSearchPointStep = int(nSearchLen * 1.0f / (nSearchPointNum - 1));
}
if (bdbuge)
{
cv::rectangle(showimg, roi, cv::Scalar(255, 0, 0), 2);
printf("nSearchPointStep %d nCurPoint_Step %d,nrange_start %d %d\n", nSearchPointStep, nCurPoint_Step, nrange_start, nrange_end);
}
uchar *pdata = (uchar *)img.data;
int offt = 0;
// 搜索 上下边
if (search_UP_DOWN)
{
// 每个搜索点 分布在X方向。
for (int x = sx; x < ex; x = x + nSearchPointStep)
{
int bOKNum = 0;
int cur_x = x;
int cur_y = sy;
bool bSucc = false;
int succ_y = 0;
// 对每个搜索点进行 y方向搜索
for (int y = sy;; y = y + nCurPoint_Step)
{
if (y < 0 || y >= img.rows)
{
continue;
}
//
if (nCurPoint_Step > 0 && y > ey)
{
break;
}
if (nCurPoint_Step < 0 && y < ey)
{
break;
}
offt = y * img.cols;
int range_okNum = 0;
// 对一定范围的点进行判断
for (int k = nrange_start; k < nrange_end; k++)
{
int rangeX = x + k;
if (rangeX < 0 || rangeX >= img.cols)
{
continue;
}
offt += rangeX;
if (offt < 0 || offt >= img.cols * img.rows)
{
printf("rangeX %d nCurPoint_Step %d off %d x %d y %d sy %d ey %d %d %d\n", rangeX, nCurPoint_Step, offt, x, y, sy, ey, img.cols, img.rows);
}
if (pdata[offt] >= pEdge_Search_Config->nValueThreshold) // 找到
{
range_okNum++;
}
}
if (range_okNum >= pEdge_Search_Config->nSearchrange)
{
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 0, 255));
}
if (bOKNum == 0)
{
cur_y = y;
}
bOKNum++;
// 连续搜索到 满足要求的点。
if (bOKNum >= pEdge_Search_Config->nLimit)
{
bSucc = true;
succ_y = y;
break;
}
}
else
{
// 如果有间断,需要重新计算连续情况。
bOKNum = 0;
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 255, 0));
}
}
}
if (bSucc)
{
cv::Point p(cur_x, cur_y);
if (bdbuge)
{
cv::circle(showimg, p, 3, cv::Scalar(255, 0, 0));
}
pointList.push_back(p);
if (pointList.size() > 5)
{
// printf("=============feeeee\n");
sy = succ_y - 100;
ey = succ_y + 100;
switch (pEdge_Search_Config->directSign)
{
case DirectSign_UP:
sy = succ_y - 100;
ey = succ_y + 100;
break;
case DirectSign_DOWN:
sy = succ_y + 100;
ey = succ_y - 100;
break;
default:
break;
}
if (sy < 0)
{
sy = 0;
}
if (ey >= img.rows)
{
ey = img.rows - 1;
}
if (ey < 0)
{
ey = 0;
}
if (sy >= img.rows)
{
sy = img.rows - 1;
}
}
}
}
}
else // 搜索 左右边
{
// 每个搜索点 分布在X方向。
for (int y = sy; y < ey; y = y + nSearchPointStep)
{
int bOKNum = 0;
int cur_x = sx;
int cur_y = y;
bool bSucc = false;
int succ_x = 0;
// 对每个搜索点进行 y方向搜索
for (int x = sx;; x = x + nCurPoint_Step)
{
if (x < 0 || x >= img.cols)
{
continue;
}
//
if (nCurPoint_Step > 0 && x > ex)
{
break;
}
if (nCurPoint_Step < 0 && x < ex)
{
break;
}
int range_okNum = 0;
// 对一定范围的点进行判断
for (int k = nrange_start; k < nrange_end; k++)
{
int rangey = y + k;
if (rangey < 0 || rangey >= img.rows)
{
continue;
}
offt = rangey * img.cols + x;
if (offt < 0 || offt >= img.cols * img.rows)
{
printf("rangey %d off %d x %d y %d ey %d %d %d\n", rangey, offt, x, y, ey, img.cols, img.rows);
}
if (pdata[offt] >= pEdge_Search_Config->nValueThreshold) // 找到
{
range_okNum++;
}
}
if (range_okNum >= pEdge_Search_Config->nSearchrange)
{
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 0, 255));
}
if (bOKNum == 0)
{
cur_x = x;
}
bOKNum++;
// 连续搜索到 满足要求的点。
if (bOKNum >= pEdge_Search_Config->nLimit)
{
bSucc = true;
succ_x = x;
break;
}
}
else
{
// 如果有间断,需要重新计算连续情况。
bOKNum = 0;
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 255, 0));
}
}
}
if (bSucc)
{
cv::Point p(cur_x, cur_y);
if (bdbuge)
{
cv::circle(showimg, p, 3, cv::Scalar(255, 0, 0));
}
pointList.push_back(p);
if (pointList.size() > 5)
{
// printf("=============feeeee\n");
sx = succ_x - 100;
ex = succ_x + 100;
if (sx < 0)
{
sx = 0;
}
if (ex >= img.cols)
{
ex = img.cols - 1;
}
}
}
}
}
if (bdbuge)
{
cv::imwrite(pEdge_Search_Config->strchannel + "show.png", showimg);
}
{
const int maxDeviation = 10; // 可调阈值:最大允许偏离像素
std::vector<cv::Point> avgPoints;
int PNum = pointList.size();
// 第一次计算粗略均值
int sum_y = 0, sum_x = 0;
for (const auto &pt : pointList)
{
sum_x += pt.x;
sum_y += pt.y;
}
float avg_y = sum_y * 1.0f / PNum;
float avg_x = sum_x * 1.0f / PNum;
// 过滤异常点
std::vector<cv::Point> filtered;
for (const auto &pt : pointList)
{
if (search_UP_DOWN) // 横向:判断 y 偏差
{
if (std::abs(pt.y - avg_y) <= maxDeviation)
filtered.push_back(pt);
}
else // 纵向:判断 x 偏差
{
if (std::abs(pt.x - avg_x) <= maxDeviation)
filtered.push_back(pt);
}
}
if (filtered.empty())
return -1;
int sum_fx = 0, sum_fy = 0;
for (const auto &pt : filtered)
{
sum_fx += pt.x;
sum_fy += pt.y;
}
if (search_UP_DOWN) // 横向:判断 y 偏差
{
outP = sum_fy / (int)filtered.size();
}
else // 纵向:判断 x 偏差
{
outP = sum_fx / (int)filtered.size();
}
}
return 0;
}
int ImageMerge::GetLine(const cv::Mat &img, std::vector<cv::Point> &pointList, int lineNum, int xory, int &outP)
{
if (pointList.size() < 0)
return -1;
const int maxDeviation = 10; // 可调阈值:最大允许偏离像素
std::vector<cv::Point> avgPoints;
int PNum = pointList.size();
// 第一次计算粗略均值
int sum_y = 0, sum_x = 0;
for (const auto &pt : pointList)
{
sum_x += pt.x;
sum_y += pt.y;
}
float avg_y = sum_y * 1.0f / PNum;
float avg_x = sum_x * 1.0f / PNum;
// 过滤异常点
std::vector<cv::Point> filtered;
for (const auto &pt : pointList)
{
if (xory == 0) // 横向:判断 y 偏差
{
if (std::abs(pt.y - avg_y) <= maxDeviation)
filtered.push_back(pt);
}
else // 纵向:判断 x 偏差
{
if (std::abs(pt.x - avg_x) <= maxDeviation)
filtered.push_back(pt);
}
}
if (filtered.empty())
return -1;
int sum_fx = 0, sum_fy = 0;
for (const auto &pt : filtered)
{
sum_fx += pt.x;
sum_fy += pt.y;
}
if (xory == 0) // 横向:判断 y 偏差
{
outP = sum_fy / (int)filtered.size();
}
else // 纵向:判断 x 偏差
{
outP = sum_fx / (int)filtered.size();
}
return 0;
}
bool ImageMerge::ProductSide_left(const cv::Mat &img)
{
cv::Rect Roi_left, Right_Roi;
Roi_left.x = 0;
Roi_left.y = 0;
Roi_left.width = img.cols * 0.1;
Roi_left.height = img.rows;
Right_Roi.x = img.cols - img.cols * 0.1;
Right_Roi.y = 0;
Right_Roi.width = img.cols * 0.1;
Right_Roi.height = img.rows;
cv::Mat left_img = img(Roi_left);
cv::Mat right_img = img(Right_Roi);
cv::Size sz = cv::Size(200, 600);
cv::resize(left_img, left_img, sz);
cv::resize(right_img, right_img, sz);
int nonZeroCount_left = cv::countNonZero(left_img);
int nonZeroCount_right = cv::countNonZero(right_img);
if (nonZeroCount_left >= nonZeroCount_right)
{
return true;
}
else
{
return false;
}
return false;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,85 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-11 15:32:52
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-16 09:40:36
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/ImageStorage.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include "ImageStorage.h"
#include <iostream>
#include <opencv2/opencv.hpp>
ImageStorage *ImageStorage::instance = nullptr;
ImageStorage::ImageStorage() : stopFlag(false)
{
// 启动存储线程
storageThread = std::thread(&ImageStorage::storeImages, this);
}
ImageStorage::~ImageStorage()
{
stop(); // 在销毁时确保线程被正确停止
}
// 获取单例实例的静态方法
ImageStorage *ImageStorage::getInstance()
{
if (instance == nullptr)
{
instance = new ImageStorage(); // 如果实例为空,则创建新实例
}
return instance;
}
void ImageStorage::storeImages()
{
while (!stopFlag)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep for 100 milliseconds
std::unique_lock<std::mutex> lock(queueMutex);
cv.wait(lock, [this]()
{ return !imageQueue.empty() || stopFlag; });
if (stopFlag && imageQueue.empty())
break;
auto item = imageQueue.front();
imageQueue.pop();
lock.unlock();
cv::Mat temimg = item.first;
if (!temimg.empty())
{
cv::imwrite(item.second, item.first); // 保存图片到文件
// std::cout << "Image saved to: " << item.second << std::endl;
}
}
}
int ImageStorage::addImage(const std::string &path, const cv::Mat &image, bool badd)
{
std::lock_guard<std::mutex> lock(queueMutex);
if (imageQueue.size() > 1000 && !badd)
{
std::cout << "Queue has more than 10 items, not adding new images." << std::endl;
return 1;
}
else
{
imageQueue.push({image, path});
cv.notify_one(); // 通知存储线程处理新任务
}
return 0;
}
void ImageStorage::stop()
{
stopFlag = true;
cv.notify_one(); // 通知存储线程停止
if (storageThread.joinable())
{
storageThread.join(); // 等待线程退出
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,21 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2022-09-26 16:27:27
* @LastEditors: sueRimn
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp
*/
#include "ImgCheckBase.h"
#include "ImgCheckAnalysisy.hpp"
#include "ImgCheckConfig.h"
#include "ALLImgCheckAnalysisy.hpp"
ALLImgCheckBase *ALLImgCheckBase::instance = nullptr;
ALLImgCheckBase *ALLImgCheckBase::GetInstance()
{
// if (instance == nullptr)
// {
// instance = (ALLImgCheckBase *)new ALLImgCheckAnalysisy();
// }
return (ALLImgCheckBase *)new ALLImgCheckAnalysisy();;
}

@ -0,0 +1,46 @@
#include "OtherDetect.h"
#include "CheckErrorCodeDefine.hpp"
AIDetectBase ::AIDetectBase(/* args */)
{
m_pOtherDet_Config = NULL;
m_bInitialized = false;
m_bModelSucc = false;
}
AIDetectBase ::~AIDetectBase()
{
}
int AIDetectBase ::Init(OtherDet_Config *pOtherDet_Config)
{
m_pOtherDet_Config = pOtherDet_Config;
m_bInitialized = true;
return 0;
}
LackPolDet::LackPolDet(/* args */)
{
}
LackPolDet::~LackPolDet()
{
}
int LackPolDet::Init_LackPol()
{
return 0;
}
int LackPolDet::InitModel_ALL()
{
return 0;
}
int LackPolDet::Detect(const cv::Mat &img, DetConfig *pDetConfig, cv::Mat &outMask)
{
return 0;
}

@ -0,0 +1,97 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-13 19:26:19
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-17 18:10:38
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/Product.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*
*/
#include "Product.h"
#include "QX_Merge_Analysis.h"
Product::Product(/* args */)
{
productBaseResult = std::make_shared<ProductBaseResult>();
productBaseResult->detlog = std::make_shared<DetLog>();
productBaseResult->pQX_Merge_Analysis = QX_Merge_Analysis::GetInstance();
productBaseResult->pQX_Merge_Analysis->InitData();
productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "Product create %s productBaseResult ", CheckUtil::getCurTimeHMS().c_str());
}
Product::~Product()
{
}
std::shared_ptr<CameraResult> Product::GetCameraResult(std::string strcameraName)
{
// 加锁保证多线程安全
std::lock_guard<std::mutex> lock(mtx_CameraResultList);
for (auto &ptr : m_pCameraResultList)
{
if (ptr->cameraBaseResult->strCameraName == strcameraName)
{
return ptr;
}
}
productBaseResult->detlog->bPrintStr = false;
// 不存在,创建新的 CameraResult 并插入 map
std::shared_ptr<CameraResult> newResult = std::make_shared<CameraResult>();
newResult->productBaseResult = productBaseResult;
newResult->cameraBaseResult->strCameraName = strcameraName;
m_pCameraResultList.push_back(newResult);
productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "11111 Camera %s %s", strcameraName.c_str(), CheckUtil::getCurTimeHMS().c_str());
productBaseResult->pQX_Merge_Analysis->AddCamer(strcameraName);
productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "22222 Camera %s %s", strcameraName.c_str(), CheckUtil::getCurTimeHMS().c_str());
productBaseResult->nCamera_Num = m_pCameraResultList.size();
productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "add new Camera %s %s", strcameraName.c_str(), CheckUtil::getCurTimeHMS().c_str());
return newResult;
}
void Product::AddLog(std::string str)
{
LogList.push_back(str);
}
void Product::UpdatePushStatus(int status)
{
if (IN_IMG_Status_End == status ||
IN_IMG_Status_OneImg == status ||
-1 == status)
{
bIsImgComplete = true;
std::lock_guard<std::mutex> lock(mtx_CameraResultList); // 加锁保护 map
for (auto &ptr : m_pCameraResultList)
{
// printf("===========1112\n");
ptr->setImgPushComplate();
}
std::string strTimg = CheckUtil::getCurTimeHMS();
productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "%s Add ALL img end %s m_pCameraResultList %ld ",
productBaseResult->strproductName.c_str(), strTimg.c_str(), m_pCameraResultList.size());
}
}
bool Product::bCheckCamplate()
{
// 所有的图都送完了。
if (bIsImgComplete)
{
bool ballcomplate = true;
std::lock_guard<std::mutex> lock(mtx_CameraResultList); // 加锁保护 map
for (auto &ptr : m_pCameraResultList)
{
if (!ptr->bCheckCamplate())
{
ballcomplate = false;
break;
}
}
if (ballcomplate)
{
return true;
}
}
return false;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,36 @@
#include "Task.h"
Task::Task()
{
}
Task::~Task()
{
}
int Task::sendTask(std::shared_ptr<TaskInfo> task)
{
{
std::lock_guard<std::mutex> lock(m_task_mutex_);
task->SetStatus(TaskStep_Waite);
m_tasks_.push(task);
}
m_task_cv_.notify_one();
return 0;
}
std::shared_ptr<TaskInfo> Task::GetTask()
{
std::shared_ptr<TaskInfo> task;
{
std::unique_lock<std::mutex> lock(m_task_mutex_);
m_task_cv_.wait(lock, [this]()
{ return !m_tasks_.empty(); });
task = std::move(m_tasks_.front());
m_tasks_.pop();
}
return task;
}

@ -0,0 +1,72 @@
#CMake
cmake_minimum_required (VERSION 3.5)
project(rootproject)
set(CHECK_WORK_Value "CELL_ET")
if (DEFINED WORK)
set(CHECK_WORK_Value ${WORK})
endif()
#
add_definitions(-DCHECK_WORK="${CHECK_WORK_Value}")
message(STATUS "CHECK_WORK: ${CHECK_WORK_Value}")
find_package( OpenCV REQUIRED )
message(STATUS "oPENCV Library status:")
message(STATUS ">version:${OpenCV_VERSION}")
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
set(CMAKE_BUILD_TYPE "release")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # C++17
set(CMAKE_CXX_EXTENSIONS OFF) # GNU
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
#set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; --default-stream per-thread)
add_definitions(-DCUDA_API_PER_THREAD_DEFAULT_STREAM)
# PROJECT_INCLUDE_DIR
set(PROJECT_INCLUDE_DIR c/include)
# x86_64,aarch64
set(BUILD_ARCH x86_64 CACHE STRING "Arch of this project" FORCE)
MESSAGE(STATUS "BUILD_ARCH : ${BUILD_ARCH}")
MESSAGE(STATUS "CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}")
MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})
#
include(${PROJECT_SOURCE_DIR}/cmake/default_variabes.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/cpp_c_flags.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/print_archs.cmake)
include_directories(${PROJECT_SOURCE_DIR}/include/)
include_directories(/usr/local/boost/include
/usr/include
${OpenCV_INCLUDE_DIRS}
)
link_directories(
${PROJECT_SOURCE_DIR}/lib/x86_64/
/usr/local/boost/lib
)
#
MESSAGE("build dependent module - start")
# ADD_SUBDIRECTORY(src) src CMakeLists.txt
add_subdirectory(ConfigModule)
MESSAGE("ConfigModule")
# CommonUtil
add_subdirectory(AlgorithmModule)
MESSAGE("AlgorithmModule")
add_subdirectory(example)
MESSAGE("example")

@ -0,0 +1,18 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2022-09-23 21:51:58
* @LastEditors: sueRimn
* @Description: koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
*/
#ifndef Base_Define_H_
#define Base_Define_H_
#include <opencv2/opencv.hpp>
#include <iostream>
#define RECT_TO_STRING(rect) \
"(x=" + std::to_string((rect).x) + ", y=" + std::to_string((rect).y) \
+ ", width=" + std::to_string((rect).width) + ", height=" + std::to_string((rect).height) + ")"
#endif

@ -0,0 +1,42 @@
#
cmake_minimum_required (VERSION 3.5)
set(ModuleName "ConfigModule")
include(${PROJECT_SOURCE_DIR}/cmake/default_variabes.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/cpp_c_flags.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/print_archs.cmake)
#
include_directories(
/usr/local/include
${CMAKE_CURRENT_SOURCE_DIR}/include
)
link_directories(
/usr/local/lib/
)
# set使*.cpp
file(GLOB SRC_LISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
add_library(Config SHARED ${SRC_LISTS})
target_link_libraries(Config
${OpenCV_LIBS}
)
set(ModuleName "")
#add_subdirectory(example)
# make install /usr/local
#
set(CMAKE_INSTALL_PREFIX /usr/local/cellet CACHE PATH "Install path prefix" FORCE)
set(HEADER_FILES include/ConfigBase.h)
#
install(TARGETS Config
LIBRARY DESTINATION lib # CMAKE_INSTALL_PREFIX/lib
ARCHIVE DESTINATION lib/static
RUNTIME DESTINATION bin
PUBLIC_HEADER DESTINATION include) # CMAKE_INSTALL_PREFIX/include
#
install(FILES ${HEADER_FILES} DESTINATION include)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,91 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-11 15:32:54
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-13 18:49:40
* @FilePath: /BOE_CELL_AOI_Detect/ConfigModule/include/ConfigBase.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#ifndef ConfigBase_H_
#define ConfigBase_H_
#include <string>
#include <unordered_map>
#include <memory>
#define CONFIGBASE_VERSION 4
#define EMPTY_CONFIG_NAME "ALL"
enum CONFIG_TYPE_
{
ConfigType_Analysisy_Common_XL,
ConfigType_Check_XL,
ConfigType_Image_In,
ConfigType_Image_out,
ConfigType_BloB,
ConfigType_Count,
};
struct ImageInfo
{
int width;
int height;
int channels;
ImageInfo()
{
width = 0;
height = 0;
channels = 0;
}
void copy(ImageInfo tem)
{
this->width = tem.width;
this->height = tem.height;
this->channels = tem.channels;
}
void print(std::string str)
{
printf("%s width=%d height=%d channels=%d\n", str.c_str(), width, height, channels);
}
};
class ConfigBase
{
protected:
ConfigBase() {}
public:
// delete camera interface
~ConfigBase() {}
static std::shared_ptr<ConfigBase> GetInstance();
virtual int GetConfigIdx() = 0;
// 获取参数更新状态 true 有更新
virtual bool GetConfigUpdataStatus(int nConfigType, int nidx) = 0;
// 复制想使用的参数
virtual int GetConfig(int nConfigType, void *pconfig) = 0;
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
virtual int UpdateConfig(void *pconfig, int nConfigType) = 0;
virtual int UpdateJSONConfig(void *pconfig, int nConfigType) = 0;
// 返回检测版本信息
virtual std::string GetVersion() = 0;
// 返回错误信息
virtual std::string GetErrorInfo() = 0;
};
class ConfigManagerBase
{
protected:
ConfigManagerBase() {}
public:
// delete camera interface
~ConfigManagerBase() {}
static ConfigManagerBase *GetInstance();
virtual int LoadAnalysisConfig(std::string strConfigPath) = 0;
virtual int UpdateConfig() = 0;
virtual int GetConfig(int nConfigType, void *pconfig) = 0;
static ConfigManagerBase *m_pInstance;
public:
std::unordered_map<std::string, std::shared_ptr<ConfigBase>> Config_instances_;
};
#endif

@ -0,0 +1,49 @@
#ifndef ConfigInstance_H_
#define ConfigInstance_H_
#include "JsonCoversion.h"
#include <stdio.h>
#include <mutex>
#include <string.h>
#include <thread>
#include "ConfigBase.h"
#include "Define.h"
#include "JsonConfig.h"
#include "CheckConfigDefine.h"
class ConfigInstance : public ConfigBase
{
public:
ConfigInstance();
~ConfigInstance();
int GetConfigIdx();
bool GetConfigUpdataStatus(int nConfigType, int nidx);
// 获取想使用的参数
int GetConfig(int nConfigType, void *pconfig);
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
int UpdateConfig(void *pconfig, int nConfigType);
int UpdateJSONConfig(void *pconfig, int nConfigType);
// 返回检测版本信息
std::string GetVersion();
// 返回错误信息
std::string GetErrorInfo();
private:
// updata analysis cofnig
int Updata_analysis(Json::Value json_value);
int Updata_Check(Json::Value json_value);
// 设置 参数更新状态
int SetStatus(int nConfigType);
// 成员变量
private:
int m_ErrorValue; // 错误代码
std::mutex mutex_status;
bool m_USER_ConfigUpdataStatusList[ConfigType_Count][MAX_USER_COUNT];
AnalysisyConfigST m_AnalysisyConfig;
CheckConfigST m_CheckConfig;
std::mutex mtx_GetIdx; //
int m_nCurIdx;
};
#endif

@ -0,0 +1,55 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-09 13:57:25
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-11 21:57:35
* @FilePath: /BOE_Bounding/ConfigModule/include/ConfigBase.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#ifndef ConfigManager_H_
#define ConfigManager_H_
#include "JsonCoversion.h"
#include <stdio.h>
#include <iostream>
#include <filesystem>
#include <string.h>
#include <thread>
#include "ConfigBase.h"
#include "Define.h"
#include "JsonConfig.h"
#include "CheckConfigDefine.h"
#include <fstream>
#include <memory>
#include <vector>
using namespace std;
namespace fs = std::filesystem;
class ConfigManager : public ConfigManagerBase
{
public:
ConfigManager();
~ConfigManager();
int LoadAnalysisConfig(std::string strConfigPath);
int UpdateConfig();
int GetConfig(int nConfigType, void *pconfig);
struct CameraParam
{
std::string identity;
std::string code;
std::string desc;
std::string name;
int64_t created_at;
};
int ReadParamName(std::vector<CameraParam>& camera_list); // 读取参数名配置
private:
int LoadParamConfig(std::shared_ptr<ConfigBase> &Config, std::string strConfigPath);
private:
std::string m_strConfigRootPath;
};
#endif

@ -0,0 +1,46 @@
#ifndef Define_H_
#define Define_H_
#include <string>
// 参数使用最大的用户数 用以更新 参数使用
#define MAX_USER_COUNT 10
enum ERROR_TYPE_Config_
{
ERROR_Type_Ok,
ERROR_Type_JsonNull,
ERROR_Type_ConfigType,
ERROR_Type_Count,
};
static const std::string ERROR_TYPE_Names[] =
{
"OK",
"Json Is Null",
"Config Type Error"};
struct CommonParamST
{
std::string image;
std::string skuName;
std::string value;
CommonParamST()
{
image = "";
value = "";
skuName = "";
}
void copy(CommonParamST tem)
{
this->image = tem.image;
this->value = tem.value;
this->skuName = tem.skuName;
}
};
enum CHECK_INSTUCT_
{
CHECK_INSTUCT_NULL = 1, // 空
CHECK_INSTUCT_WhiteAndBlack = CHECK_INSTUCT_NULL * 2, // WTB,BTW,HB3,HB4 使用单独检查方法
};
#endif

@ -0,0 +1,86 @@
#ifndef CamConfig_H
#define CamConfig_H
#include "JsonCoversion.h"
#include <stdio.h>
#include <string.h>
#include "CheckConfigDefine.h"
#include "Define.h"
class CommonParamJson : public JsonCoversion
{
public:
CommonParamJson() {}
virtual ~CommonParamJson() {}
public:
virtual Json::Value toJsonValue();
virtual void toObjectFromValue(Json::Value root);
int GetConfig(CommonParamST &config);
private:
CommonParamST _config;
};
class CommonParamToCheckConfigJson : public JsonCoversion
{
public:
CommonParamToCheckConfigJson() {}
virtual ~CommonParamToCheckConfigJson() {}
public:
virtual Json::Value toJsonValue();
virtual void toObjectFromValue(Json::Value root);
int GetConfig(CommonCheckConfigST &config);
private:
CommonCheckConfigST _config;
};
class CheckConfigJson : public JsonCoversion
{
public:
CheckConfigJson() {}
virtual ~CheckConfigJson() {}
public:
virtual Json::Value toJsonValue();
virtual void toObjectFromValue(Json::Value root);
int GetConfig(CheckConfigST &config);
private:
CheckConfigST _config;
};
class ChannelFuntonConfigJson : public JsonCoversion
{
public:
ChannelFuntonConfigJson() {}
virtual ~ChannelFuntonConfigJson() {}
public:
virtual Json::Value toJsonValue();
virtual void toObjectFromValue(Json::Value root);
int GetConfig(ALLChannelCheckFunction &config);
int GetFunction(Json::Value value, CheckFunction &function);
private:
ALLChannelCheckFunction _config;
};
class BaseFuntonConfigJson : public JsonCoversion
{
public:
BaseFuntonConfigJson() {}
virtual ~BaseFuntonConfigJson() {}
public:
virtual Json::Value toJsonValue();
virtual void toObjectFromValue(Json::Value root);
int GetConfig(BaseCheckFunction &config);
int GetFunction(Json::Value value);
private:
BaseCheckFunction _config;
};
#endif //

@ -0,0 +1,31 @@
#ifndef JsonCoversion_H
#define JsonCoversion_H
#include<iostream>
#include<memory>
#include<string>
#include "json/json.h"
using namespace std;
class JsonCoversion
{
protected:
Json::Value root;
// Json::FastWriter writer; //弃用 改用StreamWriterBuilder
Json::StreamWriterBuilder writerBuilder;
// Json::Reader reader; //弃用 改用CharReaderBuilder
Json::CharReaderBuilder readerBuilder;
public:
JsonCoversion();
virtual ~JsonCoversion();
protected:
public:
string toJson();
void toObject(string & strBuf);
protected:
virtual Json::Value toJsonValue() = 0;
virtual void toObjectFromValue(Json::Value root) = 0;
};
#endif // JsonCoversion_H

@ -0,0 +1,346 @@
/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).
/// It is intended to be used with #include "json/json-forwards.h"
/// This header provides forward declaration for all JsonCpp types.
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: LICENSE
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
========================================================================
(END LICENSE TEXT)
The MIT license is compatible with both the GPL and commercial
software, affording one all of the rights of Public Domain with the
minor nuisance of being required to keep the above copyright notice
and license text in the source code. Note also that by accepting the
Public Domain "license" you can re-license your copy using whatever
license you like.
*/
// //////////////////////////////////////////////////////////////////////
// End of content of file: LICENSE
// //////////////////////////////////////////////////////////////////////
#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
# define JSON_FORWARD_AMALGAMATED_H_INCLUDED
/// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion.
#define JSON_IS_AMALGAMATION
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/config.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_CONFIG_H_INCLUDED
#define JSON_CONFIG_H_INCLUDED
#include <stddef.h>
#include <stdint.h> //typedef int64_t, uint64_t
#include <string> //typedef String
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of
/// std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
// If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions.
#ifndef JSON_USE_EXCEPTION
#define JSON_USE_EXCEPTION 1
#endif
/// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL
#include <cpptl/config.h>
#ifndef JSON_USE_CPPTL
#define JSON_USE_CPPTL 1
#endif
#endif
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#endif // ifdef JSON_IN_CPPTL
#if !defined(JSON_API)
#define JSON_API
#endif
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
// integer
// Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1
#if defined(_MSC_VER) // MSVC
#if _MSC_VER <= 1200 // MSVC 6
// Microsoft Visual Studio 6 only support conversion from __int64 to double
// (no conversion from unsigned __int64).
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
// characters in the debug information)
// All projects I've ever seen with VS6 were using this globally (not bothering
// with pragma push/pop).
#pragma warning(disable : 4786)
#endif // MSVC 6
#if _MSC_VER >= 1500 // MSVC 2008
/// Indicates that the following function is deprecated.
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif
#endif // defined(_MSC_VER)
// In c++11 the override keyword allows you to explicitly define that a function
// is intended to override the base-class version. This makes the code more
// manageable and fixes a set of common hard-to-find bugs.
#if __cplusplus >= 201103L
#define JSONCPP_OVERRIDE override
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
#define JSONCPP_OVERRIDE override
#define JSONCPP_NOEXCEPT throw()
#if _MSC_VER >= 1800 // MSVC 2013
#define JSONCPP_OP_EXPLICIT explicit
#else
#define JSONCPP_OP_EXPLICIT
#endif
#elif defined(_MSC_VER) && _MSC_VER >= 1900
#define JSONCPP_OVERRIDE override
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#else
#define JSONCPP_OVERRIDE
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT
#endif
#ifndef JSON_HAS_RVALUE_REFERENCES
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // MSVC >= 2010
#ifdef __clang__
#if __has_feature(cxx_rvalue_references)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // has_feature
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // GXX_EXPERIMENTAL
#endif // __clang__ || __GNUC__
#endif // not defined JSON_HAS_RVALUE_REFERENCES
#ifndef JSON_HAS_RVALUE_REFERENCES
#define JSON_HAS_RVALUE_REFERENCES 0
#endif
#ifdef __clang__
#if __has_extension(attribute_deprecated_with_message)
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#endif
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
#endif // GNUC version
#endif // __clang__ || __GNUC__
#if !defined(JSONCPP_DEPRECATED)
#define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)
#if __GNUC__ >= 6
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif
#if !defined(JSON_IS_AMALGAMATION)
#include "version.h"
#if JSONCPP_USING_SECURE_MEMORY
#include "allocator.h" //typedef Allocator
#endif
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
typedef int Int;
typedef unsigned int UInt;
#if defined(JSON_NO_INT64)
typedef int LargestInt;
typedef unsigned int LargestUInt;
#undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#else // if defined(_MSC_VER) // Other platforms, use long long
typedef int64_t Int64;
typedef uint64_t UInt64;
#endif // if defined(_MSC_VER)
typedef Int64 LargestInt;
typedef UInt64 LargestUInt;
#define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
#if JSONCPP_USING_SECURE_MEMORY
#define JSONCPP_STRING \
std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
#define JSONCPP_OSTRINGSTREAM \
std::basic_ostringstream<char, std::char_traits<char>, \
Json::SecureAllocator<char> >
#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char> >
#define JSONCPP_ISTRINGSTREAM \
std::basic_istringstream<char, std::char_traits<char>, \
Json::SecureAllocator<char> >
#define JSONCPP_ISTREAM std::istream
#else
#define JSONCPP_STRING std::string
#define JSONCPP_OSTRINGSTREAM std::ostringstream
#define JSONCPP_OSTREAM std::ostream
#define JSONCPP_ISTRINGSTREAM std::istringstream
#define JSONCPP_ISTREAM std::istream
#endif // if JSONCPP_USING_SECURE_MEMORY
} // end namespace Json
#endif // JSON_CONFIG_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/config.h
// //////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/forwards.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_FORWARDS_H_INCLUDED
#define JSON_FORWARDS_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
// writer.h
class FastWriter;
class StyledWriter;
// reader.h
class Reader;
// features.h
class Features;
// value.h
typedef unsigned int ArrayIndex;
class StaticString;
class Path;
class PathArgument;
class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
} // namespace Json
#endif // JSON_FORWARDS_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/forwards.h
// //////////////////////////////////////////////////////////////////////
#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED

File diff suppressed because it is too large Load Diff

@ -0,0 +1,30 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-11 18:42:03
* @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 "ConfigBase.h"
#include "ConfigInstance.h"
#include "ConfigManager.h"
std::shared_ptr<ConfigBase> ConfigBase::GetInstance()
{
std::shared_ptr<ConfigBase> pInstance = std::make_shared<ConfigInstance>();
return pInstance;
}
bool compareBylay(const RegionConfigST &a, const RegionConfigST &b)
{
return a.basicInfo.lay < b.basicInfo.lay;
}
ConfigManagerBase *ConfigManagerBase::m_pInstance = nullptr;
ConfigManagerBase *ConfigManagerBase::GetInstance()
{
if (!m_pInstance)
{
m_pInstance = new ConfigManager();
}
return m_pInstance;
}

@ -0,0 +1,222 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-25 09:15:15
* @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 "ConfigInstance.h"
ConfigInstance::ConfigInstance()
{
m_ErrorValue = ERROR_Type_Ok;
m_nCurIdx = 0;
}
ConfigInstance::~ConfigInstance()
{
}
int ConfigInstance::GetConfigIdx()
{
std::lock_guard<std::mutex> lock(mtx_GetIdx);
int reidx = m_nCurIdx;
if (reidx < 0)
{
reidx = 0;
}
m_nCurIdx++;
if (m_nCurIdx >= MAX_USER_COUNT)
{
m_nCurIdx = MAX_USER_COUNT - 1;
}
return reidx;
}
bool ConfigInstance::GetConfigUpdataStatus(int nConfigType, int nidx)
{
std::lock_guard<std::mutex> lock(mutex_status);
if (nConfigType >= 0 && nConfigType < ConfigType_Count && nidx >= 0 && nidx < MAX_USER_COUNT)
{
m_ErrorValue = ERROR_Type_Ok;
bool status = m_USER_ConfigUpdataStatusList[nConfigType][nidx];
m_USER_ConfigUpdataStatusList[nConfigType][nidx] = false;
return status;
}
m_ErrorValue = ERROR_Type_ConfigType;
return false;
}
int ConfigInstance::GetConfig(int nConfigType, void *pconfig)
{
if (nConfigType >= 0 && nConfigType < ConfigType_Count)
{
}
else
{
m_ErrorValue = ERROR_Type_ConfigType;
return m_ErrorValue;
}
AnalysisyConfigST *p = (AnalysisyConfigST *)pconfig;
CheckConfigST *p1 = (CheckConfigST *)pconfig;
ImageInfo *pimg = (ImageInfo *)pconfig;
switch (nConfigType)
{
case ConfigType_Analysisy_Common_XL:
p->copy(m_AnalysisyConfig);
break;
case ConfigType_Check_XL:
p1->copy(m_CheckConfig);
break;
case ConfigType_Image_In:
pimg->copy(m_CheckConfig.Srcimg_in);
break;
case ConfigType_Image_out:
pimg->copy(m_CheckConfig.resultimg_out);
break;
}
m_ErrorValue = ERROR_Type_Ok;
return 0;
}
int ConfigInstance::UpdateConfig(void *pconfig, int nConfigType)
{
m_ErrorValue = ERROR_Type_Ok;
return 0;
}
int ConfigInstance::UpdateJSONConfig(void *pconfig, int nConfigType)
{
if (pconfig == NULL)
{
m_ErrorValue = ERROR_Type_JsonNull;
return m_ErrorValue;
}
if (nConfigType < 0 || nConfigType >= ConfigType_Count)
{
m_ErrorValue = ERROR_Type_ConfigType;
return m_ErrorValue;
}
Json::Value *pJsonConfig = (Json::Value *)pconfig;
switch (nConfigType)
{
case ConfigType_Analysisy_Common_XL:
Updata_analysis(*pJsonConfig);
/* code */
break;
case ConfigType_Check_XL:
/* code */
Updata_Check(*pJsonConfig);
break;
default:
break;
}
// getchar();
m_ErrorValue = ERROR_Type_Ok;
return 0;
}
std::string ConfigInstance::GetVersion()
{
m_ErrorValue = ERROR_Type_Ok;
return std::string();
}
std::string ConfigInstance::GetErrorInfo()
{
return ERROR_TYPE_Names[m_ErrorValue];
}
int ConfigInstance::Updata_analysis(Json::Value json_value)
{
// std::cout << json_value << std::endl;
CommonParamJson configJson;
configJson.toObjectFromValue(json_value);
CommonParamST config;
configJson.GetConfig(config);
printf("------config.skuName %s \n", config.skuName.c_str());
// 解析成对应的 参数
CommonParamToCheckConfigJson tp;
tp.toObjectFromValue(config.value);
tp.GetConfig(m_AnalysisyConfig.commonCheckConfig);
m_AnalysisyConfig.strSkuName = config.skuName;
int img_W = 0;
int img_H = 0;
for (int i = 0; i < m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.size(); i++)
{
if (i == 0)
{
img_W = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).nodebasicConfog.img_width;
img_H = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).nodebasicConfog.img_height;
}
// m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).ToMaskImg();
// std::string strpath = "mask_" + std::to_string(i) + ".jpg";
// if (!m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).mask.empty())
// {
// cv::imwrite(strpath, m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).mask);
// }
}
// 解析成对应的 参数
ChannelFuntonConfigJson jxjason;
jxjason.toObjectFromValue(config.value);
jxjason.GetConfig(m_AnalysisyConfig.checkFunction);
for (int i = 0; i < m_AnalysisyConfig.checkFunction.channelFunctionArr.size(); i++)
{
m_AnalysisyConfig.checkFunction.channelFunctionArr.at(i).function.f_ShieldRegion.ToMaskImg(img_W, img_H);
m_AnalysisyConfig.checkFunction.channelFunctionArr.at(i).function.f_EdgeROI.ToMaskImg(img_W, img_H);
m_AnalysisyConfig.checkFunction.channelFunctionArr.at(i).function.f_Image_Align.ToMaskImg(img_W, img_H);
}
BaseFuntonConfigJson basefjason;
basefjason.toObjectFromValue(config.value);
basefjason.GetConfig(m_AnalysisyConfig.baseFunction);
// m_AnalysisyConfig.checkFunction.print("------------ChannelFunction---------------");
// getchar();
// 更新所有状态
SetStatus(ConfigType_Analysisy_Common_XL);
m_ErrorValue = ERROR_Type_Ok;
return 0;
}
int ConfigInstance::Updata_Check(Json::Value json_value)
{
std::cout << json_value << std::endl;
// 解析成对应的 参数
CheckConfigJson tp;
tp.toObjectFromValue(json_value);
tp.GetConfig(m_CheckConfig);
// 更新所有状态
SetStatus(ConfigType_Check_XL);
m_ErrorValue = ERROR_Type_Ok;
return 0;
}
int ConfigInstance::SetStatus(int nConfigType)
{
for (int i = 0; i < MAX_USER_COUNT; i++)
{
m_USER_ConfigUpdataStatusList[nConfigType][i] = true;
}
m_ErrorValue = ERROR_Type_Ok;
return 0;
}

@ -0,0 +1,179 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-11 22:03:50
* @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 "ConfigManager.h"
#include <regex>
#include "ConfigBase.h"
ConfigManager::ConfigManager()
{
m_strConfigRootPath = "";
}
ConfigManager::~ConfigManager()
{
}
int ConfigManager::LoadParamConfig(std::shared_ptr<ConfigBase> &Config, std::string strConfigPath)
{
Json::Reader json_reader;
Json::Value json_value;
std::ifstream infile(strConfigPath, ios::binary);
printf("Analysis_Config_path========== %s \n", strConfigPath.c_str());
// getchar();
if (infile.is_open())
{
if (json_reader.parse(infile, json_value))
{
Config->UpdateJSONConfig((void *)&json_value, ConfigType_Analysisy_Common_XL);
printf("m_pConfig ConfigType_Analysisy_Common_XL %s\n", Config->GetErrorInfo().c_str());
}
else
{
printf("****%s fail \n", strConfigPath.c_str());
}
}
else
{
printf("****%s fail \n", strConfigPath.c_str());
infile.close();
return 1;
}
infile.close();
return 0;
}
int ConfigManager::LoadAnalysisConfig(std::string strConfigPath)
{
m_strConfigRootPath = strConfigPath;
int re = UpdateConfig();
return re;
}
int ConfigManager::UpdateConfig()
{
std::vector<CameraParam> camera_list;
int re = ReadParamName(camera_list);
if (re != 0)
{
printf("ConfigManager::UpdateConfig() ReadParamName error re = %d\n", re);
return re;
/* code */
}
for (auto &camera : camera_list)
{
std::string strConfigPath = m_strConfigRootPath + "/param_" + camera.code + ".json";
std::shared_ptr<ConfigBase> temConfig = ConfigBase::GetInstance();
re = LoadParamConfig(temConfig, strConfigPath);
if (re != 0)
{
printf("ConfigManager::UpdateConfig() LoadParamConfig %s error re = %d\n", strConfigPath.c_str(), re);
continue;
}
AnalysisyConfigST p;
temConfig->GetConfig(ConfigType_Analysisy_Common_XL, &p);
printf("********* CamearName %s\n", p.commonCheckConfig.baseConfig.strCamearName.c_str());
if (p.commonCheckConfig.baseConfig.strCamearName == "")
{
printf("Error >>>> camear Name is empty \n");
continue;
}
Config_instances_[p.commonCheckConfig.baseConfig.strCamearName] = temConfig;
}
// getchar();
// std::regex pattern(R"(param_[0-9]\.json)");
// if (!fs::exists(m_strConfigRootPath))
// {
// std::cerr << "目录不存在: " << m_strConfigRootPath << std::endl;
// return 1;
// }
// Config_instances_.clear();
// for (const auto &entry : fs::directory_iterator(m_strConfigRootPath))
// {
// if (entry.is_regular_file())
// {
// std::string filename = entry.path().filename().string();
// if (std::regex_match(filename, pattern))
// {
// std::cout << "匹配文件: " << entry.path() << std::endl;
// std::shared_ptr<ConfigBase> temConfig = ConfigBase::GetInstance();
// int re = LoadParamConfig(temConfig, entry.path());
// if (re != 0)
// {
// continue;
// }
// AnalysisyConfigST p;
// temConfig->GetConfig(ConfigType_Analysisy_Common_XL, &p);
// printf("********* CamearName %s\n", p.commonCheckConfig.baseConfig.strCamearName.c_str());
// if (p.commonCheckConfig.baseConfig.strCamearName == "")
// {
// printf("Error >>>> camear Name is empty \n");
// continue;
// }
// Config_instances_[p.commonCheckConfig.baseConfig.strCamearName] = temConfig;
// }
// }
// else
// {
// std::cerr << "config error 2: " << m_strConfigRootPath << std::endl;
// }
// }
return 0;
}
int ConfigManager::GetConfig(int nConfigType, void *pconfig)
{
return 0;
}
int ConfigManager::ReadParamName(std::vector<CameraParam> &camera_list)
{
std::string file_path = m_strConfigRootPath + "/camera_list.json";
Json::Reader json_reader;
Json::Value json_value;
std::ifstream infile(file_path, ios::binary);
if (!infile.is_open())
{
printf("****%s open fail\n", file_path.c_str());
return 1;
}
if (!json_reader.parse(infile, json_value))
{
printf("****%s parse fail\n", file_path.c_str());
infile.close();
return 1;
}
infile.close();
camera_list.clear();
for (const auto &camera : json_value)
{
CameraParam param;
param.identity = camera["identity"].asString();
param.code = camera["code"].asString();
param.desc = camera["desc"].asString();
param.name = camera["name"].asString();
param.created_at = camera["created_at"].asInt64();
printf("Camera: identity=%s, code=%s, name=%s, desc=%s, created_at=%ld\n",
param.identity.c_str(), param.code.c_str(), param.name.c_str(), param.desc.c_str(), param.created_at);
camera_list.push_back(param);
}
return 0;
}

@ -0,0 +1 @@
#include "Define.h"

File diff suppressed because it is too large Load Diff

@ -0,0 +1,35 @@
#include "JsonCoversion.h"
JsonCoversion::JsonCoversion()
{
//ctor
}
JsonCoversion::~JsonCoversion()
{
//dtor
}
string JsonCoversion::toJson()
{
toJsonValue();
std::unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
std::ostringstream os;
std::string jsonStr;
jsonWriter->write(root,&os);
jsonStr = os.str();
return jsonStr;
}
void JsonCoversion::toObject(string & strBuf)
{
std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
JSONCPP_STRING errs;
bool res = jsonReader->parse(strBuf.c_str(), strBuf.c_str()+strBuf.length(), &root, &errs);
if (!res || !errs.empty())
{
std::cout << "parseJson err. " << errs << std::endl;
}
toObjectFromValue(root);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,41 @@
if(CMAKE_BUILD_TYPE MATCHES "(Release|RELEASE|release)")
# release mode
set(CMAKE_BUILD_TYPE "release")
else()
set(CMAKE_BUILD_TYPE "debug")
# debug mode
if(NOT (${CMAKE_C_FLAGS} MATCHES "-g"))
add_compile_options(-g)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
endif()
if(NOT (${CMAKE_CXX_FLAGS} MATCHES "-g"))
add_compile_options(-g)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
endif()
endif()
#---------------------------------------------------------------------------------------------------
#++++++add c++11 standard and c99 standard
if(NOT (${CMAKE_C_FLAGS} MATCHES "-std="))
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
endif()
if(NOT (${CMAKE_CXX_FLAGS} MATCHES "-std="))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
endif()
#---------------------------------------------------------------------------------------------------
#++++++add path of link library
if(NOT (${CMAKE_C_FLAGS} MATCHES "-Wl,-rpath,"))
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-rpath,.:lib/:lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/HK/:../lib/${BUILD_ARCH}/HK/HCNetSDKCom")
endif()
if(NOT (${CMAKE_CXX_FLAGS} MATCHES "-Wl,-rpath,"))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-rpath,.:lib/:lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/HK/:../lib/${BUILD_ARCH}/HK/HCNetSDKCom")
endif()
#---------------------------------------------------------------------------------------------------
# message(STATUS "CMAKE_CXX_FLAGS:${CMAKE_CXX_FLAGS}")

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save