Initial commit from BOE_CELL_AOI_Detect

dev_lsy
xiewenji 1 week ago
commit 50e9883a79

6
.gitignore vendored

@ -0,0 +1,6 @@
/build
/lib
/include
/data
/SaveImg
.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,84 @@
{
"files.associations": {
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"array": "cpp",
"atomic": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"complex": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"filesystem": "cpp",
"functional": "cpp",
"iterator": "cpp",
"map": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"set": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"variant": "cpp",
"bit": "cpp",
"regex": "cpp",
"shared_mutex": "cpp",
"__nullptr": "cpp",
"__split_buffer": "cpp",
"__locale": "cpp",
"__atomic": "cpp",
"__bit_reference": "cpp",
"__functional_base": "cpp",
"__node_handle": "cpp",
"__memory": "cpp",
"locale": "cpp",
"ios": "cpp",
"__hash_table": "cpp",
"__tree": "cpp",
"queue": "cpp",
"stack": "cpp",
"__mutex_base": "cpp"
},
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json"
}

@ -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,304 @@
/*
* @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;
gpu.gpu_0 = true;
gpu.gpu_1 = true;
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;
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,215 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-03 09:48:19
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-14 20:25:35
* @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
{
bool gpu_0;
bool gpu_1;
GPU_Config()
{
gpu_0 = true;
gpu_1 = true;
}
int GetNum()
{
int num = 0;
if (gpu_0)
{
num++;
}
if (gpu_1)
{
num++;
}
return num;
}
void copy(GPU_Config tem)
{
this->gpu_0 = tem.gpu_0;
this->gpu_1 = tem.gpu_1;
}
};
// 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> CELL_Mark;
std::shared_ptr<AIModel_Base> CELL_Align;
std::shared_ptr<AIModel_Base> CELL_CA_Det;
std::shared_ptr<AIModel_Base> CELL_TA_Det;
std::shared_ptr<AIModel_Base> CELL_CA_Cls;
std::shared_ptr<AIModel_Base> CELL_TA_Cls;
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;
};
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,588 @@
/*
* @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"
AIModel_Impl::AIModel_Impl()
{
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_nLast_GPUStreamIdx = 0;
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.gpu_0)
{
re = LoadEngine(0);
// 加载失败
if (re != 0)
{
}
}
if (m_modelRun_Config.gpuconfig.gpu_1)
{
re = LoadEngine(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;
}
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
{
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 都放到一起,方便调用。
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);
}
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;
outimg = InitMat(m_pNode_output_0->channel, m_pNode_output_0->width, m_pNode_output_0->height);
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 (cudaStreamCreate(&cudasteam->stream) != 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;
}
}
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;
GetStream(pdetStream);
// printf("=== s2 ");
std::lock_guard<std::mutex> lock(pdetStream->AI_mutex);
// printf(" ss g %d s %d -- ", pdetStream->nGPUIdx, pdetStream->cuda_stream->nstreamIdx);
// // 设置 显卡ID
cudaSetDevice(pdetStream->nGPUIdx);
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)
{
int sidx = m_nLast_GPUStreamIdx;
sidx++;
if (sidx >= m_nALLStreamNum)
{
sidx = 0;
}
pdetStream = m_DetGPUStream.at(sidx);
m_nLast_GPUStreamIdx = 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;
GetStream(pdetStream);
// 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;
cudaSetDevice(pdetStream->nGPUIdx);
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,106 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-03 10:33:48
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-14 20:28:10
* @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 (!CELL_CA_Det)
{
CELL_CA_Det = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_CellAOI/Detect_CA.engine";
edge_config.strName = "CA_Det";
edge_config.inputType = AIModel_Base::Input_HWC;
edge_config.Stream_num = 2;
CELL_CA_Det->Init(edge_config);
}
if (!CELL_TA_Det)
{
CELL_TA_Det = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_CellAOI/Detect_TA.engine";
edge_config.strName = "TA_Det";
edge_config.inputType = AIModel_Base::Input_HWC;
edge_config.Stream_num = 2;
CELL_TA_Det->Init(edge_config);
}
if (!CELL_Align)
{
CELL_Align = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_CellAOI/Align.engine";
edge_config.strName = "Align";
edge_config.inputType = AIModel_Base::Input_HWC;
CELL_Align->Init(edge_config);
}
if (!CELL_Mark)
{
CELL_Mark = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_CellAOI/Cell_marker.engine";
edge_config.strName = "Mark";
edge_config.inputType = AIModel_Base::Input_HWC;
CELL_Mark->Init(edge_config);
}
if (!CELL_CA_Cls)
{
CELL_CA_Cls = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config jbl_config;
jbl_config.gpuconfig.copy(gupconfig);
jbl_config.strPath = "/home/aidlux/BOE/UseModel_CellAOI/Class_10.engine";
jbl_config.inputType = AIModel_Base::Input_HWC;
jbl_config.strName = "CA_Class";
jbl_config.IsClass = true;
CELL_CA_Cls->Init(jbl_config);
}
if (!CELL_TA_Cls)
{
CELL_TA_Cls = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config jbl_config;
jbl_config.gpuconfig.copy(gupconfig);
jbl_config.strPath = "/home/aidlux/BOE/UseModel_CellAOI/Class_10_TA.engine";
jbl_config.inputType = AIModel_Base::Input_HWC;
jbl_config.strName = "TA_Class";
jbl_config.IsClass = true;
CELL_TA_Cls->Init(jbl_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,157 @@
/*
* @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,88 @@
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
${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 SRC_LISTS
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cu
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.cpp
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.c
${PROJECT_SOURCE_DIR}/AIEngineModule/src/*.cu
)
add_library(TY_Check SHARED ${SRC_LISTS})
target_link_libraries(TY_Check
nvinfer
Config
${OpenCV_LIBS}
${CUDA_LIBRARIES}
)
set(ModuleName "")
# make install /usr/local
#
set(CMAKE_INSTALL_PREFIX /usr/local/cellAOI CACHE PATH "Install path prefix" FORCE)
set(HEADER_FILES include/ImgCheckBase.h include/ImgCheckConfig.h)
#
install(TARGETS TY_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,43 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-17 19:09:40
* @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_
// AI缺陷分类缺陷的种类
enum AI_CLass_QX_NAME_
{
AI_CLass_QX_NAME_aotudian, // 凹凸点
AI_CLass_QX_NAME_other, // 其他
AI_CLass_QX_NAME_line, // 线状
AI_CLass_QX_NAME_zangwu, // 脏污
AI_CLass_QX_NAME_dianzhuang, // 点状
AI_CLass_QX_NAME_posun, // 破损
AI_CLass_QX_NAME_xianwei, // 纤维
AI_CLass_QX_NAME_shuizi, // 水渍
AI_CLass_QX_NAME_danban, // 淡斑
AI_CLass_QX_NAME_fuchen, // 浮尘
AI_CLass_QX_NAME_count,
};
// 缺陷项对应在参数中的名称
static const std::string AI_CLass_QX_NAME_Names[] =
{
"aotudian",
"qx",
"line",
"zangwu",
"dianzhuang",
"posun",
"xianwei",
"shuizi",
"danban",
"fuchen",
};
#endif

@ -0,0 +1,236 @@
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#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 "CheckConfigDefine.h"
#include "ImageStorage.h"
#include "AI_Factory.h"
#include "DetLog.h"
using namespace std;
using namespace std;
using namespace cv;
class AI_Edge_Algin
{
public:
enum Mark_Result_Status
{
Mark_Result_Status_NULL,
Mark_Result_Status_OK,
Mark_Result_Status_Error,
};
struct MarK_Result
{
Mark_Result_Status status;
cv::Rect SearchROI_DetImg; // 相对于 检测图的 搜索区域;
cv::Point param_Local_DetImg; // mark的参数位置,相对于检测图片
cv::Point det_Local_DetImg; // 检测结果 相对于 检测图片
cv::Rect SearchROI_SrcImg; // 相对于 检测图的 搜索区域;
cv::Point param_Local_SrcImg; // mark的参数位置,相对于检测图片
cv::Point det_Local_SrcImg; // 检测结果 相对于 检测图片
MarK_Result()
{
status = Mark_Result_Status_NULL;
SearchROI_DetImg = cv::Rect(0, 0, 0, 0);
param_Local_DetImg = cv::Point(0, 0);
det_Local_DetImg = cv::Point(0, 0);
SearchROI_SrcImg = cv::Rect(0, 0, 0, 0);
param_Local_SrcImg = cv::Point(0, 0);
det_Local_SrcImg = cv::Point(0, 0);
}
};
// 边缘搜索定位结果
struct Edge_AI_Result
{
int nresult;
cv::Rect roi;
bool buseOfft;
int offt_x;
int offt_y;
cv::Mat H;
std::vector<MarK_Result> markresulList;
Edge_AI_Result()
{
Init();
}
void Init()
{
buseOfft = false;
nresult = 0;
offt_x = 0;
offt_y = 0;
roi = cv::Rect(0, 0, 0, 0);
markresulList.clear();
if (!H.empty())
{
H.release();
/* code */
}
}
};
enum SaveProcessType
{
Save_Close, // 不保存
Save_Filter, // 过滤的
Save_ALL, // 全部
};
/// @brief 检测过程的参数
struct DetConfig
{
int ncamId; // 相机ID
BaseCheckFunction *pBaseCheckFunction;
std::string strChannel; // 通道
int nthresholdvalue; // 背景阈值
int nAIErodesize; // 边缘腐蚀强度
bool bSaveResultImg; // 保存结果图片
SaveProcessType saveProcessImg; // 保存过程图片
bool bUseDrawRoi_Check; // 是否用绘制的ROI进行校验
cv::Rect drawRoi; // 绘制的 ROi;
cv::Mat drawMask; // 绘制的maksk
DetConfig()
{
Init();
}
void Init()
{
pBaseCheckFunction = NULL;
ncamId = 0;
nthresholdvalue = 1;
nAIErodesize = 7;
bSaveResultImg = 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(bSaveResultImg), 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(std::shared_ptr<DetLog>& log_ref);
~AI_Edge_Algin();
// 初始化检测模型
int Init(OtherDet_Config *pOtherDet_Config);
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);
// 利用mark 实现精确定位
int MarkAlign(const cv::Mat &img, DetConfig *pDetConfig, cv::Rect bigroi);
private:
int InitModel_Big();
int InitModel_Mark();
int Det_big(const cv::Mat &img, DetConfig *pDetConfig, std::string strChannel, cv::Rect &bigRoi);
int Det_MarkPoint(const cv::Mat &img, DetConfig *pDetConfig, cv::Rect bigroi, cv::Point SampleImg_Local);
int AnalsysMarkPoint(const cv::Mat &img, DetConfig *pDetConfig);
int creatsavedir();
private:
bool m_bInitSucc; // 是否初始化成功
// 检测结果
std::shared_ptr<Edge_AI_Result> m_pCheckResult_Aling;
OtherDet_Config *m_pOtherDet_Config;
DetConfig *m_pDetConfig;
std::shared_ptr<DetLog>& m_pdetlog;
bool m_bInitialized;
bool m_bModelSucc;
bool m_bModel_Mark_Succ;
bool m_bshowimg;
cv::Mat showimg;
std::string m_strRootPath_Big;
std::string m_strSavePath_Big;
std::string m_strRootPath_Mark;
std::string m_strSavePath_Mark;
std::string m_strLastDate;
ImageStorage *m_pImageStorage;
std::shared_ptr<AIFactory> AI_Factory;
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,176 @@
/*
* @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"
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();
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);
// 异常返回
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;
};
#endif

@ -0,0 +1,125 @@
#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;
float breadth;
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);
#ifdef __cplusplus
}
#endif

@ -0,0 +1,240 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-17 20:10:01
* @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"
using namespace std;
using namespace cv;
// 相机处理类
class CameraCheckAnalysisy
{
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 = 40;
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:
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 Mergimg(cv::Mat &img, const cv::Mat &img_B, std::string strcam, std::string strchannel);
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 Detect_Images();
// 结果参数分析
int ResultParamJudge();
// 边缘处理
int ImgEdge(cv::Mat img, cv::Mat &detMaskImg, cv::Rect &roi, int productIdx);
// 插入相机日志
int InsertCameraLog();
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能
// 预处理 字符检测
int preDet_ZF(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult);
// 获取 检测核心库
ImgCheckBase *GetDealResult(int idx = -1);
// 边缘点搜索函数
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);
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;
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; // 条件变量,是否有图片需要检查
private:
// 检测核心库
ImgCheckBase *m_pImgCheckAnalysisy[IMGCHECKANALYSISY_NUM];
CheckResultJson m_CheckResultJson;
private:
cv::Mat showimg;
bool bshowimg;
private:
};
#endif

@ -0,0 +1,74 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-16 21:20:28
* @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:
/* data */
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();
// 返回一个未检测的 图片进行检测
std::shared_ptr<ImageAllResult> GetNoDetImg();
long time_start;
bool bJson = false;
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;
};
#endif

@ -0,0 +1,285 @@
#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
// 输入模型图片尺寸
#define SRC_AI_In_IMAGE_WIDTH 800
#define SRC_AI_In_IMAGE_HEIGHT 800
// 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 AD_Channel_Info_
{
cv::Rect roi;
int num;
float fdis;
AD_Channel_Info_()
{
roi = cv::Rect(0, 0, 0, 0);
num = 0;
fdis = 999999999999;
}
};
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,80 @@
/*
* @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 int CalHjWeighted(const cv::Mat &img, const cv::Mat &mask, int b_value, float power = 2.0f);
// 计算平均灰度
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::Point p1, cv::Point 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,43 @@
/*
//定义整个系统基础的 定义 信息
*/
#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 2
// 相机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];
}
};
#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,151 @@
/*
* @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;
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());
}
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)
{
logList.push_back(str);
}
}
void printLog(std::string str)
{
printf("===========================%s==============================\n", str.c_str());
for (auto strl : logList)
{
printf("%s\n", strl.c_str());
}
printf("==========================================================\n");
}
};
#endif

@ -0,0 +1,252 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-13 16:05:08
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Edge_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-04 21:29:05
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Edge_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef Edge_QX_Det_H_
#define Edge_QX_Det_H_
#include <opencv2/opencv.hpp>
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
using namespace std;
using namespace cv;
// 边缘缺陷检测
class Edge_QX_Det
{
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 = 40;
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);
}
};
struct QX_Result
{
cv::Rect roi_src;
int area_pixel;
QX_Result()
{
roi_src = cv::Rect(0, 0, 0, 0);
area_pixel = 0;
}
};
// 检测小区域的信息
struct Det_ROI_Config
{
cv::Rect roi;
std::vector<cv::Point> plist;
};
struct Algin_Result
{
cv::Rect corpRoi;
int offtx;
int offty;
cv::Mat H;
Algin_Result()
{
Init();
}
void Init()
{
corpRoi = cv::Rect(0, 0, 0, 0);
offtx = 0;
offty = 0;
if (!H.empty())
{
H.release();
}
}
/* data */
};
// 检测参数和结果
struct DetConfigResult
{
BaseCheckFunction *pBaseCheckFunction;
std::string strChannel;
std::vector<QX_Result> qx_result;
std::vector<Det_ROI_Config> edge_det_roi;
Algin_Result alginResult;
std::vector<cv::Point> Det_region;
bool bSaveResultImg;
DetConfigResult()
{
Init();
}
void Init()
{
pBaseCheckFunction = NULL;
strChannel = "";
qx_result.clear();
edge_det_roi.clear();
alginResult.Init();
Det_region.clear();
bSaveResultImg = false;
}
};
enum Det_ROI_Type
{
Det_ROI_Type_UP,
Det_ROI_Type_DOWN,
Det_ROI_Type_LEFT,
Det_ROI_Type_RIGHT,
};
public:
bool GetSegmentIntersection(const Line &l1, const Line &l2, cv::Point2f &intersection);
Edge_QX_Det(/* args */);
~Edge_QX_Det();
int Detect(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
// 边缘点搜索函数
int GetEdgePoint(const cv::Mat &img, Edge_Search_Config *pEdge_Search_Config, std::vector<cv::Point> &pointList);
int GetLine(const cv::Mat &img, std::vector<cv::Point> &pointList, int lineNum, int xory, std::vector<Line> &lineList);
// 检测缺陷
int Det_qx(const cv::Mat &img, std::vector<Det_ROI_Config> roilist, Det_ROI_Type type, DetConfigResult *pDetConfig);
int applyMaskInROI(const cv::Mat &grayImg, const Det_ROI_Config &config, cv::Mat &result, int threshold);
// 通过手绘的方式来检测
int Draw_Det(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
/// @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);
private:
cv::Mat showimg;
bool bshowimg;
private:
/* data */
};
#endif

@ -0,0 +1,97 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-23 10:45:58
* @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;
};
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();
public:
// 裁切大小
cv::Rect CropRoi = cv::Rect(0, 0, 0, 0);
// 检测的原始图片
cv::Mat detImg;
// AI 推理的mask图片
cv::Mat AIMaskImg;
// 结果图片
cv::Mat resultImg;
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;
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::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,364 @@
#ifndef _ImageDetConfig_HPP_
#define _ImageDetConfig_HPP_
#include <string>
#include <opencv2/opencv.hpp>
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
#include "DetLog.h"
#define QX_SAMLLIMG_WIDTH 160
#define QX_SAMLLIMG_HEIGHT 160
// 缺陷结果信息
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;
float fbreadth;
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_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>();
}
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 ProductBaseResult
{
std::string strproductName = ""; // 产品 ID
std::shared_ptr<DetLog> detlog;
};
// 相机相关的 基础检测结果
struct CameraBaseResult
{
std::string strCameraName = ""; // 相机结果 ID
};
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,208 @@
/*
//图片基本处理
*/
#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"
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;
};
struct singleQxInfo{
int qxidx;
int ng_type;
cv::Point pcenter;
singleQxInfo(int qxidx, int ng_type, cv::Point pcenter):qxidx(qxidx),ng_type(ng_type),pcenter(pcenter){}
};
struct singleQxZoningInfo{
float scale_X;
float scale_Y;
float judge_dis;
int judge_num;
Point center;
vector<singleQxInfo> qxList;
void Init(){
scale_X = 0;
scale_Y = 0;
judge_dis = 0;
judge_num = 0;
center = Point(0, 0);
qxList.clear();
}
float calulateDisSquared(cv::Point pcenter){
float dx = (pcenter.x - center.x) * scale_X;
float dy = (pcenter.y - center.y) * scale_Y;
return (pow(dx, 2) + pow(dy, 2));
}
// 由距离来卡控添加缺陷并更新区域center坐标
bool Insert(singleQxInfo qxInfo){
if(qxList.size() == 0)
{
center = qxInfo.pcenter;
qxList.push_back(qxInfo);
return true;
}
else
{
if(calulateDisSquared(qxInfo.pcenter) < judge_dis * judge_dis)
{
center = Point((qxInfo.pcenter.x + center.x) / 2, (qxInfo.pcenter.y + center.y) / 2);
qxList.push_back(qxInfo);
return true;
}
else return false;
}
}
bool judgeNum(){
if(qxList.size() >= judge_num) return true;
else return false;
}
};
struct usenumQxZoningInfo{
vector<singleQxZoningInfo> singleQxZoningList;
};
struct ictQxZoningInfo{
vector<usenumQxZoningInfo> usenumQxZoningList;
};
struct iregionQxZoningInfo{
vector<ictQxZoningInfo> ictQxZoningList;
};
public:
ImageResultJudge(/* args */);
~ImageResultJudge();
int SetAnalysisyConfig(AnalysisyConfigST *pAnalysisyConfig);
int ResultJudge(std::shared_ptr<ImageAllResult> pImageResult);
int UpdateConfig();
int DrawResult(std::shared_ptr<ImageAllResult> pImageResult);
private:
// 获取 缺陷在参数列表的位置
int GetParamidx();
int UpdateImgageScale();
int addInDrawBlob(int errortype, int blobidx, QX_ERROR_INFO_ *QX_info, float fs_resize_x, float fs_resize_y);
// 参数缺陷类型转 结果参数类型
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();
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_;
};
#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,291 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:49:50
* @LastEditTime: 2025-09-17 19:49:41
* @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 "Edge_QX_Det.h"
#include "AI_Edge_Algin.h"
#include "AI_Factory.h"
#include "ImageAllResult.h"
#include "Task.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();
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 AI_Edge(const cv::Mat &img, cv::Rect &cutRoi);
// 计算产品尺寸
int CalProductSize();
// 图片预处理
int ImgPreDet();
// 设置新的检测参数
int SetNewConfig();
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 GetClassImg(const cv::Mat &img, cv::Mat &AIdetImg, cv::Rect qx_roi, int detwidth, int detheight);
// 计算缺陷长度
vector<float> Cal_QXLen(cv::Mat qx_maskImg, int qx_type, float fsc_x, float fsc_y);
// 获取检测结果blob用于后续分析。
int GetCheckResultBLob();
// 获得所有blob
int GetALLBlob();
// 对AI mask图片进行 结果处理
int AIMaskDet();
// 轮廓处理
int Contours();
// 检测初始化
int CheckImgInit();
// 参数 核对
int ConfigCheck(cv::Mat img);
// 多线程方式处理
int AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg);
// 缺陷分类
int AI_QX_Class_Thread();
// 多线程 任务运行管理器
int ThreadTask(int nId); // 运行;
// resize 图片
int ResizeImg();
// AI 推理任务函数
void TaskFun_AIDet(std::shared_ptr<TaskInfo> task);
// 缺陷分类任务函数
void TaskFun_QxClass(std::shared_ptr<TaskInfo> task);
// 更新 检测区域
int Update_DetRoiList();
// 临时绘制结果
int DrawResult_Step_1();
// 参数缺陷类型转 结果参数类型
int AIClassTypeToConfigType(int nAIQXType);
// 更新成像精度
int UpdateImgageScale();
// 边缘缺陷检测
int Edge_Qx_Det(const cv::Mat &img);
// 把blob 汇总成 检测结果。
int BLobToDetResult();
//自适应参数区域更新
int Adapt_Config(Mat img, Rect roi, bool b_update);
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;
bool m_bupdateconfig;
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_strCurDetChannel; // 当前处理的图片通道
// // 检测控制参数
// CheckControlConfigSt *m_pcheckControlConfig;
int m_nRun_Status; // 运行状态:空闲,运行中,异常,。。。。。
int m_nCheckResultErrorCode;
Detect_ROI_Config m_DetRoiList; // 检测区域roi List
ERROR_DOTS_BLOBS blobs;
OtherDet_Config m_OtherDet_Config;
AI_Edge_Algin m_pAI_Edge_Algin;
// 边缘定位结果
std::shared_ptr<AI_Edge_Algin::Edge_AI_Result> m_pEdge_Align_Result;
Edge_QX_Det m_Edge_QX_Det;
Edge_QX_Det::DetConfigResult m_Edge_DetConfig;
std::vector<QXImageResult> m_Draw_qxImageResult; // 缺陷小图结果
std::vector<cv::Rect> SmallRoiList;
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 推理的所有结果, 可能会返回去。需要临时存储。
std::queue<std::shared_ptr<AIMulThreadRunBase::AITask>> m_AIMaskImgBLobQueue;
std::mutex mtx_AIMaskImgBLobQueue;
Task m_task;
std::shared_ptr<TaskInfo> m_AItask;
std::shared_ptr<TaskInfo> m_Classtask; // 缺陷分类任务
// AI mask 在这一列是否有 缺陷残点,用以 加速 blob 分析。
unsigned char *m_ImgBlobHFlagData;
// 原始区域数据
Rect m_old_productROI = Rect(0, 0, 0, 0);
std::vector<cv::Point> m_old_cur_edgeDet_region;
std::vector<cv::Point> m_old_cur_markLine_region;
cv::Point m_old_cur_markLine_mark1;
cv::Point m_old_cur_markLine_mark2;
std::vector<RegionConfigST> m_old_cur_regionConfigArr;
};
#endif

@ -0,0 +1,94 @@
#ifndef ImgCheckBase_H_
#define ImgCheckBase_H_
#include <string>
#include <memory>
#define ALL_INTERFACE_VERSION 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
};
struct RunInfoST
{
int nThreadIdx; // 线程号id
int nDeviceId; // GPU 设备 号 0 或 1
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;
nCpu_start_Idx = 0;
nCpu_num = 8;
flag1 = 0;
flag2 = 0;
bRetest = false;
str1 = "";
str2 = "";
bSaveCheckImg = false;
}
void copy(RunInfoST tem)
{
this->nDeviceId = tem.nDeviceId;
this->nThreadIdx = tem.nThreadIdx;
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,460 @@
/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2022-03-16 17:09:11
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-23 10:15:49
*/
/***********************************************/
/************ ***************/
/************金佰利检测算法参数定义**************/
/************ **************/
/**********************************************/
#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, // 1 疑是
ERROR_TYPE_aotudian, // 2 凹凸点
ERROR_TYPE_other, // 3 其他
ERROR_TYPE_line, // 4 线状
ERROR_TYPE_zangwu, // 5 脏污
ERROR_TYPE_edge, // 6 边缘
ERROR_TYPE_ymhs, // 7 研磨划伤
ERROR_TYPE_dianzhuang, // 8 点状
ERROR_TYPE_posun, // 9 破损
ERROR_TYPE_xianwei, // 10 纤维
ERROR_TYPE_shuizi, // 11 水渍
ERROR_TYPE_danban, // 12 淡斑
ERROR_TYPE_fuchen, // 13 浮尘
ERROR_TYPE_COUNT,
};
extern std::vector<std::string> QX_Result_Names;
extern std::vector<std::string> QX_Result_Code;
// 检测检测参数类型
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_YX,
DET_MODE_UP,
DET_MODE_Det,
DET_MODE_MarkLine,
DET_MODE_ReJson,
};
#define MAX_REGION_NUM 20
struct ReadFlawCode
{
std::string flaw_name;
std::string flaw_code;
std::vector<std::string> config_flaw_name;
ReadFlawCode()
{
config_flaw_name.clear();
flaw_name = "";
flaw_code = "";
}
};
extern std::vector<ReadFlawCode> m_FlawCodeList;
// 一个检测项基本信息,包括图片序号,图片、开始时间
struct shareImage
{
int Det_Mode; // 检测模式
int Status;
bool bCam_AB; // 是AB两个相机
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;
int nImgBigIdx;
int otherValue;
int otherValue_1;
std::string resultJson; // 检测结果 json 字符串
bool bsaveProcessImg; // 保存处理图片
std::unordered_map<std::string, int> runCommand; // 运行命令 map
shareImage()
{
Init();
}
~shareImage()
{
}
void Init()
{
if (!img.empty())
{
img.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;
bCam_AB = false;
strImgName = "";
strCameraName = "";
strImgProductID = "";
strChannel = "";
nImgBigIdx = 0;
cutRoi = cv::Rect(0, 0, 0, 0);
otherValue = 0;
ninstruct = 0;
resultJson = "";
bsaveProcessImg = 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 breadth;
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;
breadth = 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,67 @@
/*
* @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();
void SetCheckEnd();
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;
std::string strEndTime;
long time_pushImg_end;
long time_CheckImg_end;
long product_UseAllTime;
};
#endif

@ -0,0 +1,96 @@
/*
* @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_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;
}
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,695 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-22 16:44:43
* @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"
#include <fstream>
std::vector<ReadFlawCode> m_FlawCodeList;
std::vector<std::string> QX_Result_Names =
{
"OK",
"aotudian",
"other",
"line",
"zangwu",
"edge",
"ymhs",
"dianzhuang",
"posun",
"xianwei",
"shuizi",
"danban",
"fuchen",
};
std::vector<std::string> QX_Result_Code =
{
"P0000",
"MA507",
"MA508",
"MA506",
"MA504",
"MA503",
"MA502",
"MA505",
"MA501",
"P0001",
"P0002",
"P0003",
"P0004",
};
int ReadFlawCodeConfig(std::string json_path)
{
m_FlawCodeList.erase(m_FlawCodeList.begin(), m_FlawCodeList.end());
std::string strPath = json_path;
printf("ReadFlawCodeConfig path %s\n", strPath.c_str());
Json::CharReaderBuilder builder;
builder["collectComments"] = true;
Json::Value root;
std::string err;
std::ifstream ifs(strPath);
if (!ifs.is_open())
{
printf("error:file is open\n");
return 0;
}
if (!Json::parseFromStream(builder, ifs, &root, &err))
{
printf("error:parseFromStream\n");
return 0;
}
for (int i = 0; i < root.size(); i++)
{
// printf("Node idx %d /%d \n", i, root.size());
ReadFlawCode tem;
tem.flaw_name = root[i]["zh_name"].asString();
tem.flaw_code = root[i]["en_name"].asString();
string desc = root[i]["desc"].asString();
{
std::istringstream stream(desc);
std::string token;
// 使用 getline 按照分号分割
while (std::getline(stream, token, ';'))
{
tem.config_flaw_name.push_back(token);
}
}
m_FlawCodeList.push_back(tem);
}
for(int i = 0; i < m_FlawCodeList.size(); i++)
{
if(i >= QX_Result_Names.size()) {
QX_Result_Names.push_back(m_FlawCodeList.at(i).flaw_name);
QX_Result_Code.push_back(m_FlawCodeList.at(i).flaw_code);
}
else
{
QX_Result_Names.at(i) = m_FlawCodeList.at(i).flaw_name;
QX_Result_Code.at(i) = m_FlawCodeList.at(i).flaw_code;
}
}
return 0;
}
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)
{
VERSION_INFO *pVersionconfig = (VERSION_INFO *)pconfig1;
if (pVersionconfig == NULL)
{
printf("**************************** \n");
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;
}
int re = 0;
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);
// 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;
gpu.gpu_0 = true;
gpu.gpu_1 = true;
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::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()
{
string defect_list_file = m_pConfigManager->GetJsonPath();
if (defect_list_file == "") {
defect_list_file = "/var/aidlux/efs/model/defect_list.json";
}
else{
defect_list_file += "/defect_list.json";
}
ReadFlawCodeConfig(defect_list_file);
m_pCameraCheckAnalysisyList.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;
}
if (m_pCameraCheckAnalysisyList.size() <= 0)
{
printf("ALLImgCheckAnalysisy::InitCameraCheckAnalysisy error camera config is null \n");
return 1;
/* code */
}
// for (const auto &pCameraCheckAnalysisy : m_pCameraCheckAnalysisyList)
// {
// std::cout << "key: " << pCameraCheckAnalysisy.first << std::endl;
// }
printf("ALLImgCheckAnalysisy::InitCameraCheckAnalysisy end \n");
return 0;
}
int ALLImgCheckAnalysisy::InitData()
{
return 0;
}
int ALLImgCheckAnalysisy::Det_Product(std::shared_ptr<Product> &product)
{
// 处理每个相机
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);
SetProductResult(product);
product->SetCheckEnd();
string cur_time = CheckUtil::getCurTimeHMS();
printf("[%s]>>>>>>>>>>>>>>>Det_Product****************det End************\n", cur_time.c_str());
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;
}
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;
std::string strBase = "";
strBase += " PushInImg->SN:";
strBase += p->strImgProductID;
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->strCameraName;
cout << "strcameraName: " << strcameraName << endl;
if(m_pCameraCheckAnalysisyList.size() <= 0){
cout << "m_pCameraCheckAnalysisyList.size(): " << m_pCameraCheckAnalysisyList.size() << endl;
}
for (auto it = m_pCameraCheckAnalysisyList.begin(); it != m_pCameraCheckAnalysisyList.end(); ++it) {
std::cout << "m_pCameraCheckAnalysisyList_Key: " << it->first << std::endl;
}
// 判断 相机名称是否存在
if (!m_pCameraCheckAnalysisyList.count(strcameraName) && -1 != p->Status)
{
return CHECK_ERROR_Camear_ID_Error;
}
product = GetProduct(p->strImgProductID);
bool ProductID_Exist = false; // 是否存在当前产品ID
if (product)
{
ProductID_Exist = true;
}
// 产品存在 并且 模式 是第一张图, 则,返回异常。
if (IN_IMG_Status_Start == p->Status && ProductID_Exist)
{
return CHECK_ERROR_PRODUCT_ID_EXIST;
}
// 产品存在,但是 图片都已经完了的状态
if (ProductID_Exist && product->bIsImgComplete)
{
ErrorReturn(p);
return CHECK_ERROR_PRODUCT_ID_EXIST;
}
// 产品不存在 新建一个
if (!product)
{
std::lock_guard<std::mutex> lock(mtx_ProductList);
{
if (m_ProductList.size() > 5)
{
return CHECK_ERROR_PushImg_ListSize;
}
}
product = std::make_shared<Product>();
product->productBaseResult->strproductName = p->strImgProductID;
m_ProductList.push_back(product);
std::string strTimg = CheckUtil::getCurTimeHMS();
product->productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "add new product %s %s ", p->strImgProductID.c_str(), strTimg.c_str());
}
// 送入图的状态 不是结束
if (-1 != p->Status)
{
// 对应相机的 检测结果
std::shared_ptr<CameraResult> pCamera = product->GetCameraResult(strcameraName);
if (pCamera.get() == nullptr)
{
ErrorReturn(p);
return CHECK_ERROR_Camear_ID_Error;
}
// 添加产品信息
pCamera->AddDetImage(p);
}
product->UpdatePushStatus(p->Status);
if (-1 == p->Status || IN_IMG_Status_End == p->Status)
{
m_strTest += "\n";
product->AddLog(m_strTest);
m_strTest = "";
}
ProductList_cond.notify_all();
}
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;
}

@ -0,0 +1,979 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "BlobBase.h"
void pretest(double x)
{
printf("fff %f \n", x);
}
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
static inline int GetType(int nvalue, int *qx_list)
{
// int re = 0;
// if ((nvalue & Value_ERR_TYPE_1) != 0)
// {
// re = 1;
// qx_list[ERR_TYPE_1] = 1;
// }
// else
// {
// qx_list[ERR_TYPE_1] = 0;
// }
// if ((nvalue & Value_ERR_TYPE_2) != 0)
// {
// re = 1;
// qx_list[ERR_TYPE_2] = 1;
// }
// else
// {
// qx_list[ERR_TYPE_2] = 0;
// }
// return re;
qx_list[ERR_TYPE_1] = !!(nvalue & Value_ERR_TYPE_1);
qx_list[ERR_TYPE_2] = !!(nvalue & Value_ERR_TYPE_2);
return qx_list[ERR_TYPE_1] | qx_list[ERR_TYPE_2];
}
//-------------sxg added
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)
{
if (curRow->scanCount < _MAX_ERROR_SCAN_LINE_PER_ROW)
{
int lastScanLineIndex = curRow->scanCount++;
ERROR_DOTS_SCAN_DATA *scan = curRow->errorScanLineTab + lastScanLineIndex;
scan->x = x;
scan->count = len;
int ex = x + len - 1;
scan->energy = difSum;
scan->area = scan->count;
scan->xposSum = (x + (len >> 1)) * len;
scan->yposSum = y * len;
scan->minx = x;
scan->miny = y;
scan->maxx = ex;
scan->maxy = y;
scan->macro = mdx;
for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
{
scan->ErrClass[ec] = pErrClass[ec];
}
curRow->macro[scan->macro] = len;
int linkIndexTab[_MAX_ERROR_SCAN_LINE_PER_ROW];
int linkCount = 0;
if (prevRow)
{
for (int t = 0; t < _MAX_MACRO_COUNT; t++)
{
curRow->macro[t] += prevRow->macro[t];
// prevRow->macro[t]=0;
}
int prevLastScanLineIndex = prevRow->scanCount - 1;
ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex;
for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan)
{
int psx = pscan->x - 1;
int pex = psx + pscan->count - 1 + 1;
// sxg modified waitting for valid 9.5
if (x <= pex && ex >= psx)
{
if (pscan->area > 0)
{
int area = scan->area + (pscan->area);
scan->area = area;
if (scan->macro != pscan->macro)
{
if (scan->macro < pscan->macro)
scan->macro = pscan->macro;
}
scan->energy += pscan->energy;
scan->xposSum += pscan->xposSum;
scan->yposSum += pscan->yposSum;
scan->minx = min(scan->minx, pscan->minx);
scan->miny = min(scan->miny, pscan->miny);
scan->maxx = max(scan->maxx, pscan->maxx);
scan->maxy = max(scan->maxy, pscan->maxy);
pscan->area = 0;
pscan->energy = lastScanLineIndex;
for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
{
scan->ErrClass[ec] = pErrClass[ec] + (pscan->ErrClass[ec]);
}
linkIndexTab[/*0xff & */ (linkCount++)] = prevLastScanLineIndex;
}
// else
//{
// int bindex = 0xff & pscan->energy;
// ERROR_DOTS_SCAN_DATA * hscan = curRow->errorScanLineTab + bindex;
// hscan->count = ex - hscan->x + 1;
// hscan->area += scan->area;
// hscan->energy += scan->energy;
// hscan->xposSum += scan->xposSum;
// hscan->yposSum += scan->yposSum;
// hscan->minx = min(scan->minx , hscan->minx);
// hscan->miny = min(scan->miny , hscan->miny);
// hscan->maxx = max(scan->maxx , hscan->maxx);
// hscan->maxy = max(scan->maxy , hscan->maxy);
// scan->area = 0;
// for(;linkCount > 0 ; --linkCount)
// {
// ERROR_DOTS_SCAN_DATA * p = prevRow->errorScanLineTab + linkIndexTab[0xff & (linkCount - 1)];
// p->energy = bindex;
// }
// curRow->scanCount--;
// break;
// }
}
}
}
}
}
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)
{
if (prevRow)
{
int prevLastScanLineIndex = prevRow->scanCount - 1;
ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex;
// int minArea = param->minArea;
// int minEnergy = param->minEnergy;
for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan)
{
if (pscan->area > 0)
{
int x = pscan->xposSum / pscan->area + sx;
int y = pscan->yposSum / pscan->area + sy;
int minx = pscan->minx + sx;
int miny = pscan->miny + sy;
int maxx = pscan->maxx + sx;
int maxy = pscan->maxy + sy;
if (x < width)
{
int blobIndex = blobs->blobCount;
// int mergeDistance = param->mergeDistance;
ERROR_DOTS_BLOB_DATA *pblob = blobs->blobTab + blobIndex - 1;
int left = minx - mergeDistanceX, right = maxx + mergeDistanceX;
int top = miny - mergeDistanceY, bottom = maxy + mergeDistanceY;
for (int i = blobIndex - 1; i >= 0; --i, --pblob)
{
if (1)
{
if (pblob->maxy > top && pblob->miny < bottom)
{
if (pblob->maxx > left && pblob->minx < right)
{
int area = pblob->area + pscan->area;
pblob->x = (pblob->x * pblob->area + x * pscan->area) / area;
pblob->y = (pblob->y * pblob->area + y * pscan->area) / area;
pblob->area = area;
for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
{
pblob->ErrClass[ec] += pscan->ErrClass[ec];
}
pblob->energy += pscan->energy;
pblob->minx = min(pblob->minx, minx);
pblob->miny = min(pblob->miny, miny);
pblob->maxx = max(pblob->maxx, maxx);
pblob->maxy = max(pblob->maxy, maxy);
pblob->macro[pscan->macro] += prevRow->macro[pscan->macro];
prevRow->macro[pscan->macro] -= pscan->area;
blobIndex = _MAX_ERROR_DOT_BLOB;
break;
}
}
}
}
if (pscan->area > minArea /*|| pscan->energy > minEnergy*/)
{
if (blobIndex < _MAX_ERROR_DOT_BLOB)
{
pblob = blobs->blobTab + blobIndex;
pblob->x = x;
pblob->y = y;
pblob->area = pscan->area;
pblob->energy = pscan->energy;
pblob->minx = minx;
pblob->miny = miny;
pblob->maxx = maxx;
pblob->maxy = maxy;
blobs->blobCount++;
for (int t = 0; t < _MAX_MACRO_COUNT; t++)
{
pblob->macro[t] = 0;
}
pblob->macro[pscan->macro] = pscan->area;
prevRow->macro[pscan->macro] -= pscan->area;
// prevRow->macro[pscan->macro]=0;
for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
{
pblob->ErrClass[ec] = pscan->ErrClass[ec];
}
}
}
}
}
pscan->area = 0;
for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
{
pscan->ErrClass[ec] = 0;
}
}
// for (int t=0;t<MAX_MACRO_COUNT;t++)
//{
// //curRow->macro[t]+=prevRow->macro[t];
// prevRow->macro[t]=0;
// }
}
}
void MergeBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOB_PARAM *param)
{
int count = blobs->blobCount;
ERROR_DOTS_BLOB_DATA *blob = blobs->blobTab + count - 1;
int pace = param->mergeDistance;
for (int i = count - 1; i > 0; --i, --blob)
{
int minx = blob->minx;
int miny = blob->miny;
int maxx = blob->maxx;
int maxy = blob->maxy;
int energy = blob->energy;
int left = minx - pace, right = maxx + pace;
int top = miny - 1, bottom = maxy + 1;
ERROR_DOTS_BLOB_DATA *pblob = blob - 1;
for (int j = i - 1; j >= 0; --j, --pblob)
{
if (pblob->ErrType == blob->ErrType)
{
if (pblob->maxy > top && pblob->miny < bottom)
{
if (pblob->maxx > left && pblob->minx < right)
{
int areaSum = pblob->area + blob->area;
int x = blob->x, y = blob->y;
pblob->x = (pblob->x * pblob->area + x * blob->area) / areaSum;
pblob->y = (pblob->y * pblob->area + y * blob->area) / areaSum;
pblob->area = areaSum;
for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
{
pblob->ErrClass[ec] += blob->ErrClass[ec];
}
pblob->energy += energy;
pblob->minx = min(pblob->minx, minx);
pblob->miny = min(pblob->miny, miny);
pblob->maxx = max(pblob->maxx, maxx);
pblob->maxy = max(pblob->maxy, maxy);
for (int t = 0; t < _MAX_MACRO_COUNT; t++)
{
pblob->macro[t] += blob->macro[t];
blob->macro[t] = 0;
}
count--;
memmove(blob, blob + 1, (count - i) * sizeof(blob[0]));
break;
}
}
}
}
}
blobs->blobCount = count;
}
// static int __cdecl compareBlob(const void * p1, const void * p2)
static int compareBlob(const void *p1, const void *p2)
{
ERROR_DOTS_BLOB_DATA *b1 = (ERROR_DOTS_BLOB_DATA *)p1;
ERROR_DOTS_BLOB_DATA *b2 = (ERROR_DOTS_BLOB_DATA *)p2;
return (b2->area) - (b1->area);
}
void SortBlob(ERROR_DOTS_BLOBS *blobs)
{
int count = blobs->blobCount;
ERROR_DOTS_BLOB_DATA *blob = blobs->blobTab;
qsort(blob, count, sizeof(blob[0]), compareBlob);
}
// 当前行和前面行合并
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)
{
if (curRow->scanCount < _MAX_ERROR_SCAN_LINE_PER_ROW)
{
int lastScanLineIndex = curRow->scanCount++;
ERROR_DOTS_SCAN_DATA *scan = curRow->errorScanLineTab + lastScanLineIndex;
scan->x = x;
scan->count = len;
int ex = x + len - 1;
scan->energy = difSum;
scan->area = scan->count;
scan->xposSum = (x + (len >> 1)) * len;
scan->yposSum = y * len;
scan->minx = x;
scan->miny = y;
scan->maxx = ex;
scan->maxy = y;
scan->type = errorType;
if (prevRow)
{
int prevLastScanLineIndex = prevRow->scanCount - 1;
ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex;
for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan)
{
int psx = pscan->x - 1;
int pex = psx + pscan->count - 1 + 1;
if (x <= pex && ex >= psx && pscan->type == scan->type)
{
if (pscan->area > 0)
{
int area = scan->area + (pscan->area);
scan->area = area;
scan->energy += pscan->energy;
scan->xposSum += pscan->xposSum;
scan->yposSum += pscan->yposSum;
scan->minx = min(scan->minx, pscan->minx);
scan->miny = min(scan->miny, pscan->miny);
scan->maxx = max(scan->maxx, pscan->maxx);
scan->maxy = max(scan->maxy, pscan->maxy);
pscan->area = 0;
pscan->energy = lastScanLineIndex;
}
}
}
}
}
}
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)
{
if (prevRow)
{
int prevLastScanLineIndex = prevRow->scanCount - 1;
ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex;
// int minArea = param->minArea;
// int minEnergy = param->minEnergy;
for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan)
{
if (pscan->area > 0)
{
int x = pscan->xposSum / pscan->area + sx;
int y = pscan->yposSum / pscan->area + sy;
int minx = pscan->minx + sx;
int miny = pscan->miny + sy;
int maxx = pscan->maxx + sx;
int maxy = pscan->maxy + sy;
if (x < width)
{
int blobIndex = blobs->blobCount;
// int mergeDistance = param->mergeDistance;
ERROR_DOTS_BLOB_DATA *pblob = blobs->blobTab + blobIndex - 1;
int left = minx - mergeDistanceX, right = maxx + mergeDistanceX;
int top = miny - mergeDistanceY, bottom = maxy + mergeDistanceY;
for (int i = blobIndex - 1; i >= 0; --i, --pblob)
{
if (pblob->ErrType == pscan->type)
{
if (pblob->maxy > top && pblob->miny < bottom)
{
if (pblob->maxx > left && pblob->minx < right)
{
int area = pblob->area + pscan->area;
pblob->x = (pblob->x * pblob->area + x * pscan->area) / area;
pblob->y = (pblob->y * pblob->area + y * pscan->area) / area;
pblob->area = area;
// for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
// {
// pblob->ErrClass[ec] += pscan->ErrClass[ec];
// }
pblob->energy += pscan->energy;
pblob->minx = min(pblob->minx, minx);
pblob->miny = min(pblob->miny, miny);
pblob->maxx = max(pblob->maxx, maxx);
pblob->maxy = max(pblob->maxy, maxy);
// pblob->macro[pscan->macro] += prevRow->macro[pscan->macro];
// prevRow->macro[pscan->macro] -= pscan->area;
blobIndex = _MAX_ERROR_DOT_BLOB;
break;
}
}
}
}
if (pscan->area > minArea /*|| pscan->energy > minEnergy*/)
{
if (blobIndex < _MAX_ERROR_DOT_BLOB)
{
pblob = blobs->blobTab + blobIndex;
pblob->x = x;
pblob->y = y;
pblob->area = pscan->area;
pblob->energy = pscan->energy;
pblob->ErrType = pscan->type;
pblob->minx = minx;
pblob->miny = miny;
pblob->maxx = maxx;
pblob->maxy = maxy;
blobs->blobCount++;
// for (int t = 0; t < _MAX_MACRO_COUNT; t++)
// {
// pblob->macro[t] = 0;
// }
// pblob->macro[pscan->macro] = pscan->area;
// prevRow->macro[pscan->macro] -= pscan->area;
// prevRow->macro[pscan->macro]=0;
// for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
// {
// pblob->ErrClass[ec] = pscan->ErrClass[ec];
// }
}
}
}
}
pscan->area = 0;
for (int ec = 0; ec < _MAX_ERR_CLASS; ec++)
{
pscan->ErrClass[ec] = 0;
}
}
// for (int t=0;t<MAX_MACRO_COUNT;t++)
//{
// //curRow->macro[t]+=prevRow->macro[t];
// prevRow->macro[t]=0;
// }
}
}
int GetBlobs_V2(ERROR_DOTS_BLOBS *blobs, unsigned char *pImgdata, unsigned char *pErrordata, int width, int height, int basev, int minArea)
{
if (blobs == NULL || pErrordata == NULL)
{
return 1;
}
int pitch = width;
int offset;
int point_is_err = 0;
int wLineErrsList = 0;
int errPos_xList = 0;
int difSumList = 0;
int point_is_errList = 0;
// memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_SCAN_ROW rowDataTab[2];
ERROR_DOTS_SCAN_ROW *curRow = 0;
ERROR_DOTS_SCAN_ROW *prevRow = 0;
int MIN_AREA = minArea;
if (minArea <= 0)
{
MIN_AREA = 10;
}
int minEnergy = 2;
int mergeDistanceX = 1;
int mergeDistanceY = 1;
offset = 0;
int nErrorType = 0;
int lasttype = -1;
for (int y = 0; y < height; y++)
{
wLineErrsList = 0;
difSumList = 0;
curRow = rowDataTab + (y & 1);
curRow->scanCount = 0;
offset = y * pitch - 1;
nErrorType = -1;
lasttype = -1;
int kh = 0;
for (int x = 0; x < width; x++)
{
offset++;
point_is_err = 0;
if (pErrordata[offset] != 0 && pImgdata[offset] > basev)
{
point_is_err = 1;
difSumList += 1;
wLineErrsList++;
errPos_xList = x;
kh = 1;
}
else // 没有残点 所有缺陷都需要判断是否截止
{
// 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
wLineErrsList = 0;
difSumList = 0;
}
kh = 0;
}
if (x == width - 1)
{
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
}
}
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
prevRow = curRow;
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
ERROR_DOTS_BLOB_PARAM blobParam;
memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM));
blobParam.mergeDistance = 1;
MergeBlob(blobs, &blobParam);
SortBlob(blobs);
return 0;
}
int GetBlobs_V3(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, int width, int height, int minArea)
{
if (blobs == NULL || pErrordata == NULL)
{
return 1;
}
int pitch = width;
int offset;
int point_is_err = 0;
int wLineErrsList = 0;
int errPos_xList = 0;
int difSumList = 0;
int point_is_errList = 0;
// memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_SCAN_ROW rowDataTab[2];
ERROR_DOTS_SCAN_ROW *curRow = 0;
ERROR_DOTS_SCAN_ROW *prevRow = 0;
int MIN_AREA = minArea;
if (minArea <= 0)
{
MIN_AREA = 10;
}
int minEnergy = 2;
int mergeDistanceX = 20;
int mergeDistanceY = 20;
offset = 0;
int nErrorType = 0;
int lasttype = -1;
for (int y = 0; y < height; y++)
{
wLineErrsList = 0;
difSumList = 0;
curRow = rowDataTab + (y & 1);
curRow->scanCount = 0;
offset = y * pitch - 1;
nErrorType = -1;
lasttype = -1;
int kh = 0;
for (int x = 0; x < width; x++)
{
offset++;
point_is_err = 0;
if (pErrordata[offset] != 0)
{
point_is_err = 1;
difSumList += 1;
wLineErrsList++;
errPos_xList = x;
kh = 1;
}
else // 没有残点 所有缺陷都需要判断是否截止
{
// 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
wLineErrsList = 0;
difSumList = 0;
}
kh = 0;
}
if (x == width - 1)
{
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
}
}
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
prevRow = curRow;
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
ERROR_DOTS_BLOB_PARAM blobParam;
memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM));
blobParam.mergeDistance = 1;
MergeBlob(blobs, &blobParam);
SortBlob(blobs);
return 0;
}
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)
{
if (blobs == NULL || pErrordata == NULL)
{
return 1;
}
int pitch = width;
int offset;
int point_is_err = 0;
int wLineErrsList = 0;
int errPos_xList = 0;
int difSumList = 0;
int point_is_errList = 0;
// memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_SCAN_ROW rowDataTab[2];
ERROR_DOTS_SCAN_ROW *curRow = 0;
ERROR_DOTS_SCAN_ROW *prevRow = 0;
int MIN_AREA = minArea;
if (minArea <= 0)
{
MIN_AREA = 10;
}
int minEnergy = 2;
int mergeDistanceX = 20;
int mergeDistanceY = 20;
offset = 0;
int nErrorType = 0;
int lasttype = -1;
for (int y = 0; y < height; y++)
{
wLineErrsList = 0;
difSumList = 0;
curRow = rowDataTab + (y & 1);
curRow->scanCount = 0;
offset = y * pitch - 1;
nErrorType = -1;
lasttype = -1;
int kh = 0;
for (int x = 0; x < width; x++)
{
offset++;
point_is_err = 0;
if (pErrordata[offset] == err_1_value || pErrordata[offset] == err_2_value)
{
point_is_err = 1;
difSumList += 1;
wLineErrsList++;
errPos_xList = x;
kh = 1;
}
else // 没有残点 所有缺陷都需要判断是否截止
{
// 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
wLineErrsList = 0;
difSumList = 0;
}
kh = 0;
}
if (x == width - 1)
{
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
}
}
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
prevRow = curRow;
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
ERROR_DOTS_BLOB_PARAM blobParam;
memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM));
blobParam.mergeDistance = 1;
MergeBlob(blobs, &blobParam);
SortBlob(blobs);
return 0;
}
int GetBlobs_ALL_New(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, unsigned char *pHdata, int width, int height, int minArea)
{
if (blobs == NULL || pErrordata == NULL || pHdata == NULL)
{
return 1;
}
int pitch = width;
int offset;
int point_is_err = 0;
int wLineErrsList[ERR_TYPE_COUNT] = {0};
int errPos_xList[ERR_TYPE_COUNT] = {0};
int difSumList[ERR_TYPE_COUNT] = {0};
memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_SCAN_ROW rowDataTab[2];
ERROR_DOTS_SCAN_ROW *curRow = 0;
ERROR_DOTS_SCAN_ROW *prevRow = 0;
// int MIN_AREA = 2;
int MIN_AREA = minArea;
if (minArea <= 0)
{
MIN_AREA = 10;
}
int minEnergy = 2;
int mergeDistanceX = 25;
int mergeDistanceY = 25;
offset = 0;
int nErrorType = 0;
int lasttype = -1;
int qx_list[ERR_TYPE_COUNT] = {0};
int kv = 0;
for (int y = 0; y < height; y++)
{
if (kv == 1)
{
memset(&wLineErrsList, 0, sizeof(int) * ERR_TYPE_COUNT);
memset(&difSumList, 0, sizeof(int) * ERR_TYPE_COUNT);
}
unsigned char *p = pErrordata + y * pitch;
curRow = rowDataTab + (y & 1);
curRow->scanCount = 0;
offset = y * pitch;
nErrorType = -1;
lasttype = -1;
kv = 0;
// 表示 这一行缺陷残点
if (pHdata[y])
{
for (int x = 0; x < width; x++, p++)
{
point_is_err = 0;
if (*p)
{
point_is_err = GetType(*p, qx_list);
kv = 1;
for (int qx_i = 0; qx_i < ERR_TYPE_COUNT; qx_i++)
{
if (qx_list[qx_i] > 0)
{
difSumList[qx_i] += 1;
wLineErrsList[qx_i]++;
errPos_xList[qx_i] = x;
}
}
}
else if (kv == 1) // 这一行有残点
{
for (int qx_i = 0; qx_i < ERR_TYPE_COUNT; qx_i++)
{
if (wLineErrsList[qx_i] > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList[qx_i] - wLineErrsList[qx_i] + 1, wLineErrsList[qx_i], y, difSumList[qx_i], 0, 0, qx_i);
wLineErrsList[qx_i] = 0;
difSumList[qx_i] = 0;
}
if (!wLineErrsList[ERR_TYPE_1] && !wLineErrsList[ERR_TYPE_2])
{
kv = 0;
}
}
}
if (x == width - 1)
{
for (int qx_i = 0; qx_i < ERR_TYPE_COUNT; qx_i++)
{
if (wLineErrsList[qx_i] > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList[qx_i] - wLineErrsList[qx_i] + 1, wLineErrsList[qx_i], y, difSumList[qx_i], 0, 0, qx_i);
}
}
}
// offset++;
}
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
prevRow = curRow;
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
ERROR_DOTS_BLOB_PARAM blobParam;
memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM));
blobParam.mergeDistance = 1;
blobs->srcBlobCount = blobs->blobCount;
MergeBlob(blobs, &blobParam);
SortBlob(blobs);
return 0;
}
int GetBlobs_oneLabe(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, unsigned char *pHdata, int width, int height, int minArea)
{
if (blobs == NULL || pErrordata == NULL || pHdata == NULL)
{
return 1;
}
int pitch = width;
int offset;
int point_is_err = 0;
int wLineErrsList = 0;
int errPos_xList = 0;
int difSumList = 0;
int point_is_errList = 0;
// memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_SCAN_ROW rowDataTab[2];
ERROR_DOTS_SCAN_ROW *curRow = 0;
ERROR_DOTS_SCAN_ROW *prevRow = 0;
int MIN_AREA = minArea;
if (minArea <= 0)
{
MIN_AREA = 10;
}
int minEnergy = 2;
int mergeDistanceX = 20;
int mergeDistanceY = 20;
offset = 0;
int nErrorType = 0;
int lasttype = -1;
for (int y = 0; y < height; y++)
{
wLineErrsList = 0;
difSumList = 0;
curRow = rowDataTab + (y & 1);
curRow->scanCount = 0;
offset = y * pitch - 1;
nErrorType = -1;
lasttype = -1;
int kh = 0;
// 表示 这一行缺陷残点
if (pHdata[y])
{
for (int x = 0; x < width; x++)
{
offset++;
point_is_err = 0;
if (pErrordata[offset] != 0)
{
point_is_err = 1;
difSumList += 1;
wLineErrsList++;
errPos_xList = x;
kh = 1;
}
else // 没有残点 所有缺陷都需要判断是否截止
{
// 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
wLineErrsList = 0;
difSumList = 0;
}
kh = 0;
}
if (x == width - 1)
{
if (wLineErrsList > 0)
{
AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1);
}
}
}
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
prevRow = curRow;
}
LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width);
ERROR_DOTS_BLOB_PARAM blobParam;
memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM));
blobParam.mergeDistance = 1;
blobs->srcBlobCount = blobs->blobCount;
MergeBlob(blobs, &blobParam);
SortBlob(blobs);
return 0;
}
int PushBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOBS *addblobs)
{
for (int i = 0; i < addblobs->blobCount; i++)
{
int bhave = 0;
for (int j = 0; j < addblobs->blobCount; j++)
{
if (addblobs->blobTab[i].ErrType == blobs->blobTab[j].ErrType &&
addblobs->blobTab[i].minx == blobs->blobTab[j].minx &&
addblobs->blobTab[i].miny == blobs->blobTab[j].miny &&
addblobs->blobTab[i].maxx == blobs->blobTab[j].maxx &&
addblobs->blobTab[i].maxy == blobs->blobTab[j].maxy)
{
bhave = 1;
break;
}
}
if (!bhave)
{
int ncount = blobs->blobCount;
if (ncount < _MAX_ERROR_DOT_BLOB)
{
memcpy(&blobs->blobTab[ncount], &addblobs->blobTab[i], sizeof(ERROR_DOTS_BLOB_DATA));
blobs->blobCount++;
}
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,110 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-13 20:39:37
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-17 16:39:47
* @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);
cameraImage_Status.bHaveImg = true;
cameraImage_Status.bHave_L255 = true;
}
std::string strTimg = CheckUtil::getCurTimeHMS();
detlog->AddCheckstr(PrintLevel_0, "PushInImg", " product %s Cam %s add new image channel = %s %s",
productBaseResult->strproductName.c_str(),
cameraBaseResult->strCameraName.c_str(), imgResult->strChannel.c_str(), 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;
}
std::shared_ptr<ImageAllResult> CameraResult::GetNoDetImg()
{
std::lock_guard<std::mutex> lock_cam(mtx_DetImageList);
for (auto ptr : ImageALLDetResultList)
{
if (ptr->IsNotDet())
{
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,169 @@
#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;
Json::Value root = toJsonValue();
Json::StreamWriterBuilder writerBuilder;
std::string jsonString = Json::writeString(writerBuilder, root);
return jsonString;
}

@ -0,0 +1,658 @@
/*
* 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);
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];
}
int CheckUtil::CalHjWeighted(const cv::Mat &img, const cv::Mat &mask, int b_value, float power)
{
cv::Mat imgf;
if (img.type() != CV_32F)
img.convertTo(imgf, CV_32F);
else
imgf = img;
cv::Mat absDiff = cv::abs(imgf - b_value);
cv::Mat weight;
cv::pow(absDiff, power, weight);
cv::Mat maskedDiff, maskedWeight;
absDiff.copyTo(maskedDiff, mask);
weight.copyTo(maskedWeight, mask);
cv::Scalar weightedSum = cv::sum(maskedDiff.mul(weight));
cv::Scalar weightSum = cv::sum(maskedWeight);
if (weightSum[0] < 1e-6)
return 0;
return static_cast<int>(weightedSum[0] / weightSum[0]);
}
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::Point p1, cv::Point 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,117 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-13 20:39:37
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-23 14:29: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 "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;
}
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;
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();
}

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,98 @@
/*
* @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"
Product::Product(/* args */)
{
productBaseResult = std::make_shared<ProductBaseResult>();
productBaseResult->detlog = std::make_shared<DetLog>();
}
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;
}
}
// 不存在,创建新的 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", "add new Camera %s ", strcameraName.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)
{
ptr->setImgPushComplate();
}
std::string strTimg = CheckUtil::getCurTimeHMS();
strEndTime = strTimg;
time_pushImg_end = CheckUtil::getcurTime();
productBaseResult->detlog->AddCheckstr(PrintLevel_0, "PushInImg", "%s Add ALL img end %s ", productBaseResult->strproductName.c_str(), strTimg.c_str());
}
}
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;
}
void Product::SetCheckEnd() {
time_CheckImg_end = CheckUtil::getcurTime();
product_UseAllTime = time_CheckImg_end - time_pushImg_end;
std::string strTimg = CheckUtil::getCurTimeHMS();
productBaseResult->detlog->AddCheckstr(PrintLevel_0, "Product", "Product Usetime %ld ms,start %s end %s",\
product_UseAllTime, strEndTime.c_str(), strTimg.c_str());
}

@ -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,75 @@
#CMake
cmake_minimum_required (VERSION 3.5)
project(rootproject)
set(CHECK_WORK_Value "POL_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(ExtractImageModule)
MESSAGE("ExtractImageModule")
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/polet 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,92 @@
/*
* @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;
virtual std::string GetJsonPath() = 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,44 @@
/*
* @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>
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);
std::string GetJsonPath();
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,223 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-13 18:52:55
* @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)
{
std::lock_guard<std::mutex> lock(mutex_status);
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,222 @@
/*
* @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"
#include "../../AlgorithmModule/include/ImgCheckConfig.h"
ConfigManager::ConfigManager()
{
m_strConfigRootPath = "";
}
ConfigManager::~ConfigManager()
{
}
std::vector<std::string> QX_Result_Names =
{
"OK",
"aotudian",
"other",
"line",
"zangwu",
"edge",
"ymhs",
"dianzhuang",
"posun",
"xianwei",
"shuizi",
"danban",
"fuchen",
};
std::vector<std::string> QX_Result_Code =
{
"P0000",
"MA507",
"MA508",
"MA506",
"MA504",
"MA503",
"MA502",
"MA505",
"MA501",
"P0001",
"P0002",
"P0003",
"P0004",
};
int ReadFlawCodeConfig(std::string json_path)
{
m_FlawCodeList.erase(m_FlawCodeList.begin(), m_FlawCodeList.end());
std::string strPath = json_path;
printf("ReadFlawCodeConfig path %s\n", strPath.c_str());
Json::CharReaderBuilder builder;
builder["collectComments"] = true;
Json::Value root;
std::string err;
std::ifstream ifs(strPath);
if (!ifs.is_open())
{
printf("error:file is open\n");
return 0;
}
if (!Json::parseFromStream(builder, ifs, &root, &err))
{
printf("error:parseFromStream\n");
return 0;
}
for (int i = 0; i < root.size(); i++)
{
// printf("Node idx %d /%d \n", i, root.size());
ReadFlawCode tem;
tem.flaw_name = root[i]["zh_name"].asString();
tem.flaw_code = root[i]["en_name"].asString();
string desc = root[i]["desc"].asString();
{
std::istringstream stream(desc);
std::string token;
// 使用 getline 按照分号分割
while (std::getline(stream, token, ';'))
{
tem.config_flaw_name.push_back(token);
}
}
m_FlawCodeList.push_back(tem);
}
for(int i = 0; i < m_FlawCodeList.size(); i++)
{
if(i >= QX_Result_Names.size()) {
QX_Result_Names.push_back(m_FlawCodeList.at(i).flaw_name);
QX_Result_Code.push_back(m_FlawCodeList.at(i).flaw_code);
}
else
{
QX_Result_Names.at(i) = m_FlawCodeList.at(i).flaw_name;
QX_Result_Code.at(i) = m_FlawCodeList.at(i).flaw_code;
}
}
return 0;
}
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;
}
std::string ConfigManager::GetJsonPath()
{
return m_strConfigRootPath;
}
int ConfigManager::UpdateConfig()
{
string defect_list_file = GetJsonPath();
if (defect_list_file == "") {
defect_list_file = "/var/aidlux/efs/model/defect_list.json";
}
else{
defect_list_file += "/defect_list.json";
}
ReadFlawCodeConfig(defect_list_file);
bool bFileName = false;
// std::regex pattern(R"(param_[0-9]\.json)");
std::regex pattern(R"(param_(\d+|left|right)\.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))
{
bFileName = true;
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;
}
auto it = Config_instances_.find(p.commonCheckConfig.baseConfig.strCamearName);
if (it != Config_instances_.end() && it->second) {
LoadParamConfig(it->second, entry.path());
} else {
Config_instances_[p.commonCheckConfig.baseConfig.strCamearName] = temConfig;
}
}
}
else
{
std::cerr << "config error 2: " << m_strConfigRootPath << std::endl;
}
}
if(!bFileName){
cout << "Error >>>> no param_x.json file !!!!!!!!!!!!\n";
return 2;
}
return 0;
}
int ConfigManager::GetConfig(int nConfigType, void *pconfig)
{
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,50 @@
#
cmake_minimum_required (VERSION 3.5)
set(ModuleName "ExtractImageModule")
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)
find_package(PkgConfig REQUIRED)
pkg_check_modules(TURBOJPEG REQUIRED libturbojpeg)
MESSAGE(STATUS "TURBOJPEG_INCLUDE_DIRS dir " ${TURBOJPEG_INCLUDE_DIRS})
include_directories(${TURBOJPEG_INCLUDE_DIRS})
link_directories(${TURBOJPEG_LIBRARY_DIRS})
#
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(ExtractImage SHARED ${SRC_LISTS})
target_link_libraries(ExtractImage
${OpenCV_LIBS}
${TURBOJPEG_LIBRARIES}
)
set(ModuleName "")
#add_subdirectory(example)
# make install /usr/local
#
set(CMAKE_INSTALL_PREFIX /usr/local/polet CACHE PATH "Install path prefix" FORCE)
set(HEADER_FILES include/ExtractBase.h)
#
install(TARGETS ExtractImage
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,25 @@
#ifndef ExtractBase_H_
#define ExtractBase_H_
#include <string>
#include <opencv2/opencv.hpp>
#define ExtractBaseBASE_VERSION 1
class ExtractBase
{
protected:
ExtractBase() {}
public:
// delete camera interface
~ExtractBase() {}
static ExtractBase *GetInstance();
// 复制想使用的参数
virtual int ReadCELLImg(std::string strimgPath, cv::Mat &outImg, bool bdecode) = 0;
// 返回检测版本信息
virtual std::string GetVersion() = 0;
// 返回错误信息
virtual std::string GetErrorInfo() = 0;
};
#endif

@ -0,0 +1,73 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-09-11 15:33:10
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-13 17:07:23
* @FilePath: /BOE_CELL_AOI_Detect/ExtractImageModule/include/ExtractInstance.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#ifndef ExtractInstance_H_
#define ExtractInstance_H_
#include <stdio.h>
#include <string.h>
#include <thread>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <filesystem>
#include <thread>
#include <mutex>
#include <future>
#include <opencv2/opencv.hpp>
#include "ExtractBase.h"
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
// jpg 图片的内存指针
struct JPGImgDataPtr
{
unsigned char *buffer = nullptr;
size_t imgDataSize = 0;
unsigned char *ptr_start = nullptr;
unsigned char *ptr_end = nullptr;
cv::Mat decodedImg;
int width = 0;
int height = 0;
void printInfo(const std::string &name = "") const
{
std::cout << "=== JPGImgDataPtr " << name << " ===" << std::endl;
std::cout << " imgDataSize: " << imgDataSize << " bytes" << std::endl;
std::cout << " buffer: " << (buffer ? "OK" : "NULL") << std::endl;
std::cout << " buffer: " << (void *)buffer << std::endl;
std::cout << " ptr_start: " << (void *)ptr_start
<< " ptr_end: " << (void *)ptr_end << std::endl;
}
};
class ExtractInstance : public ExtractBase
{
public:
ExtractInstance();
~ExtractInstance();
int ReadCELLImg(std::string strimgPath, cv::Mat &outImg, bool bdecode);
// 返回检测版本信息
std::string GetVersion();
// 返回错误信息
std::string GetErrorInfo();
private:
long getcurTime();
bool decode_Img(const std::string &file_path, cv::Mat &img);
// 读取图片的内存地址
int ReadImgData(const std::string &file_path, unsigned char *&buffer, size_t *fileSize);
int CalAllImgPtrDate(unsigned char *buffer, size_t fileSize, std::vector<JPGImgDataPtr> &ptrImgdataList);
int DecodeJpgImg(std::vector<JPGImgDataPtr> &ptrImgdataList, cv::Mat &outImg);
private:
};
#endif

@ -0,0 +1,15 @@
/*
* @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 "ExtractBase.h"
#include "ExtractInstance.h"
ExtractBase* ExtractBase::GetInstance()
{
return (ExtractBase*)new ExtractInstance();
}

@ -0,0 +1,322 @@
/*
* @Author: your name
* @Date: 2022-04-20 15:50:00
* @LastEditTime: 2025-09-13 17:12:17
* @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 <turbojpeg.h>
#include "ExtractInstance.h"
#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
#include <sys/time.h>
#include <fstream>
#include <chrono>
ExtractInstance::ExtractInstance()
{
}
ExtractInstance::~ExtractInstance()
{
}
int ExtractInstance::ReadImgData(const std::string &file_path, unsigned char *&buffer, size_t *fileSize)
{
std::ifstream file(file_path, std::ios::binary);
if (!file.is_open())
{
std::cerr << "Error opening file!" << std::endl;
return 1;
}
// 获取文件的大小
file.seekg(0, std::ios::end);
size_t fileSize123 = file.tellg();
file.seekg(0, std::ios::beg);
// printf("file size %d \n", fileSize);
// 分配内存来存储文件内容
buffer = new unsigned char[fileSize123];
// 读取文件内容到内存
file.read(reinterpret_cast<char *>(buffer), fileSize123);
file.close(); // 关闭文件
*fileSize = fileSize123;
return 0;
}
int ExtractInstance::CalAllImgPtrDate(unsigned char *buffer, size_t fileSize, std::vector<JPGImgDataPtr> &ptrImgdataList)
{
int count = 0;
int start = 0;
// 循环提取图片,最多提取 3 张
while (count < 3)
{
unsigned char *ptr = buffer + start;
bool found_soi = false;
bool found_eoi = false;
unsigned char *soi1 = nullptr;
unsigned char *eoi1 = nullptr;
// 寻找SOI标记0xFF 0xD8
for (; ptr < buffer + fileSize - 1; ++ptr)
{
if (*ptr == 0xFF && *(ptr + 1) == 0xD8)
{
soi1 = ptr;
found_soi = true;
break;
}
}
if (!found_soi)
break;
// 在找结束标志时又找到了一个 开始表示。
bool brestart = false;
// 寻找EOI标记0xFF 0xD9
for (ptr = soi1 + 2; ptr < buffer + fileSize - 1; ++ptr)
{
if (*ptr == 0xFF && *(ptr + 1) == 0xD9)
{
eoi1 = ptr + 2; // 包括EOI的结束部分
found_eoi = true;
break;
}
// 在找结束标志时又找到了一个 开始表示。
if (*ptr == 0xFF && *(ptr + 1) == 0xD8)
{
eoi1 = ptr - 1;
printf("error s %x %x -> %p \n ", *ptr, *(ptr + 1), ptr);
brestart = true;
break;
}
}
if (brestart)
{
start = eoi1 - buffer;
continue;
}
if (!found_eoi)
break;
size_t jpegSize = eoi1 - soi1;
// 更新起始位置
start = eoi1 - buffer;
JPGImgDataPtr temdata;
temdata.buffer = buffer;
temdata.imgDataSize = jpegSize;
temdata.ptr_start = soi1;
temdata.ptr_end = eoi1;
ptrImgdataList.push_back(temdata);
count++;
}
return 0;
}
int ExtractInstance::DecodeJpgImg(std::vector<JPGImgDataPtr> &ptrImgdataList, cv::Mat &outImg)
{
if (ptrImgdataList.empty())
return -1;
int commonWidth = 0;
int totalHeight = 0;
// 第一步:读取所有头信息,检查宽度一致,累加高度
for (auto &imgData : ptrImgdataList)
{
tjhandle handle = tjInitDecompress();
if (!handle)
{
std::cerr << "tjInitDecompress failed!" << std::endl;
return -2;
}
int jpegSubsamp = 0, jpegColorspace = 0;
if (tjDecompressHeader3(handle,
imgData.ptr_start, imgData.imgDataSize,
&imgData.width, &imgData.height,
&jpegSubsamp, &jpegColorspace) != 0)
{
std::cerr << "tjDecompressHeader3 error: " << tjGetErrorStr() << std::endl;
tjDestroy(handle);
return -3;
}
tjDestroy(handle);
if (commonWidth == 0)
commonWidth = imgData.width;
else if (commonWidth != imgData.width)
{
std::cerr << "All images must have the same width!" << std::endl;
return -4;
}
totalHeight += imgData.height;
}
// 第二步:分配大图
outImg = cv::Mat(totalHeight, commonWidth, CV_8UC1);
// 第三步:多线程解码到不同位置
auto worker = [&](JPGImgDataPtr &imgData, int yOffset)
{
tjhandle handle = tjInitDecompress();
if (!handle)
{
std::cerr << "tjInitDecompress failed!" << std::endl;
return;
}
if (tjDecompress2(handle,
imgData.ptr_start, imgData.imgDataSize,
outImg.ptr(yOffset), imgData.width,
outImg.step, imgData.height,
TJPF_GRAY, TJFLAG_FASTDCT) != 0)
{
std::cerr << "tjDecompress2 error: " << tjGetErrorStr() << std::endl;
}
tjDestroy(handle);
};
std::vector<std::thread> threads;
threads.reserve(ptrImgdataList.size());
int yOffset = 0;
for (auto &imgData : ptrImgdataList)
{
threads.emplace_back(worker, std::ref(imgData), yOffset);
yOffset += imgData.height; // 下一张图拼在下方
}
for (auto &t : threads)
{
if (t.joinable())
t.join();
}
return 0;
}
int ExtractInstance::ReadCELLImg(std::string strimgPath, cv::Mat &outImg, bool bdecode)
{
int re = -1;
if(bdecode)
{
printf("ReadCELLImg========= %s \n", strimgPath.c_str());
int re = decode_Img(strimgPath, outImg);
}
else
{
size_t lastSlashIndex = strimgPath.find_last_of("/");
std::string basePath;
std::string pureFileName;
if (lastSlashIndex != std::string::npos) {
basePath = strimgPath.substr(0, lastSlashIndex);
pureFileName = strimgPath.substr(lastSlashIndex + 1);
} else {
pureFileName = strimgPath;
}
// 4. 拼接出目标图片的完整路径
std::string targetImgPath;
if (pureFileName.find("CA") != std::string::npos || pureFileName.find("CF") != std::string::npos) {
// 如果是 CA 开头,读取 CELL_CF.jpg
targetImgPath = basePath + "/CELL_CF.jpg";
} else if (pureFileName.find("TA") != std::string::npos || pureFileName.find("TFT") != std::string::npos) {
// 如果是 TA 开头,读取 CELL_TFT.jpg
targetImgPath = basePath + "/CELL_TFT.jpg";
} else {
std::cerr << "未知文件名: " << pureFileName << std::endl;
return -1;
}
printf("ReadCELLImg========= %s \n", targetImgPath.c_str());
outImg = cv::imread(targetImgPath, cv::IMREAD_GRAYSCALE);
// 6. 检查是否成功加载
if (outImg.empty()) {
std::cerr << "错误:无法读取图片,请检查路径是否正确!" << std::endl;
return -1;
}
re = 0;
}
return re;
}
std::string ExtractInstance::GetVersion()
{
std::string str = "";
return str;
}
std::string ExtractInstance::GetErrorInfo()
{
std::string str = "";
return str;
}
bool ExtractInstance::decode_Img(const std::string &file_path, cv::Mat &img)
{
long t1 = getcurTime();
unsigned char *buffer = NULL;
size_t fileSize;
// 1、读入图片
int re = ReadImgData(file_path, buffer, &fileSize);
if (re != 0 || buffer == NULL)
{
printf("error re %d buffer == NULL\n", re);
return false;
}
long t2 = getcurTime();
// 2、获取图片地址指针
std::vector<JPGImgDataPtr> ptrImgdataList;
re = CalAllImgPtrDate(buffer, fileSize, ptrImgdataList);
if (re != 0 || ptrImgdataList.size() <= 0)
{
printf("error re %d size %ld \n", re, ptrImgdataList.size());
return false;
}
long t3 = getcurTime();
// 3、解码 jpg 图片
re = DecodeJpgImg(ptrImgdataList, img);
long t4 = getcurTime();
// printf("time %ld read %ld call ptrdata %ld decode %ld\n", t4 - t1, t2 - t1, t3 - t2, t4 - t3);
if (re != 0 || img.empty())
{
printf("error re %d outimg.empty()\n", re);
return false;
}
// if (true)
// {
// cv::imwrite("outimg_img11.png", outimg);
// }
// getchar();
delete[] buffer;
return true;
}
long ExtractInstance::getcurTime()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000;
}

@ -0,0 +1,23 @@
# 阿加犀工业检测算法调用通用库
## 介绍
京东方 检测算法so
## 环境
1、opencv
2、tensorRT
## 使用
1、把本地的TensorRT 头文件拷贝到 include文件下中。/home/aidlux/drivers/tensorrt/TensorRT-8.2.1.8/samples/common/
2、修改模型输入、输出尺寸。ImgCheckConfig.h AI_IN_IMAGE_WIDTH AI_IN_IMAGE_HEIGHT AI_OUT_IMAGE_WIDTH AI_OUT_IMAGE_HEIGHT
3、修改模型输入参数宏定义 作为变量初始化参数
### 最近更新 Update
### Notes
+ 1、如果不能正确显示中文有可能系统没有安装中文字符 sudo apt-get install language-pack-zh-hans
### Author
- [谢文吉]

@ -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}")

@ -0,0 +1,15 @@
if(NOT DEFINED ModuleName OR ModuleName EQUAL "")
set(ModuleName "DefaultModule")
endif()
# BUILD_ARCH:x86_64 aarch64 gcc -v Target
if(NOT DEFINED BUILD_ARCH)
set(BUILD_ARCH x86_64 CACHE STRING "Arch of this project")
endif()
if(NOT "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}" STREQUAL "${CMAKE_BINARY_DIR}/../lib/${BUILD_ARCH}/")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/${BUILD_ARCH}/)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/${BUILD_ARCH}/)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/)
endif()
link_directories(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})

@ -0,0 +1,2 @@
message(STATUS "build <${ModuleName}>")
message(STATUS " ARCH type:${BUILD_ARCH} Mode:${CMAKE_BUILD_TYPE}")

@ -0,0 +1,42 @@
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")
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/AlgorithmModule/include
${PROJECT_SOURCE_DIR}/ConfigModule/include
${PROJECT_SOURCE_DIR}/ExtractImageModule/include
)
link_directories(
/usr/local/lib/
/usr/local/cuda/lib64
)
file(GLOB SRC_LISTS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_executable("test_CellAOI" ${SRC_LISTS})
target_link_libraries("test_CellAOI"
pthread
z
nvinfer
TY_Check
Config
ExtractImage
#/usr/local/cuda-12.1/targets/x86_64-linux/lib/libcudart.so
${OpenCV_LIBS}
)
# RPATH
set_target_properties("test_CellAOI" PROPERTIES
BUILD_RPATH "\$ORIGIN"
)
set(ModuleName "")

@ -0,0 +1,48 @@
/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2022-03-16 17:09:11
* @LastEditors: sueRimn
* @LastEditTime: 2022-09-23 17:43:15
*/
#ifndef _CheckDefine_HPP_
#define _CheckDefine_HPP_
#include <opencv2/opencv.hpp>
#define SRC_IMAGE_WIDTH 14192
#define SRC_IMAGE_HEIGHT 10640
#define SRC_IMAGE_SIZE 1*SRC_IMAGE_WIDTH *SRC_IMAGE_HEIGHT
#define AI_BATCH_SIZE 1
enum ERRORDEFINE
{
RESULT_OK,
ERROR_CHECK_IMG_NULL, // 检测图片为空
ERROR_CHECK_RESOURCE_NULL, // 检测资源为空
ERROR_PRECHECK_IMG_NULL, // 预检测图片 异常
};
// 检测控制参数
struct CheckControlConfigSt
{
CheckControlConfigSt()
{
}
};
// 系统运行控制参数
struct SystmeControlConfigST
{
CheckControlConfigSt checkControlConfig; //// 检测控制参数
SystmeControlConfigST()
{
}
};
#endif //_CORELOGICFACTORY_HPP_

@ -0,0 +1,129 @@
#include "Image_ReadAndChange.h"
#include "json/json.h"
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <map>
#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <mutex>
#include <unistd.h>
Image_ReadChannel::Image_ReadChannel()
{
m_ChannelNameList.clear();
}
Image_ReadChannel::~Image_ReadChannel()
{
}
bool Image_ReadChannel::containsChinese(const std::string &str)
{
for (size_t i = 0; i < str.size(); ++i)
{
if ((unsigned char)str[i] >= 0x80)
{
return true; // 如果有非ASCII字符可能是中文
}
}
return false;
}
bool Image_ReadChannel::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;
}
int Image_ReadChannel::ReadJsonConfig(std::string json_path)
{
m_ChannelNameList.erase(m_ChannelNameList.begin(), m_ChannelNameList.end());
std::string strPath = json_path;
printf("ReadJsonConfig path %s\n", strPath.c_str());
Json::CharReaderBuilder builder;
builder["collectComments"] = true;
Json::Value root;
std::string err;
std::ifstream ifs(strPath);
if (!ifs.is_open())
{
printf("error:file is open\n");
return false;
}
if (!Json::parseFromStream(builder, ifs, &root, &err))
{
printf("error:parseFromStream\n");
return false;
}
for (int i = 0; i < root.size(); i++)
{
// printf("Node idx %d /%d \n", i, root.size());
ReadImageName tem;
tem.strDetChannle = root[i]["code"].asString();
std::string strimgname = root[i]["image_name"].asString();
{
std::istringstream stream(strimgname);
std::string token;
// 使用 getline 按照分号分割
while (std::getline(stream, token, ';'))
{
tem.strImgNameList.push_back(token);
}
}
// printf("det name %s img name Num %ld \n", tem.strDetChannle.c_str(), tem.strImgNameList.size());
// 输出分割后的结果
// for (const auto &str : tem.strImgNameList)
// {
// std::cout << str << std::endl;
// }
m_ChannelNameList.push_back(tem);
}
return 0;
}
std::string Image_ReadChannel::strDetName(std::string strImageName)
{
std::string strDetName = "";
for (const auto name : m_ChannelNameList)
{
for (int i = 0; i < name.strImgNameList.size(); i++)
{
// 包含中文
if (containsChinese(strImageName))
{
// printf("strImageName %s name.strImgNameList.at(i) %s\n",strImageName.c_str(), name.strImgNameList.at(i).c_str());
if (strImageName == name.strImgNameList.at(i))
{
return name.strDetChannle;
}
}
else
{
if (CompareIgnoreCase(strImageName, name.strImgNameList.at(i)))
{
return name.strDetChannle;
}
}
}
}
return strDetName;
}

@ -0,0 +1,56 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-07-25 09:14:25
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-11 18:00:27
* @FilePath: /BOE_CELL_ET/AlgorithmModule/example/Image_ReadAndChange.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
//图片基本处理
*/
#ifndef Image_ReadAndChange_H_
#define Image_ReadAndChange_H_
#include <vector>
#include <thread>
#include "CheckDefine.h"
#include "ImgCheckConfig.h"
using namespace std;
// 图片读取的通道
class Image_ReadChannel
{
public:
struct ReadImageName
{
std::string strDetChannle;
std::vector<std::string> strImgNameList;
ReadImageName()
{
strImgNameList.clear();
strDetChannle = "";
}
};
private:
/* data */
public:
Image_ReadChannel(/* args */);
~Image_ReadChannel();
bool containsChinese(const std::string &str);
int ReadJsonConfig(std::string json_path); // 加载检测图片名称配置参数
bool CompareIgnoreCase(const std::string &str1, const std::string &str2);
std::string strDetName(std::string strImageName);
private:
std::vector<ReadImageName> m_ChannelNameList;
};
#endif

@ -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);
}

@ -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,287 @@
#include "Read_Image.h"
#include <filesystem>
// 转小写
std::string toLower(const std::string &str)
{
std::string lower = str;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return lower;
}
int Extract_Name_Base::Read_Product_Image(std::string strPath)
{
return 0;
}
int Extract_Name_Base::Read_Camera_Product_Image(std::string strPath, int userflag, std::string strproduct)
{
std::vector<cv::String> img_paths;
// std::cout << strPath << std::endl;
cv::glob(strPath, img_paths, true);
for (int i = 0; i < img_paths.size(); i++)
{
string strImagePath = img_paths[i];
Extract_Info(strImagePath, strproduct, userflag);
}
return 0;
}
int Extract_Name_Base::Read_Product_Camera_Image(std::string strPath)
{
return 0;
}
std::shared_ptr<Product_File_Info> Extract_Name_Base::GetProduct(std::string strProductID)
{
for (int i = 0; i < m_product_Camera_List.size(); i++)
{
if (m_product_Camera_List[i]->strProductID == strProductID)
{
return m_product_Camera_List[i];
}
}
return std::shared_ptr<Product_File_Info>();
}
std::shared_ptr<Camera_File_Info> Extract_Name_Base::GetCamera(std::string strProductID, std::string strCamName)
{
for (int i = 0; i < m_product_Camera_List.size(); i++)
{
if (m_product_Camera_List[i]->strProductID == strProductID)
{
for (int j = 0; j < m_product_Camera_List[i]->camera_list.size(); j++)
{
if (m_product_Camera_List[i]->camera_list[j]->strCamName == strCamName)
{
return m_product_Camera_List[i]->camera_list[j];
}
}
}
}
return std::shared_ptr<Camera_File_Info>();
}
std::shared_ptr<Camera_File_Info> Extract_Name_Base::GetCamera(std::shared_ptr<Product_File_Info> product, std::string strCamName)
{
for (int i = 0; i < product->camera_list.size(); i++)
{
if (product->camera_list[i]->strCamName == strCamName)
{
return product->camera_list[i];
}
}
return std::shared_ptr<Camera_File_Info>();
}
// 判断目录部分是否包含某些关键词(不区分大小写)
bool Extract_Name_Base::dirPathContains(const fs::path &fullPath, const std::string KeyName)
{
fs::path parentDir = fullPath.parent_path();
std::string lowKeyName = toLower(KeyName);
for (const auto &dir : parentDir)
{
std::string dirName = toLower(dir.string());
if (dirName == lowKeyName)
{
return true;
}
}
return false;
}
Read_Image::Read_Image(/* args */)
{
}
Read_Image::~Read_Image()
{
}
int Read_Image::Read_Image_List(std::string strPath, std::string strproduct)
{
m_extract.pimage_ReadChannel = pimage_ReadChannel;
m_extract.m_product_Camera_List.clear();
int re = m_extract.Read_Image_List(strPath, strproduct);
if (re != 0)
{
return re;
}
m_product_Camera_List.clear();
m_product_Camera_List.assign(m_extract.m_product_Camera_List.begin(), m_extract.m_product_Camera_List.end());
for (int i = 0; i < m_extract.m_product_Camera_List.size(); i++)
{
m_extract.m_product_Camera_List[i]->print();
}
return 0;
}
int Read_Image::Read_Image_List(std::string strPath_left, std::string strPath_right, std::string strproduct)
{
m_extract.pimage_ReadChannel = pimage_ReadChannel;
m_extract.m_product_Camera_List.clear();
int re = m_extract.Read_Image_List(strPath_left, strPath_right, strproduct);
if (re != 0)
{
return re;
}
m_product_Camera_List.clear();
m_product_Camera_List.assign(m_extract.m_product_Camera_List.begin(), m_extract.m_product_Camera_List.end());
for (int i = 0; i < m_extract.m_product_Camera_List.size(); i++)
{
m_extract.m_product_Camera_List[i]->print();
}
return 0;
}
int Extract_ALL::Extract_Info(std::string strPath, std::string strproduct, int userflag)
{
// std::cout << strPath << std::endl;
// 1、获取 产品名称
std::string strProductName = Extract_Product_Name(strPath, userflag);
if (strProductName.empty())
{
return -1;
}
std::shared_ptr<Product_File_Info> pProduct = GetProduct(strProductName);
if (strproduct != "" && strproduct != strProductName)
{
return -2;
}
if (pProduct.get() == nullptr)
{
printf("pProduct %s is NULL \n", strProductName.c_str());
pProduct = std::make_shared<Product_File_Info>();
pProduct->strProductID = strProductName;
m_product_Camera_List.push_back(pProduct);
}
// 2、获取 相机名称
std::string strCameraName = Extract_Camera_Name(strPath, userflag);
if (strCameraName.empty())
{
printf("strCameraName is error \n");
return -1;
}
std::shared_ptr<Camera_File_Info> pCamera = GetCamera(pProduct, strCameraName);
if (pCamera.get() == nullptr)
{
printf("pCamera %s is NULL \n", strCameraName.c_str());
pCamera = std::make_shared<Camera_File_Info>();
pCamera->strCamName = strCameraName;
pProduct->camera_list.push_back(pCamera);
}
// 3、获取 通道
std::string strChannelName = Extract_Channel_Name(strPath, userflag);
if (strChannelName.empty())
{
printf("strChannelName is NULL \n");
return -1;
}
fs::path p = fs::path(strPath);
std::string filenameWithoutExt = p.stem().string();
std::shared_ptr<Image_Info> pImage = std::make_shared<Image_Info>();
pImage->strProductID = strProductName;
pImage->strCamID = strCameraName;
pImage->strchannelName = strChannelName;
pImage->strName = filenameWithoutExt;
pImage->strPath = strPath;
pCamera->image_list.push_back(pImage);
return 0;
}
std::string Extract_ALL::Extract_Camera_Name(std::string strPath, int userflag)
{
fs::path p = fs::path(strPath);
std::string filename = p.stem();
if (filename.find("TA") != std::string::npos)
return "TA";
else if (filename.find("CA") != std::string::npos)
return "CA";
// std::cout << "完整路径: " << p << std::endl;
// std::cout << "文件名: " << p.filename() << std::endl;
// std::cout << "不带后缀的文件名: " << p.stem() << std::endl;
// std::cout << "后缀: " << p.extension() << std::endl;
// getchar();
return "";
}
std::string Extract_ALL::Extract_Product_Name(std::string strPath, int userflag)
{
// std::cout << strPath << std::endl;
fs::path p = fs::path(strPath);
fs::path lastDir = p.parent_path().filename();
std::string name = lastDir.string();
if (name.length()<7)
{
lastDir = p.parent_path().parent_path().filename();
name = lastDir.string();
}
// std::cout << name << std::endl;
if (name.empty())
{
return "";
}
return name;
}
std::string Extract_ALL::Extract_Channel_Name(std::string strPath, int userflag)
{
std::string strchannelName = "";
fs::path p = fs::path(strPath);
std::string filename = p.stem();
if (filename.find("TAA") != std::string::npos)
strchannelName = "TA";
else if (filename.find("TAB") != std::string::npos)
strchannelName = "TA";
else if (filename.find("CAA") != std::string::npos)
strchannelName = "CA";
else if (filename.find("CAB") != std::string::npos)
strchannelName = "CA";
else if (filename.find("CA") != std::string::npos)
strchannelName = "CA";
else if (filename.find("TA") != std::string::npos)
strchannelName = "TA";
return strchannelName;
}
int Extract_ALL::Read_Image_List(std::string strPath, std::string strproduct)
{
std::string strSearchImgPath = strPath + "/*.ytimage";
Read_Camera_Product_Image(strSearchImgPath, 0, strproduct);
// strSearchImgPath = strPath + "/*.png";
// Read_Camera_Product_Image(strSearchImgPath, 1);
return 0;
}
int Extract_ALL::Read_Image_List(std::string strPath_left, std::string strPath_right, std::string strproduct)
{
std::string strSearchImgPath = strPath_left + "/*.ytimage";
Read_Camera_Product_Image(strSearchImgPath, 0, strproduct);
strSearchImgPath = strPath_right + "/*.ytimage";
Read_Camera_Product_Image(strSearchImgPath, 0, strproduct);
// strSearchImgPath = strPath + "/*.png";
// Read_Camera_Product_Image(strSearchImgPath, 1);
return 0;
}

@ -0,0 +1,185 @@
#ifndef Read_Image_HPP_
#define Read_Image_HPP_
#include <map>
#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <filesystem>
#include <opencv2/opencv.hpp>
#include "Image_ReadAndChange.h"
namespace fs = std::filesystem;
using namespace std;
// 图片信息
struct Image_Info
{
std::string strProductID; // 产品ID
std::string strCamID; // 相机名称
std::string strchannelName; // 通道名称
std::string strPath; // 完整路径
std::string strName; // 图片名称
cv::Mat img; // 图像数据
long readImg_start; // 读取开始时间
long readImg_end; // 读取结束时间
// 构造函数,调用 Init 初始化
Image_Info()
{
Init();
}
// 初始化函数,重置所有成员变量
void Init()
{
strProductID = "";
strCamID = "";
strchannelName = "";
strPath = "";
strName = "";
img.release(); // 释放图像内存
readImg_start = 0;
readImg_end = 0;
}
void print()
{
std::cout << "Product ID: " << strProductID << std::endl;
std::cout << "Camera ID: " << strCamID << std::endl;
std::cout << "Channel Name: " << strchannelName << std::endl;
std::cout << "Image Path: " << strPath << std::endl;
std::cout << "Image Name: " << strName << std::endl;
std::cout << "Read Start Time: " << readImg_start << std::endl;
std::cout << "Read End Time: " << readImg_end << std::endl;
}
};
// 相机信息
struct Camera_File_Info
{
std::string strCamName; // 相机名称
std::string strCamPath; // 相机路径
vector<std::shared_ptr<Image_Info>> image_list; // 图片信息列表
Camera_File_Info()
{
Init();
}
void Init()
{
strCamName = "";
strCamPath = "";
}
int getImgNum()
{
int num = 0;
for (auto item : image_list)
{
num++;
}
return num;
}
void print()
{
printf("************CamName: %s img num %ld\n", strCamName.c_str(), image_list.size());
// for (auto &item : image_list)
// {
// // item->print();
// }
}
};
// 产品信息
struct Product_File_Info
{
std::string strProductID; // 产品ID
std::string strProductPath; // 产品路径
vector<std::shared_ptr<Camera_File_Info>> camera_list; // 相机信息列表
Product_File_Info()
{
Init();
}
void Init()
{
strProductID = "";
strProductPath = "";
}
int getImgNum()
{
int num = 0;
for (auto item : camera_list)
{
num += item->getImgNum();
}
return num;
}
void print()
{
printf("***strProductID: %s\n", strProductID.c_str());
for (auto &item : camera_list)
{
item->print();
}
}
};
class Extract_Name_Base
{
public:
virtual int Extract_Info(std::string strPath, std::string strproduct, int userflag) = 0;
virtual std::string Extract_Camera_Name(std::string strPath, int userflag = 0) = 0;
virtual std::string Extract_Product_Name(std::string strPath, int userflag = 0) = 0;
virtual std::string Extract_Channel_Name(std::string strPath, int userflag = 0) = 0;
virtual int Read_Image_List(std::string strPath, std::string strproduct) = 0;
virtual int Read_Image_List(std::string strPath_left, std::string strPath_right, std::string strproduct) = 0;
int Read_Product_Image(std::string strPath);
int Read_Camera_Product_Image(std::string strPath, int userflag, std::string strproduct);
int Read_Product_Camera_Image(std::string strPath);
std::shared_ptr<Product_File_Info> GetProduct(std::string strProductID);
std::shared_ptr<Camera_File_Info> GetCamera(std::string strProductID, std::string strCamName);
std::shared_ptr<Camera_File_Info> GetCamera(std::shared_ptr<Product_File_Info> product, std::string strCamName);
bool dirPathContains(const fs::path &fullPath, const std::string KeyName);
vector<std::shared_ptr<Product_File_Info>> m_product_Camera_List;
Image_ReadChannel *pimage_ReadChannel;
};
class Extract_ALL : public Extract_Name_Base
{
public:
int Extract_Info(std::string strPath, std::string strproduct, int userflag = 0);
std::string Extract_Camera_Name(std::string strPath, int userflag = 0);
std::string Extract_Product_Name(std::string strPath, int userflag = 0);
std::string Extract_Channel_Name(std::string strPath, int userflag = 0);
int Read_Image_List(std::string strPath, std::string strproduct);
int Read_Image_List(std::string strPath_left, std::string strPath_right, std::string strproduct);
};
class Read_Image
{
public:
// 图片文件的格式
enum Image_File_TYPE_
{
Image_File_Product_Image, // 产品-图片格式
Image_File_Camera_Product_Image, // 相机-产品-图片格式
Image_File_Product_Camera_Image, // 产品-相机-图片格式
};
public:
Read_Image(/* args */);
~Read_Image();
int Read_Image_List(std::string strPath, std::string strproduct);
int Read_Image_List(std::string strPath_left, std::string strPath_right, std::string strproduct);
Extract_ALL m_extract;
Image_ReadChannel *pimage_ReadChannel;
private:
public:
vector<std::shared_ptr<Product_File_Info>> m_product_Camera_List; // 产品相机列表
};
#endif

@ -0,0 +1,163 @@
/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2022-03-16 17:09:11
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-11 18:16:45
*/
#ifndef _SYSTEMCOMMONDEFIN1_HPP_
#define _SYSTEMCOMMONDEFIN1_HPP_
#include <string>
// working:”检测”, ready:”就绪”, check: “自检”, bad: “故障”, close: “关闭”
// 系统运行状态定义
enum SYSTEMRUNTYPE_
{
SYSTEM_RUN_TYPE_null,
SYSTEM_RUN_TYPE_working, // ”检测”
SYSTEM_RUN_TYPE_ready, // ”就绪”
SYSTEM_RUN_TYPE_check, // “自检”
SYSTEM_RUN_TYPE_bad, // “故障”
SYSTEM_RUN_TYPE_close, // “关闭”
SYSTEM_RUN_TYPE_count,
};
//
// 检测状态 离线检测 在线检测
enum CHECKIMGTRUNTYP_
{
CHECK_TYPE_ONLING, // 在线检测
CHECK_TYPE_OFFLING, // 离线检测
};
//------------------------config file define----------------------------------------
#define FILE_SYSTEM_RUN_CONFIG "../data/system_param.json"
#define FILE_THRESHOLDPARARM "/var/aidlux/efs/jdf/model/param.json"
#define FILE_CAM_ROI_PARARM "/var/aidlux/aid-cms/model/roi.json"
#define FILE_AIMODEL_FILE_PATH "/var/aidlux/aid-cms/model/config.json"
#define FILE_CONFIG_ROOR_PATH "/var/aidlux/aid-cms/model/"
#define FILE_AI_defect_BOE_MODEL_PATH "/home/aidlux/BOE/UseModel/defect.engine"
#define FILE_AI_classis_BOE_MODEL_PATH "/home/aidlux/BOE/UseModel/class.engine"
#define FILE_CHECKIMG_CONFIG "../DataConfig/check_Config.ini"
#define FILE_SAVEOKIMG_PATH "/home/aidlux/xwj/OKImg/"
// #define FILE_SAVEALLIMG_PATH "/home/aidlux/JBL/imageData/"
#define FILE_SAVEALLIMG_PATH "/ssd/SaveImg/"
#define FILE_SAVENGIMG_PATH "/ssd/NGImg/"
// #define MAX_NAM_LEN 64
// 字符长度
#define MAX_STR_LEN 128
// url长度
#define MAX_ULR_LEN 256
#define MAX_GPU_NUM 2
// ncnn 行人检测 跟踪 检测最大 线程个数
#define MAX_PERSONTRACKER_THREAD_NUM 4
// 共享内存检测最大 线程个数
#define MAX_SHARMEMORYCHECK_THREAD_NUM 2
// 行人+跌倒检测 算法 资源 起止
#define SHARMEMORYCHECK_THREAD_PERSON_IDX_START 0
#define SHARMEMORYCHECK_THREAD_PERSON_IDX_END 6
// 离岗行人 算法 资源 起止
#define SHARMEMORYCHECK_THREAD_Departure_PERSON_IDX_START 7
#define SHARMEMORYCHECK_THREAD_Departure_PERSON_IDX_END 7
// 属性检测 算法 资源 起止
#define SHARMEMORYCHECK_THREAD_ATTRIBUTE_IDX_START 9
#define SHARMEMORYCHECK_THREAD_ATTRIBUTE_IDX_END 9
#define USERSHAREKEY 476550
#define SHARED_MEM_LEN IMAGE_WIDTH *IMAGE_HEIGHT * 3
#define HTTP_SERVER_PATTERN_CAMCONFIG "/api/camera/param"
#define HTTP_SERVER_PATTERN_CAMCHECKROI "/api/camera/roi"
#define HTTP_SERVER_PATTERN_PARAM_ADD "/param/add"
#define HTTP_SERVER_PATTERN_PREVIEW "/preview"
#define HTTP_SERVER_PATTERN_SWITCH "/switch"
#define HTTP_SERVER_PATTERN_DETECT_OPEN_ALL "/api/detect/open/all"
#define HTTP_SERVER_PATTERN_PLC_STATE "/api/plc/state"
#define HTTP_SERVER_PATTERN_PLC_SET_STATE "/api/plc/set/state"
#define IMAGE_SIZE (2048 * 1792)
enum START_SYSTEM_STEP_
{
START_SYSTEM_STEP_LoadConfig,
START_SYSTEM_STEP_InitCheck,
START_SYSTEM_STEP_PreCheck,
START_SYSTEM_STEP_CamIO,
START_SYSTEM_STEP_Complete,
};
struct SystemConfigParam
{
std::string Analysis_Config_path;
std::string Analysis_Config_path_Cam2;
std::string Check_Config_path;
std::string config_Root_Path;
std::string preCheckImg_Path; // 预处理图片
int Use_CPU_StartIdx; // 使用 CPU的开始核
int preCHeck_YX; // 异显检测 1 用异显1模型 检测; 2用异显2模型 检测; 其他:不进行异显检测
int preCHeck_defect; // 缺陷检测模型1用wtb btw hb4 等进检测; 其他 用模型进行检测
SystemConfigParam()
{
Use_CPU_StartIdx = 0;
preCheckImg_Path = "../data/t1.tif";
preCHeck_YX = 0;
preCHeck_defect = 0;
config_Root_Path = "";
}
bool valid()
{
if (Analysis_Config_path.size() &&
Check_Config_path.size() &&
preCheckImg_Path.size() &&
config_Root_Path.size() &&
Use_CPU_StartIdx >= 0)
{
return true;
}
return false;
}
};
enum THREAD_CPU_
{
THREAD_CPU_Main_Det,
THREAD_CPU_Main_readImg,
THREAD_CPU_Main_saveImg,
THREAD_CPU_CheckSo,
THREAD_CPU_Count,
};
struct CPU_ID_INFO_
{
int startIdx;
int num;
CPU_ID_INFO_()
{
startIdx = 0;
num = 0;
}
void set(int sidx, int num)
{
this->startIdx = sidx;
this->num = num;
}
};
#endif //_CORELOGICFACTORY_HPP_

File diff suppressed because it is too large Load Diff

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

Loading…
Cancel
Save