|
|
#include "deal.h"
|
|
|
#include "json/json.h"
|
|
|
#include <sys/time.h>
|
|
|
#include <sys/types.h>
|
|
|
#include <sys/stat.h>
|
|
|
#include <unistd.h>
|
|
|
#include <string>
|
|
|
#include "CheckUtil.hpp"
|
|
|
#include "LoadImage.hpp" // #include "LoadImage.h"
|
|
|
std::string ExtractFileNameWithoutExtension(const std::string &strImgPath)
|
|
|
{
|
|
|
// 查找最后一个斜杠 '/' 或 '\' 的位置
|
|
|
size_t lastSlashPos = strImgPath.find_last_of("/\\");
|
|
|
|
|
|
// 如果没有找到斜杠,默认整个字符串是文件名
|
|
|
std::string fileName = (lastSlashPos == std::string::npos)
|
|
|
? strImgPath
|
|
|
: strImgPath.substr(lastSlashPos + 1);
|
|
|
// 查找最后一个点 '.' 的位置
|
|
|
size_t lastDotPos = fileName.find_last_of('.');
|
|
|
// 如果没有找到点号,或者点号在第一个字符的位置,则返回完整文件名
|
|
|
if (lastDotPos == std::string::npos || lastDotPos == 0)
|
|
|
{
|
|
|
return fileName;
|
|
|
}
|
|
|
|
|
|
// 返回去掉扩展名的部分
|
|
|
return fileName.substr(0, lastDotPos);
|
|
|
}
|
|
|
std::string GetFileName(const std::string &strImgPath)
|
|
|
{
|
|
|
// 查找最后一个斜杠 '/' 或 '\' 的位置
|
|
|
size_t lastSlashPos = strImgPath.find_last_of("/\\");
|
|
|
|
|
|
// 如果没有找到斜杠,默认整个字符串是文件名
|
|
|
std::string fileName = (lastSlashPos == std::string::npos)
|
|
|
? strImgPath
|
|
|
: strImgPath.substr(lastSlashPos + 1);
|
|
|
// 查找最后一个点 '.' 的位置
|
|
|
|
|
|
return fileName;
|
|
|
}
|
|
|
|
|
|
bool customSort(const AI_Det_Channel_ &a, const AI_Det_Channel_ &b)
|
|
|
{
|
|
|
// 特定规则排序: "a" 排第一, "b" 排第二, "L" 排最后
|
|
|
if (a.strChannel == "Up-Particle" && b.strChannel != "Up-Particle")
|
|
|
{
|
|
|
return true; // "a" 排在前面
|
|
|
}
|
|
|
if (a.strChannel != "Up-Particle" && b.strChannel == "Up-Particle")
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (a.strChannel == "Down-Particle" && b.strChannel != "Down-Particle" && b.strChannel != "Up-Particle")
|
|
|
{
|
|
|
return true; // "b" 排第二
|
|
|
}
|
|
|
if (a.strChannel != "Down-Particle" && b.strChannel == "Down-Particle")
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (a.strChannel == "L0" && b.strChannel != "L0" && b.strChannel != "Up-Particle" && b.strChannel != "Down-Particle")
|
|
|
{
|
|
|
return false; // "L" 排最后
|
|
|
}
|
|
|
if (a.strChannel != "L0" && b.strChannel == "L0")
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 对其他情况使用字典顺序排序
|
|
|
return a.strChannel < b.strChannel;
|
|
|
}
|
|
|
|
|
|
// 定义图片读取函数
|
|
|
void readImage(const std::string &filename)
|
|
|
{
|
|
|
cv::Mat image = cv::imread(filename);
|
|
|
if (image.empty())
|
|
|
{
|
|
|
std::cerr << "Error: Unable to read image " << filename << std::endl;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// // 在这里可以添加对图像的处理操作
|
|
|
// // 例如:显示图像、保存图像、进行其他处理等
|
|
|
|
|
|
// // 示例:显示图像
|
|
|
// cv::imshow(filename, image);
|
|
|
// cv::waitKey(0);
|
|
|
// cv::destroyWindow(filename);
|
|
|
}
|
|
|
|
|
|
int _sysmkdir_1(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_1(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_1(const std::string &dir)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
if (dir.empty())
|
|
|
return -1;
|
|
|
std::string pdir;
|
|
|
if ((ret = _sysmkdir_1(dir)) == -1)
|
|
|
{
|
|
|
pdir = __getParentDir_1(dir);
|
|
|
if ((ret = _sysmkdirs_1(pdir)) == 0)
|
|
|
{
|
|
|
ret = _sysmkdirs_1(dir);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
long getcurTime()
|
|
|
{
|
|
|
struct timeval tv;
|
|
|
gettimeofday(&tv, NULL);
|
|
|
return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000;
|
|
|
}
|
|
|
deal::deal()
|
|
|
{
|
|
|
nLastCheckAnalysisyThreadIdx = 0;
|
|
|
m_nCamIdx = 0;
|
|
|
m_nCurUseCPUIDX = 0;
|
|
|
m_DetResult.Init();
|
|
|
for (int i = 0; i < READ_IMG_THREAD_NUM; i++)
|
|
|
{
|
|
|
m_nReadStausList[i] = ReadImg_Status_IDE;
|
|
|
}
|
|
|
m_nreadImg_Stop = false;
|
|
|
m_strCurDate = "";
|
|
|
m_nReadThread_type = READ_THREAD_TYPE_NULL;
|
|
|
|
|
|
for (int i = 0; i < Status_Type_Count; i++)
|
|
|
{
|
|
|
m_DetStatusList[i] = Thread_Status_IDE;
|
|
|
}
|
|
|
m_nTestNum = 9999999;
|
|
|
m_pALLImgCheckAnalysisy = NULL;
|
|
|
|
|
|
// ✅ 新增:初始化产品检测线程池
|
|
|
m_bProductReadExit = false;
|
|
|
m_nProductReadThreadNum = READ_PRODUCT_THREAD_NUM;
|
|
|
m_nProductQueueMaxSize = PRODUCT_QUEUE_MAX_SIZE;
|
|
|
m_nCheckNotifiedCount = 0;
|
|
|
}
|
|
|
|
|
|
deal::~deal()
|
|
|
{
|
|
|
// ✅ 新增:销毁产品检测线程池
|
|
|
DestroyProductReadThreadPool();
|
|
|
}
|
|
|
|
|
|
int deal::start()
|
|
|
{
|
|
|
|
|
|
std::string strdate = CheckUtil::getCurrentDate();
|
|
|
printf("===== %s\n", strdate.c_str());
|
|
|
int re = Init();
|
|
|
// getchar();
|
|
|
// 配置系统运行的cup核数。
|
|
|
|
|
|
if (re != 0)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
// 解析图片,并保存
|
|
|
if (Process_Run_SaveImg == runConfig.run_Type)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
else if (runConfig.run_Type == Process_Run_ReJson)
|
|
|
{
|
|
|
|
|
|
ReJson_ALL();
|
|
|
return 0;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
DetImg();
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::Init()
|
|
|
{
|
|
|
InitCPUIDX();
|
|
|
// 读取系统配置文件
|
|
|
int re = ReadSystemConfig(FILE_SYSTEM_RUN_CONFIG);
|
|
|
if (re == false)
|
|
|
{
|
|
|
printf("ReadSystemConfig error\n");
|
|
|
return 1;
|
|
|
}
|
|
|
// 加载 检测 的通道 图片名称
|
|
|
std::string strchannlePath = m_system_param.config_Root_Path + "surface_list.json";
|
|
|
m_image_ReadChannel.ReadJsonConfig(strchannlePath);
|
|
|
// getchar();
|
|
|
|
|
|
if (Process_Run_SaveImg == runConfig.run_Type)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
// getchar();
|
|
|
// 初始化参数模块
|
|
|
InitConfig();
|
|
|
|
|
|
printf("\n\n\n\n\n\n\n\n\n\n\n**********************************************************LoadCheckImgConfig\n");
|
|
|
// 载入参数
|
|
|
re = LoadCheckImgConfig();
|
|
|
if (re != 0)
|
|
|
{
|
|
|
printf("read config error\n");
|
|
|
return 2;
|
|
|
}
|
|
|
printf("\n\n**********************************************************InitCheckAnalysisy\n");
|
|
|
|
|
|
// 初始化检测库
|
|
|
InitCheckAnalysisy();
|
|
|
printf("\n\n\n\n\n\n\n\n\n\n\n**********************************************************Check\n");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::LoadCheckImgConfig()
|
|
|
{
|
|
|
|
|
|
int re = LoadAnalysisConfig();
|
|
|
if (re != 0)
|
|
|
{
|
|
|
return re;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::InitCheckAnalysisy()
|
|
|
{
|
|
|
int re = 0;
|
|
|
int m_nMAX_GPU_NUM = MAX_GPU_NUM;
|
|
|
if (m_nMAX_GPU_NUM <= 0)
|
|
|
{
|
|
|
printf(">>>>error GPU error %d \n", m_nMAX_GPU_NUM);
|
|
|
return 2;
|
|
|
}
|
|
|
int startidx = m_CPUInfo[THREAD_CPU_CheckSo].startIdx;
|
|
|
int cpunum = m_CPUInfo[THREAD_CPU_CheckSo].num;
|
|
|
m_RunConfig.nCpu_start_Idx = startidx;
|
|
|
m_RunConfig.nCpu_num = cpunum;
|
|
|
m_RunConfig.nWorkIdx = m_system_param.nWorkIdx;
|
|
|
for (int i = 0; i < MAX_GPU_NUM; i++)
|
|
|
{
|
|
|
m_RunConfig.UseGPUList[i] = m_system_param.GPU_Device_ID_List[i];
|
|
|
printf("gpu %d %d\n", i, m_RunConfig.UseGPUList[i]);
|
|
|
}
|
|
|
m_pALLImgCheckAnalysisy = ALLImgCheckBase::GetInstance();
|
|
|
re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)&m_RunConfig, CHECK_CONFIG_Run);
|
|
|
re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)m_pConfigManager, CHECK_CONFIG_Module);
|
|
|
|
|
|
VERSION_INFO tm;
|
|
|
tm.InterfaceVersion = ALL_INTERFACE_VERSION;
|
|
|
tm.ConfigVersion = CONFIGBASE_VERSION;
|
|
|
tm.ResultVersion = RESULT_VERSION;
|
|
|
re = m_pALLImgCheckAnalysisy->RunStart(&tm);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
printf("RunStart Fail %d\n", re);
|
|
|
return re;
|
|
|
}
|
|
|
|
|
|
printf(">>>> ImgCheckThread Start Succ \n");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::InitConfig()
|
|
|
{
|
|
|
m_pConfigManager = ConfigManagerBase::GetInstance();
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::InitSaveImgPath()
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::LoadCheckConfig()
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::LoadAnalysisConfig()
|
|
|
{
|
|
|
if (!m_pConfigManager)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
std::string folder = m_system_param.config_Root_Path;
|
|
|
|
|
|
int re = m_pConfigManager->LoadAnalysisConfig(folder);
|
|
|
|
|
|
for (const auto &pair : m_pConfigManager->Config_instances_)
|
|
|
{
|
|
|
std::cout << "cam: " << pair.first << std::endl;
|
|
|
}
|
|
|
// getchar();
|
|
|
return re;
|
|
|
}
|
|
|
int deal::StartThread(THREAD_RUN_TYPE type)
|
|
|
{
|
|
|
m_bExit = false;
|
|
|
// 只读图线程
|
|
|
if (type == THREAD_RUN_ALL)
|
|
|
{
|
|
|
|
|
|
// 开启检测线程
|
|
|
ptr_DealImgthread = std::make_shared<std::thread>(&deal::DealImg, this);
|
|
|
// 结果处理线程
|
|
|
// ptr_Resultthread = std::make_shared<std::thread>(&deal::ResultThread, this);
|
|
|
|
|
|
for (int i = 0; i < Save_IMG_THREAD_NUM; ++i)
|
|
|
{
|
|
|
// 创建线程,并使用 std::make_shared 创建 shared_ptr
|
|
|
std::shared_ptr<std::thread> threadPtr = std::make_shared<std::thread>(&deal::ResultThread, this, i);
|
|
|
// 将 shared_ptr 添加到 vector 中
|
|
|
ptr_ResultthreadList.push_back(threadPtr);
|
|
|
}
|
|
|
|
|
|
// 结果拷贝线程
|
|
|
ptr_GetResultthread = std::make_shared<std::thread>(&deal::GetResultThread, this);
|
|
|
}
|
|
|
|
|
|
InitProductReadThreadPool();
|
|
|
|
|
|
// for (int i = 0; i < READ_IMG_THREAD_NUM; ++i)
|
|
|
// {
|
|
|
// // 创建线程,并使用 std::make_shared 创建 shared_ptr
|
|
|
// std::shared_ptr<std::thread> threadPtr = std::make_shared<std::thread>(&deal::ReadImgThread, this, i);
|
|
|
// // 将 shared_ptr 添加到 vector 中
|
|
|
// threadArray.push_back(threadPtr);
|
|
|
// }
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::StopThread()
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::preCheck()
|
|
|
{
|
|
|
printf(">>> preCheck start \n");
|
|
|
|
|
|
std::string strRoot = "../data/img/t1";
|
|
|
std::string strProductID = "";
|
|
|
{
|
|
|
|
|
|
READ_IMG_INFO read;
|
|
|
readTestImg(read);
|
|
|
strRoot = read.strpath;
|
|
|
strProductID = read.strproduct;
|
|
|
printf("strSearchImg strRoot %s\n", strRoot.c_str());
|
|
|
|
|
|
std::ifstream file123(strRoot);
|
|
|
bool bhave = file123.good();
|
|
|
if (!bhave)
|
|
|
{
|
|
|
printf("read img path error %d %s\n", bhave, strRoot.c_str());
|
|
|
return 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取图片路径
|
|
|
std::string strSearchImg = strRoot;
|
|
|
|
|
|
LoadImage loader;
|
|
|
LoadConfig config;
|
|
|
config.Init();
|
|
|
|
|
|
printf("开始加载图片...\n\n");
|
|
|
std::vector<LoadProductImages> products = loader.LoadALLImg(strSearchImg, config, &m_image_ReadChannel, strProductID);
|
|
|
|
|
|
if (products.empty())
|
|
|
{
|
|
|
printf("未找到任何图片!\n");
|
|
|
printf("错误信息:%s\n", loader.getLastError().c_str());
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
printf("加载完成!\n");
|
|
|
printf("产品数量:%zu\n", products.size());
|
|
|
printf("图片总数:%zu\n\n", loader.getTotalLoaded());
|
|
|
for (size_t i = 0; i < products.size(); i++)
|
|
|
{
|
|
|
products[i].print("产品" + std::to_string(i + 1));
|
|
|
}
|
|
|
|
|
|
long t1 = getcurTime();
|
|
|
|
|
|
for (size_t i = 0; i < products.size(); i++)
|
|
|
{
|
|
|
|
|
|
CheckProduct(products[i]); // 处理单个产品
|
|
|
int getresultNum = 0;
|
|
|
// getchar();
|
|
|
while (true)
|
|
|
{
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟消费过程
|
|
|
// 处理结果
|
|
|
|
|
|
std::shared_ptr<CheckResult> checkResult;
|
|
|
int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult);
|
|
|
|
|
|
saveImg("/home/aidlux/BOE/FOG/testresult/", checkResult);
|
|
|
getresultNum++;
|
|
|
if (getresultNum == m_nProductSuccessCount)
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// }
|
|
|
printf(">>> ALL preCheck complete \n");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
std::string deal::readTestImg()
|
|
|
{
|
|
|
std::string strRoot = "../data/img/TestImg.json";
|
|
|
printf("Reading Img config %s\n", strRoot.c_str());
|
|
|
Json::CharReaderBuilder builder;
|
|
|
builder["collectComments"] = true;
|
|
|
Json::Value root;
|
|
|
std::string err;
|
|
|
std::ifstream ifs(strRoot);
|
|
|
if (!ifs.is_open())
|
|
|
{
|
|
|
printf("error:file is open\n");
|
|
|
return "";
|
|
|
}
|
|
|
if (!Json::parseFromStream(builder, ifs, &root, &err))
|
|
|
{
|
|
|
printf("error:parseFromStream\n");
|
|
|
return "";
|
|
|
}
|
|
|
std::string imgpath = "";
|
|
|
imgpath = root["TestImg_Path"].asString();
|
|
|
|
|
|
return imgpath;
|
|
|
}
|
|
|
|
|
|
int deal::readTestImg(READ_IMG_INFO &read)
|
|
|
{
|
|
|
std::string strRoot = "../data/img/TestImg.json";
|
|
|
printf("Reading Img config %s\n", strRoot.c_str());
|
|
|
Json::CharReaderBuilder builder;
|
|
|
builder["collectComments"] = true;
|
|
|
Json::Value root;
|
|
|
std::string err;
|
|
|
std::ifstream ifs(strRoot);
|
|
|
if (!ifs.is_open())
|
|
|
{
|
|
|
printf("error:file is open\n");
|
|
|
return 1;
|
|
|
}
|
|
|
if (!Json::parseFromStream(builder, ifs, &root, &err))
|
|
|
{
|
|
|
printf("error:parseFromStream\n");
|
|
|
return 1;
|
|
|
}
|
|
|
std::string imgpath = "";
|
|
|
read.strpath = root["TestImg_Path"].asString();
|
|
|
read.strproduct = root["ProductID"].asString();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::repeatCheck()
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::saveImg(std::string strpath, std::shared_ptr<CheckResult> result)
|
|
|
{
|
|
|
std::string strroot = strpath;
|
|
|
std::string strroot_qx = strpath;
|
|
|
if (result->in_shareImage->imgstr != "")
|
|
|
{
|
|
|
strroot += result->in_shareImage->imgstr;
|
|
|
strroot += "/";
|
|
|
strroot_qx += result->in_shareImage->imgstr;
|
|
|
strroot_qx += "/";
|
|
|
}
|
|
|
|
|
|
if (strpath != "")
|
|
|
{
|
|
|
|
|
|
strroot_qx += "qx/";
|
|
|
|
|
|
if (result->nProductResult != 0)
|
|
|
{
|
|
|
strroot += "NG/";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
strroot += "OK/";
|
|
|
}
|
|
|
|
|
|
if (result->in_shareImage->strImgProductID != "")
|
|
|
{
|
|
|
strroot += result->in_shareImage->strImgProductID + "/";
|
|
|
}
|
|
|
|
|
|
if (result->nresult != 0)
|
|
|
{
|
|
|
strroot += "NG/";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (result->nYS_result != 0)
|
|
|
{
|
|
|
strroot += "OK/YS/";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
strroot += "OK/OK/";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
printf("result->nresult %d %d \n", result->nresult, result->nYS_result);
|
|
|
printf("%s\n", strroot.c_str());
|
|
|
_sysmkdirs_1(strroot);
|
|
|
std::string str_saveName = "";
|
|
|
// getchar();
|
|
|
if (result->in_shareImage->strImgProductID != "")
|
|
|
{
|
|
|
strroot += result->in_shareImage->strImgProductID;
|
|
|
str_saveName += result->in_shareImage->strImgProductID;
|
|
|
}
|
|
|
|
|
|
if (result->in_shareImage->strImgName != "")
|
|
|
{
|
|
|
strroot += "_" + result->in_shareImage->strImgName;
|
|
|
str_saveName += "_" + result->in_shareImage->strImgName;
|
|
|
}
|
|
|
{
|
|
|
strroot += "_" + result->in_shareImage->strCameraName;
|
|
|
str_saveName += "_" + result->in_shareImage->strCameraName;
|
|
|
strroot += "_" + result->in_shareImage->strChannel;
|
|
|
str_saveName += "_" + result->in_shareImage->strChannel;
|
|
|
}
|
|
|
|
|
|
writeLog(strroot, result->det_LogList);
|
|
|
WriteJsonString(strroot, result->strResultJson);
|
|
|
// printf("%s \n", strroot.c_str());
|
|
|
std::string str = strroot + "_RE_Resultimg.png";
|
|
|
if (!result->resultimg.empty())
|
|
|
{
|
|
|
cv::imwrite(str, result->resultimg);
|
|
|
}
|
|
|
std::string str123 = strroot + "_RE_CutImg.png";
|
|
|
if (!result->cutSrcimg.empty())
|
|
|
{
|
|
|
cv::imwrite(str123, result->cutSrcimg);
|
|
|
}
|
|
|
std::string str123r = strroot + "_RE_CutDrawImg.png";
|
|
|
if (!result->SrcResultImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str123r, result->SrcResultImg);
|
|
|
}
|
|
|
std::string strMask = strroot + "_RE_AIMask.png";
|
|
|
|
|
|
if (!result->resultMaskImg.empty())
|
|
|
{
|
|
|
cv::imwrite(strMask, result->resultMaskImg);
|
|
|
}
|
|
|
std::string str_qx;
|
|
|
printf("result->qxImageResult.size() %ld \n", result->qxImageResult.size());
|
|
|
for (int i = 0; i < result->qxImageResult.size(); i++)
|
|
|
{
|
|
|
std::string str = strroot + "_RE_" + std::to_string(i) + "_Src.png";
|
|
|
|
|
|
if (!result->qxImageResult.at(i).srcImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str, result->qxImageResult.at(i).srcImg);
|
|
|
}
|
|
|
|
|
|
str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/";
|
|
|
printf("-1-- %s\n", str_qx.c_str());
|
|
|
_sysmkdirs_1(str_qx);
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_Src.png";
|
|
|
// printf("-2-- %s\n", str_qx.c_str());
|
|
|
|
|
|
if (!result->qxImageResult.at(i).srcImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->qxImageResult.at(i).srcImg);
|
|
|
}
|
|
|
str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/";
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_Small.png";
|
|
|
|
|
|
if (!result->qxImageResult.at(i).resizeImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->qxImageResult.at(i).resizeImg);
|
|
|
}
|
|
|
|
|
|
{
|
|
|
str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/";
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_AI_In.png";
|
|
|
if (!result->qxImageResult.at(i).AI_in_Img.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->qxImageResult.at(i).AI_in_Img);
|
|
|
}
|
|
|
|
|
|
str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/";
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_AI_In_mask.png";
|
|
|
if (!result->qxImageResult.at(i).AI_out_img.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->qxImageResult.at(i).AI_out_img);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// printf("-1111-- %s\n", str_qx.c_str());
|
|
|
std::string str1 = strroot + "_RE_" + std::to_string(i) + "_Small.png";
|
|
|
|
|
|
if (!result->qxImageResult.at(i).resizeImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str1, result->qxImageResult.at(i).resizeImg);
|
|
|
}
|
|
|
}
|
|
|
printf("result->YS_ImageResult.size() %ld\n", result->YS_ImageResult.size());
|
|
|
for (int i = 0; i < result->YS_ImageResult.size(); i++)
|
|
|
{
|
|
|
std::string str = strroot + "_RE_" + std::to_string(i) + "_YS_Src.png";
|
|
|
if (result->YS_ImageResult.at(i).srcImg.empty())
|
|
|
{
|
|
|
printf("resqwwwwwwwwwwwwwwwult->YS_ImageResult.size() %ld \n", result->YS_ImageResult.size());
|
|
|
}
|
|
|
|
|
|
if (!result->YS_ImageResult.at(i).srcImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str, result->YS_ImageResult.at(i).srcImg);
|
|
|
}
|
|
|
str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/";
|
|
|
// printf("-3-- %s\n", str_qx.c_str());
|
|
|
_sysmkdirs_1(str_qx);
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_Src.png";
|
|
|
// printf("-4-- %s\n", str_qx.c_str());
|
|
|
|
|
|
if (!result->YS_ImageResult.at(i).srcImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->YS_ImageResult.at(i).srcImg);
|
|
|
}
|
|
|
str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/";
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_Small.png";
|
|
|
|
|
|
if (!result->YS_ImageResult.at(i).resizeImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->YS_ImageResult.at(i).resizeImg);
|
|
|
}
|
|
|
{
|
|
|
str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/";
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_AI_In.png";
|
|
|
if (!result->YS_ImageResult.at(i).AI_in_Img.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->YS_ImageResult.at(i).AI_in_Img);
|
|
|
}
|
|
|
|
|
|
str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/";
|
|
|
str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_AI_In_mask.png";
|
|
|
if (!result->YS_ImageResult.at(i).AI_out_img.empty())
|
|
|
{
|
|
|
cv::imwrite(str_qx, result->YS_ImageResult.at(i).AI_out_img);
|
|
|
}
|
|
|
}
|
|
|
// printf("-1111-- %s\n", str_qx.c_str());
|
|
|
std::string str1 = strroot + "_RE_" + std::to_string(i) + "_YS_Small.png";
|
|
|
|
|
|
if (!result->YS_ImageResult.at(i).resizeImg.empty())
|
|
|
{
|
|
|
cv::imwrite(str1, result->YS_ImageResult.at(i).resizeImg);
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::writeLog(std::string strSavePath, std::vector<std::string> logList)
|
|
|
{
|
|
|
std::string str = strSavePath + ".txt";
|
|
|
// 打开文件
|
|
|
std::ofstream outFile(str);
|
|
|
|
|
|
// 检查文件是否成功打开
|
|
|
if (!outFile)
|
|
|
{
|
|
|
std::cerr << "Failed to open file." << std::endl;
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
// 将vector中的内容写入文件
|
|
|
for (const auto &str : logList)
|
|
|
{
|
|
|
// printf("%s \n",str.c_str());
|
|
|
outFile << str << std::endl;
|
|
|
}
|
|
|
|
|
|
// 关闭文件
|
|
|
outFile.close();
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::WriteJsonString(std::string strSavePath, std::string strjson)
|
|
|
{
|
|
|
|
|
|
std::string str = strSavePath + ".json";
|
|
|
// 打开文件
|
|
|
std::ofstream outFile(str);
|
|
|
|
|
|
// 检查文件是否成功打开
|
|
|
if (!outFile)
|
|
|
{
|
|
|
std::cerr << "Failed to open file." << std::endl;
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
// 将vector中的内容写入文件
|
|
|
outFile << strjson << std::endl;
|
|
|
|
|
|
// 关闭文件
|
|
|
outFile.close();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void deal::ResultThread(int id)
|
|
|
{
|
|
|
std::vector<int> vi;
|
|
|
int startidx = m_CPUInfo[THREAD_CPU_Main_saveImg].startIdx;
|
|
|
int cpunum = m_CPUInfo[THREAD_CPU_Main_saveImg].num;
|
|
|
// for (int i = 0; i < cpunum; i++)
|
|
|
// {
|
|
|
// vi.push_back(startidx + i);
|
|
|
// }
|
|
|
vi.push_back(startidx + id);
|
|
|
auto nRet = set_cpu_id(vi);
|
|
|
printf("THREAD_CPU_Main_saveImg %d bind cpu ret %d startidx %d num %d\n", id, nRet, startidx + id, 1);
|
|
|
|
|
|
int re = 0;
|
|
|
cv::Mat detImg;
|
|
|
int kkkkk = 0;
|
|
|
static int saveidx = 0;
|
|
|
while (!m_bExit)
|
|
|
{
|
|
|
std::shared_ptr<CheckResult> dealResult;
|
|
|
mutex_Result_list.lock();
|
|
|
if (m_Result_list.size() > 0)
|
|
|
{
|
|
|
dealResult = m_Result_list.front();
|
|
|
m_Result_list.pop();
|
|
|
if (m_Result_list.size() > 10)
|
|
|
{
|
|
|
printf("Result_list size %ld \n", m_Result_list.size());
|
|
|
}
|
|
|
|
|
|
mutex_Result_list.unlock();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
mutex_Result_list.unlock();
|
|
|
usleep(10000);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
{
|
|
|
updataResltInfo(dealResult);
|
|
|
}
|
|
|
|
|
|
{
|
|
|
if (true)
|
|
|
{
|
|
|
// 存图
|
|
|
std::string savepath = "/home/aidlux/BOE/FOG/Detsave/";
|
|
|
saveImg(savepath, dealResult);
|
|
|
// saveImg("/home/aidlux/BOE/ResultImg/", dealResult);
|
|
|
}
|
|
|
|
|
|
{
|
|
|
// 存 检测统计 日志
|
|
|
mutex_DetResult_.lock();
|
|
|
m_DetResult.print(false);
|
|
|
std::string strlog = "/home/aidlux/BOE/FOG/ResultImg/";
|
|
|
if (m_strCurDate != "")
|
|
|
{
|
|
|
strlog += m_strCurDate;
|
|
|
strlog += "/result";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
strlog += "/result";
|
|
|
}
|
|
|
|
|
|
writeLog(strlog, m_DetResult.strlist);
|
|
|
mutex_DetResult_.unlock();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
usleep(5 * 1000);
|
|
|
}
|
|
|
}
|
|
|
int deal::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;
|
|
|
}
|
|
|
|
|
|
void deal::GetDealResultToQueu()
|
|
|
{
|
|
|
|
|
|
// 处理结果
|
|
|
|
|
|
std::shared_ptr<CheckResult> checkResult;
|
|
|
if (!m_pALLImgCheckAnalysisy)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult);
|
|
|
|
|
|
if (re == 0)
|
|
|
{
|
|
|
mutex_Result_list.lock();
|
|
|
m_Result_list.push(checkResult);
|
|
|
mutex_Result_list.unlock();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("Check error >>>>>>>>>>>>>>>>> \n");
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
bool deal::ReadSystemConfig(const std::string &strPath)
|
|
|
{
|
|
|
|
|
|
printf("Reading system config %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;
|
|
|
}
|
|
|
m_system_param.Use_CPU_StartIdx = root["Use_CPU_StartIdx"].asInt();
|
|
|
m_system_param.nWorkIdx = root["Detect_Work_Idx"].asInt();
|
|
|
m_system_param.config_Root_Path = root["Config_Root_Path"].asString();
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
m_system_param.GPU_Device_ID_List[i] = -1;
|
|
|
if (root.isMember("GPU_Device_ID_List"))
|
|
|
{
|
|
|
auto &arr = root["GPU_Device_ID_List"];
|
|
|
for (int i = 0; i < arr.size() && i < 4; i++)
|
|
|
{
|
|
|
m_system_param.GPU_Device_ID_List[i] = arr[i].asInt();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_nCurUseCPUIDX = m_system_param.Use_CPU_StartIdx;
|
|
|
|
|
|
return m_system_param.valid();
|
|
|
}
|
|
|
int deal::GetJcImageInfo(std::string strpath, std::vector<JC_IMAGE_INFO_> &jcImageInfoList)
|
|
|
{
|
|
|
LoadOfflineCheckImg(strpath);
|
|
|
jcImageInfoList.erase(jcImageInfoList.begin(), jcImageInfoList.end());
|
|
|
|
|
|
// 遍历每一套图片
|
|
|
for (int idx = 0; idx < m_OffLineCheckImgNameList.size(); idx++)
|
|
|
{
|
|
|
std::string path = m_OffLineCheckImgNameList.at(idx);
|
|
|
JC_IMAGE_INFO_ tem;
|
|
|
int re = GetImgInfo_POL_ET(path, &tem);
|
|
|
}
|
|
|
// getchar();
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector<JC_IMAGE_INFO_> &jcImageInfoList)
|
|
|
{
|
|
|
// 1、获取图片路径
|
|
|
std::vector<cv::String> img_paths;
|
|
|
std::string strs1 = strSearchImg + "/*.ytimage";
|
|
|
cv::glob(strs1, img_paths, true);
|
|
|
printf("%ld \n", img_paths.size());
|
|
|
|
|
|
jcImageInfoList.erase(jcImageInfoList.begin(), jcImageInfoList.end());
|
|
|
|
|
|
// 遍历每一套图片
|
|
|
for (int idx = 0; idx < img_paths.size(); idx++)
|
|
|
{
|
|
|
// printf("---- %d / %d %s----\n", idx, m_OffLineCheckImgNameList.size(), m_OffLineCheckImgNameList.at(idx).c_str());
|
|
|
|
|
|
std::string path = img_paths.at(idx);
|
|
|
|
|
|
JC_IMAGE_INFO_ tem;
|
|
|
int re = 0;
|
|
|
{
|
|
|
re = GetImgInfo_POL_ET(path, &tem);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
tem.strProductID = strProductID;
|
|
|
|
|
|
jcImageInfoList.push_back(tem);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::GetImgInfo_POL_ET(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo)
|
|
|
{
|
|
|
|
|
|
if (pImageInfo == NULL)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
string strName = ExtractFileNameWithoutExtension(strImgPath);
|
|
|
printf("strName %s \n", strName.c_str());
|
|
|
size_t lastUnderscore = strName.rfind('_');
|
|
|
if (lastUnderscore == std::string::npos)
|
|
|
return 1; // 没有找到最后一个 '_'
|
|
|
|
|
|
std::string strImageChannel = strName.substr(0, lastUnderscore);
|
|
|
|
|
|
printf("strImageChannel %s\n", strImageChannel.c_str());
|
|
|
|
|
|
if (strImageChannel == "CA" || strImageChannel == "TA")
|
|
|
{
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
pImageInfo->strchannelName = strImageChannel;
|
|
|
pImageInfo->strName = strName;
|
|
|
pImageInfo->strPath = strImgPath;
|
|
|
pImageInfo->strCamID = "0";
|
|
|
printf("strImgPath %s strName %s strChannel %s\n", strImgPath.c_str(), strName.c_str(), strImageChannel.c_str());
|
|
|
|
|
|
// 使用 find 函数检查是否包含 "_左"
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo)
|
|
|
{
|
|
|
|
|
|
if (pImageInfo == NULL)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
string strImageChannel = ExtractFileNameWithoutExtension(strImgPath);
|
|
|
printf("strImageChannel %s\n", strImageChannel.c_str());
|
|
|
std::string strChannle = m_image_ReadChannel.strDetName(strImageChannel);
|
|
|
if (strChannle == "")
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
pImageInfo->strchannelName = strChannle;
|
|
|
pImageInfo->strName = strChannle;
|
|
|
pImageInfo->strPath = strImgPath;
|
|
|
pImageInfo->strCamID = "0";
|
|
|
// printf("strImgPath %s strChannel %s\n", strImgPath.c_str(), strChannle.c_str());
|
|
|
|
|
|
// 使用 find 函数检查是否包含 "_左"
|
|
|
if (strImgPath.find("_工位右") != std::string::npos)
|
|
|
{
|
|
|
pImageInfo->strCamID = "1";
|
|
|
;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::ReadTestImgaData()
|
|
|
{
|
|
|
std::string strPath = "../data/testImg.json";
|
|
|
printf("ReadTestImgaData config %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;
|
|
|
}
|
|
|
m_TestJC_ImageDate.erase(m_TestJC_ImageDate.begin(), m_TestJC_ImageDate.end());
|
|
|
{
|
|
|
auto value = root["img_date"];
|
|
|
if (value.isObject())
|
|
|
{
|
|
|
auto arr = value["date"];
|
|
|
std::cout << arr << std::endl;
|
|
|
if (arr.isArray())
|
|
|
{
|
|
|
|
|
|
// 遍历数组中的每个元素
|
|
|
for (int i = 0; i < arr.size(); i++)
|
|
|
{
|
|
|
|
|
|
// 读取对象中的属性值
|
|
|
std::string strdata = arr[i].asString();
|
|
|
m_TestJC_ImageDate.push_back(strdata);
|
|
|
|
|
|
// 输出属性值
|
|
|
std::cout << "date: " << strdata << std::endl;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// getchar();
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::InitDetData()
|
|
|
{
|
|
|
m_read_ImgNum = 0;
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::InsertDetResult(ReadImgInfo tem)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_DetResult]);
|
|
|
m_DetResultList.push_back(tem);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::GetUpMaskImg(cv::Mat inImg, cv::Rect roi, cv::Mat &maskimg)
|
|
|
{
|
|
|
// 定义滑动窗口的大小和步长
|
|
|
int windowWidth = 128;
|
|
|
int windowHeight = 128;
|
|
|
int stepX = 110; // 横向步长
|
|
|
int stepY = 110; // 纵向步长
|
|
|
|
|
|
maskimg = cv::Mat(roi.height, roi.width, CV_8U, cv::Scalar(0));
|
|
|
int sx = roi.x;
|
|
|
int ex = roi.x + roi.width;
|
|
|
int sy = roi.y;
|
|
|
int ey = roi.y + roi.height;
|
|
|
|
|
|
cv::Rect detroi;
|
|
|
detroi.width = windowWidth;
|
|
|
detroi.height = windowHeight;
|
|
|
cv::Rect maskroi;
|
|
|
maskroi.width = windowWidth;
|
|
|
maskroi.height = windowHeight;
|
|
|
cv::Mat temmask;
|
|
|
// 遍历图像,使用滑动窗口
|
|
|
for (int y = sy; y <= ey; y += stepY)
|
|
|
{
|
|
|
detroi.y = y;
|
|
|
if (detroi.y + windowHeight > ey)
|
|
|
{
|
|
|
detroi.y = ey - windowHeight;
|
|
|
}
|
|
|
maskroi.y = detroi.y - sy;
|
|
|
|
|
|
for (int x = sx; x <= ex; x += stepX)
|
|
|
{
|
|
|
detroi.x = x;
|
|
|
if (detroi.x + windowWidth > ex)
|
|
|
{
|
|
|
detroi.x = ex - windowWidth;
|
|
|
}
|
|
|
maskroi.x = detroi.x - sx;
|
|
|
int thresholdValue = 30; // 初始阈值,OTSU将自动计算
|
|
|
int maxVal = 255; // 最大值
|
|
|
double otsuThreshold;
|
|
|
|
|
|
cv::Scalar mean, stddev;
|
|
|
cv::meanStdDev(inImg(detroi), mean, stddev);
|
|
|
|
|
|
int varianceImg;
|
|
|
varianceImg = mean[0] + 1 * mean[0];
|
|
|
if (mean[0] > 100)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// 使用 OTSU 阈值处理
|
|
|
otsuThreshold = cv::threshold(inImg(detroi), temmask, thresholdValue, maxVal, cv::THRESH_BINARY | cv::THRESH_OTSU);
|
|
|
thresholdValue = otsuThreshold;
|
|
|
|
|
|
if (thresholdValue < 30)
|
|
|
{
|
|
|
thresholdValue = 30;
|
|
|
}
|
|
|
if (thresholdValue < varianceImg)
|
|
|
{
|
|
|
thresholdValue = varianceImg;
|
|
|
}
|
|
|
|
|
|
if (thresholdValue > 100)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
// std::cout << "varianceImg value is: " << varianceImg << std::endl;
|
|
|
// std::cout << "OTSU threshold value is: " << otsuThreshold << std::endl;
|
|
|
// std::cout << "stddev[0] value is: " << stddev[0] << std::endl;
|
|
|
otsuThreshold = cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY);
|
|
|
// cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY + cv::THRESH_OTSU);
|
|
|
// 提取当前窗口
|
|
|
|
|
|
// cv::rectangle(inImg, detroi, cv::Scalar(255, 0, 0));
|
|
|
}
|
|
|
}
|
|
|
// cv::imwrite("inImg1123.png", inImg);
|
|
|
// cv::imwrite("maskimg.png", maskimg);
|
|
|
// getchar();
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::ReJson()
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::ReJson_ALL()
|
|
|
{
|
|
|
printf(">>> ReJson ALL start \n");
|
|
|
|
|
|
// 1、获取所有的json
|
|
|
std::vector<cv::String> img_paths;
|
|
|
cv::glob(runConfig.filePath + "/*.json", img_paths, true);
|
|
|
if (img_paths.size() <= 0)
|
|
|
{
|
|
|
printf("json file is NULL \n");
|
|
|
return 1;
|
|
|
/* code */
|
|
|
}
|
|
|
// 用map存储每个id对应的vector
|
|
|
std::unordered_map<std::string, std::vector<cv::String>> ProductJsonList;
|
|
|
// 遍历路径并按照ID分组
|
|
|
for (const auto &path : img_paths)
|
|
|
{
|
|
|
// 获取路径中的 ID 部分(即文件夹名部分)
|
|
|
size_t start_pos = path.find_last_of("/") + 1;
|
|
|
size_t end_pos = path.find("_", start_pos);
|
|
|
std::string id = path.substr(start_pos, end_pos - start_pos);
|
|
|
// printf("id %s\n",id.c_str());
|
|
|
// 将文件路径加入对应 ID 的vector中
|
|
|
ProductJsonList[id].push_back(path);
|
|
|
}
|
|
|
for (const auto &product : ProductJsonList)
|
|
|
{
|
|
|
std::cout << product.first << " => " << product.second.size() << std::endl;
|
|
|
std::vector<Json_Det_Path> jsonList;
|
|
|
std::string strProductName = product.first;
|
|
|
for (const auto &str : product.second)
|
|
|
{
|
|
|
{
|
|
|
// 2、获取第一个 名称
|
|
|
std::string strPath = str;
|
|
|
size_t lastSlashPos = strPath.find_last_of('/');
|
|
|
// 提取文件名(从最后一个斜杠之后的部分)
|
|
|
std::string filename = strPath.substr(lastSlashPos + 1);
|
|
|
// 查找文件名中的第一个下划线位置
|
|
|
size_t firstUnderscorePos = filename.find('_');
|
|
|
// 提取文件名中的名称部分(下划线之前的字符串)
|
|
|
std::string strProduct = filename.substr(0, firstUnderscorePos);
|
|
|
// printf("strProduct %s \n", strProduct.c_str());
|
|
|
if (strProduct == strProductName)
|
|
|
{
|
|
|
Json_Det_Path tem;
|
|
|
tem.strPath_Json = str;
|
|
|
tem.strPath_CutImg = str;
|
|
|
size_t pos = tem.strPath_CutImg.rfind(".json");
|
|
|
|
|
|
if (pos != std::string::npos)
|
|
|
{
|
|
|
// 替换 ".json" 为 "_RE_CutImg.png"
|
|
|
tem.strPath_CutImg.replace(pos, 5, "_RE_CutImg.png");
|
|
|
}
|
|
|
std::cout << " Path: " << tem.strPath_Json << std::endl;
|
|
|
std::cout << " Path: " << tem.strPath_CutImg << std::endl;
|
|
|
jsonList.push_back(tem);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ReJson_product(jsonList, strProductName);
|
|
|
}
|
|
|
|
|
|
// 获取要检测的 json 图片 list
|
|
|
|
|
|
printf(">>>>>>>>>>>>>>>>>>>> rejson ALL is Complete \n");
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::DetImg()
|
|
|
{
|
|
|
// 单张检测
|
|
|
if (runConfig.det_Type == RUNTYPE_RUN_Pre)
|
|
|
{
|
|
|
m_nReadThread_type = READ_THREAD_TYPE_READIMG;
|
|
|
StartThread(THREAD_RUN_Only_ReadImg);
|
|
|
preCheck();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
m_nReadThread_type = READ_THREAD_TYPE_READIMG;
|
|
|
m_nSystemCheckType = CHECK_TYPE_OFFLING;
|
|
|
|
|
|
StartThread(THREAD_RUN_ALL);
|
|
|
// 文件夹套图处理
|
|
|
if (RUNTYPE_RUN_File == runConfig.det_Type ||
|
|
|
runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST ||
|
|
|
runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_Qx ||
|
|
|
runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_ALL)
|
|
|
{
|
|
|
CheckFileImg(); // 检查文件图片
|
|
|
}
|
|
|
// getchar();
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/// @brief 检查文件图片
|
|
|
/// @detail 后续实现具体功能
|
|
|
/// @return 0 表示成功
|
|
|
int deal::CheckFileImg()
|
|
|
{
|
|
|
std::string root_dir = runConfig.filePath;
|
|
|
printf("测试目录:%s\n\n", root_dir.c_str());
|
|
|
|
|
|
LoadImage loader;
|
|
|
LoadConfig config;
|
|
|
config.Init();
|
|
|
config.max_products = runConfig.m_nTestNum;
|
|
|
if (config.max_products <= 0)
|
|
|
{
|
|
|
config.max_products = 9999999;
|
|
|
}
|
|
|
|
|
|
printf("开始加载图片...\n\n");
|
|
|
std::vector<LoadProductImages> products = loader.LoadALLImg(root_dir, config, &m_image_ReadChannel);
|
|
|
|
|
|
if (products.empty())
|
|
|
{
|
|
|
printf("未找到任何图片!\n");
|
|
|
printf("错误信息:%s\n", loader.getLastError().c_str());
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
printf("加载完成!\n");
|
|
|
printf("产品数量:%zu\n", products.size());
|
|
|
printf("图片总数:%zu\n\n", loader.getTotalLoaded());
|
|
|
for (size_t i = 0; i < products.size(); i++)
|
|
|
{
|
|
|
products[i].print("产品" + std::to_string(i + 1));
|
|
|
}
|
|
|
// getchar();
|
|
|
for (size_t i = 0; i < products.size(); i++)
|
|
|
{
|
|
|
|
|
|
CheckProduct(products[i]); // 处理单个产品
|
|
|
}
|
|
|
printf("\n");
|
|
|
|
|
|
// TODO: 后续实现具体功能
|
|
|
// getchar();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/// @brief 检查单个产品
|
|
|
/// @param product 产品信息(包含图片对列表)
|
|
|
/// @return 0 表示成功
|
|
|
int deal::CheckProduct(const LoadProductImages &product)
|
|
|
{
|
|
|
// 1. 统计图片对总数
|
|
|
size_t totalImgNum = product.images.size();
|
|
|
|
|
|
if (runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST)
|
|
|
{
|
|
|
totalImgNum = 0;
|
|
|
for (const auto &image : product.images)
|
|
|
{
|
|
|
if (image.channel_name == "L255")
|
|
|
{
|
|
|
totalImgNum++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (totalImgNum == 0)
|
|
|
{
|
|
|
printf("[产品] %s 没有图片对\n", product.product_id.c_str());
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
// 2. 重置计数器(重要!每个产品独立计数)
|
|
|
m_nProductPendingTasks = 0;
|
|
|
m_nProductSuccessCount = 0;
|
|
|
m_nProductFailCount = 0;
|
|
|
m_ProductFailedList.clear();
|
|
|
m_nCheckNotifiedCount = 0;
|
|
|
|
|
|
// 3. 打印产品信息
|
|
|
printf("\n");
|
|
|
printf("╔══════════════════════════════════════════════════════════\n");
|
|
|
printf("║ 产品:%s\n", product.product_id.c_str());
|
|
|
printf("║ 图片对数:%zu\n", totalImgNum);
|
|
|
printf("╚══════════════════════════════════════════════════════════\n\n");
|
|
|
|
|
|
// 4. 分发读图任务
|
|
|
printf("[任务分发] 开始向读图线程分发 %zu 个任务...\n", totalImgNum);
|
|
|
DistributeProductTasks(product);
|
|
|
printf("[任务分发] 完成\n\n");
|
|
|
|
|
|
// 5. 使用条件变量等待并处理通知队列
|
|
|
int processed = 0;
|
|
|
{
|
|
|
IN_IMG_Status_ temstatus = IN_IMG_Status_Start;
|
|
|
std::unique_lock<std::mutex> lock(m_checkNotifyMutex);
|
|
|
|
|
|
while (processed < (int)totalImgNum)
|
|
|
{
|
|
|
// 等待通知:队列非空 或 所有任务已完成
|
|
|
m_checkNotifyCV.wait_for(lock, std::chrono::milliseconds(100),
|
|
|
[this, &processed, totalImgNum]()
|
|
|
{
|
|
|
return !m_checkNotifyQueue.empty() || m_nCheckNotifiedCount.load() >= (int)totalImgNum;
|
|
|
});
|
|
|
|
|
|
// 消费队列中的所有通知
|
|
|
while (!m_checkNotifyQueue.empty())
|
|
|
{
|
|
|
auto info = m_checkNotifyQueue.front();
|
|
|
m_checkNotifyQueue.pop();
|
|
|
|
|
|
// 处理图片对
|
|
|
SendCheckImg(info, temstatus, false);
|
|
|
processed++;
|
|
|
|
|
|
if (IN_IMG_Status_Start == temstatus)
|
|
|
{
|
|
|
temstatus = IN_IMG_Status_Other;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// 注:不需要第二个 while 清理,因为第一个 while 退出时 processed == totalImgNum
|
|
|
// 队列中不可能还有未处理的项目(内层 while 已经消费完)
|
|
|
}
|
|
|
CheckImgNotifyInfo info;
|
|
|
info.productId = product.product_id;
|
|
|
SendCheckImg(info, IN_IMG_Status_End, true);
|
|
|
printf("\n");
|
|
|
|
|
|
// 6. 打印统计(不清理线程,继续下一个产品)
|
|
|
PrintProductStatistics(product);
|
|
|
// getchar();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::SendCheckImg(const CheckImgNotifyInfo &info, IN_IMG_Status_ status, bool bComplete)
|
|
|
{
|
|
|
|
|
|
// 发送结束标志
|
|
|
if (bComplete)
|
|
|
{
|
|
|
std::shared_ptr<shareImage> tem = std::make_shared<shareImage>();
|
|
|
tem->strImgProductID = info.productId;
|
|
|
tem->Status = -1;
|
|
|
if (m_pALLImgCheckAnalysisy)
|
|
|
{
|
|
|
m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
// 图片读取有异常,处理失败的图片对
|
|
|
if (!info.success)
|
|
|
{
|
|
|
// 记录失败
|
|
|
FailedImgRecord record;
|
|
|
record.left_path = info.left_path;
|
|
|
record.right_path = info.right_path;
|
|
|
record.productId = info.productId;
|
|
|
record.channelName = info.channelName;
|
|
|
record.errorReason = info.errorReason;
|
|
|
RecordFailedImg(record);
|
|
|
|
|
|
m_nProductFailCount.fetch_add(1);
|
|
|
|
|
|
printf("[失败-%3d] %s | %s | %s\n",
|
|
|
info.taskIndex,
|
|
|
info.productId.c_str(),
|
|
|
info.channelName.c_str(),
|
|
|
info.errorReason.c_str());
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
// printf("[%3d] %s | %d | %s | %s | %s | 左:%dx%d 右:%dx%d | 耗时:%ldms\n",
|
|
|
// info.taskIndex,
|
|
|
// info.productId.c_str(),
|
|
|
// info.camera_Num,
|
|
|
// info.cameraSide.c_str(),
|
|
|
// info.channelName.c_str(),
|
|
|
// info.imageName.c_str(),
|
|
|
// info.left_img.cols, info.left_img.rows,
|
|
|
// info.right_img.cols, info.right_img.rows,
|
|
|
// info.readTimeMs);
|
|
|
|
|
|
m_nProductSuccessCount.fetch_add(1);
|
|
|
|
|
|
std::shared_ptr<shareImage> tem = std::make_shared<shareImage>();
|
|
|
|
|
|
tem->strChannel = info.channelName;
|
|
|
|
|
|
// cv::imwrite(tem->strChannel + "_new_debug.png", info.left_img);
|
|
|
// return 0;
|
|
|
// cv::imwrite(tem->strChannel+".png",pDetImageInfo->img);
|
|
|
tem->nImgBigIdx = 0;
|
|
|
tem->strImgName = info.imageName;
|
|
|
tem->strImgProductID = info.productId;
|
|
|
tem->imgstr = m_strCurDate;
|
|
|
|
|
|
if (runConfig.bDebugSaveImg == 1)
|
|
|
{
|
|
|
tem->otherValue = 9;
|
|
|
}
|
|
|
tem->getImgTimeMs = getcurTime();
|
|
|
tem->Status = status;
|
|
|
tem->Det_Mode = DET_MODE_Det;
|
|
|
if (runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST)
|
|
|
{
|
|
|
tem->Det_Mode = DET_MODE_EDGE;
|
|
|
}
|
|
|
if (runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_Qx || runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_ALL)
|
|
|
{
|
|
|
tem->ninstruct = 767;
|
|
|
if (runConfig.det_Type == RUNTYPE_RUN_File_Edge_Test_Save_ALL)
|
|
|
{
|
|
|
tem->ninstruct = 768;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
{
|
|
|
if (!info.left_img.empty())
|
|
|
{
|
|
|
tem->img = info.left_img;
|
|
|
}
|
|
|
else if (!info.right_img.empty())
|
|
|
{
|
|
|
tem->img = info.right_img;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
tem->strCameraName = info.cameraSide;
|
|
|
tem->camera_ID = 0;
|
|
|
|
|
|
if (runConfig.bDebugSaveImg == 1)
|
|
|
{
|
|
|
tem->bDebugsaveImg = true;
|
|
|
}
|
|
|
|
|
|
int re = 0;
|
|
|
if (m_pALLImgCheckAnalysisy)
|
|
|
{
|
|
|
bool bcontinue = false;
|
|
|
do
|
|
|
{
|
|
|
re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem);
|
|
|
if (re == 8)
|
|
|
{
|
|
|
bcontinue = true;
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
bcontinue = false;
|
|
|
}
|
|
|
|
|
|
} while (bcontinue);
|
|
|
}
|
|
|
|
|
|
return re;
|
|
|
}
|
|
|
|
|
|
// ============ 产品检测线程池相关函数 ============
|
|
|
|
|
|
void deal::InitProductReadThreadPool()
|
|
|
{
|
|
|
printf("[线程池] 初始化产品检测线程池...\n");
|
|
|
|
|
|
// 创建 8 个读图线程
|
|
|
for (int i = 0; i < m_nProductReadThreadNum; i++)
|
|
|
{
|
|
|
auto thread = std::make_shared<std::thread>(
|
|
|
&deal::ProductReadImgThreadFunc, this, i);
|
|
|
m_productReadThreads.push_back(thread);
|
|
|
}
|
|
|
|
|
|
printf("[线程池] 创建完成 (%d 读图线程)\n", m_nProductReadThreadNum);
|
|
|
}
|
|
|
|
|
|
void deal::DestroyProductReadThreadPool()
|
|
|
{
|
|
|
printf("[线程池] 销毁产品检测线程池...\n");
|
|
|
|
|
|
// 通知所有线程退出
|
|
|
m_bProductReadExit = true;
|
|
|
m_productTaskCV.notify_all();
|
|
|
m_checkNotifyCV.notify_all();
|
|
|
|
|
|
// 等待读图线程结束
|
|
|
for (auto &thread : m_productReadThreads)
|
|
|
{
|
|
|
if (thread && thread->joinable())
|
|
|
{
|
|
|
thread->join();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_productReadThreads.clear();
|
|
|
|
|
|
printf("[线程池] 销毁完成\n");
|
|
|
}
|
|
|
|
|
|
void deal::DistributeProductTasks(const LoadProductImages &product)
|
|
|
{
|
|
|
int taskIndex = 0;
|
|
|
|
|
|
for (const auto &image : product.images)
|
|
|
{
|
|
|
if (runConfig.det_Type == RUNTYPE_RUN_File_AI_TEST)
|
|
|
{
|
|
|
if (image.channel_name != "L255")
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
auto task = std::make_shared<ReadImgTask>();
|
|
|
task->productId = product.product_id;
|
|
|
task->channelName = image.channel_name;
|
|
|
task->imageName = image.image_name; // 图片名称
|
|
|
task->left_path = image.left_path;
|
|
|
task->right_path = image.right_path;
|
|
|
task->camera_Num = product.camera_Num;
|
|
|
task->cameraSide = image.camera_side;
|
|
|
task->taskIndex = taskIndex++;
|
|
|
|
|
|
// 如果队列满了,等待
|
|
|
{
|
|
|
std::unique_lock<std::mutex> lock(m_productTaskMutex);
|
|
|
|
|
|
m_productTaskCV.wait(lock, [this]()
|
|
|
{ return m_productTaskQueue.size() < (size_t)m_nProductQueueMaxSize || m_bProductReadExit; });
|
|
|
|
|
|
if (m_bProductReadExit)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
m_productTaskQueue.push(task);
|
|
|
m_nProductPendingTasks.fetch_add(1);
|
|
|
}
|
|
|
m_productTaskCV.notify_one();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
std::shared_ptr<ReadImgTask> deal::GetProductTask()
|
|
|
{
|
|
|
std::shared_ptr<ReadImgTask> task;
|
|
|
|
|
|
std::unique_lock<std::mutex> lock(m_productTaskMutex);
|
|
|
if (m_productTaskCV.wait_for(lock, std::chrono::milliseconds(10),
|
|
|
[this]()
|
|
|
{ return !m_productTaskQueue.empty() || m_bProductReadExit; }))
|
|
|
{
|
|
|
|
|
|
if (m_productTaskQueue.empty())
|
|
|
{
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
task = m_productTaskQueue.front();
|
|
|
m_productTaskQueue.pop();
|
|
|
}
|
|
|
|
|
|
return task;
|
|
|
}
|
|
|
|
|
|
void deal::ProductReadImgThreadFunc(int threadId)
|
|
|
{
|
|
|
while (!m_bProductReadExit)
|
|
|
{
|
|
|
auto task = GetProductTask();
|
|
|
if (task == nullptr)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
CheckImgNotifyInfo info;
|
|
|
info.taskIndex = task->taskIndex;
|
|
|
info.productId = task->productId;
|
|
|
info.channelName = task->channelName;
|
|
|
info.imageName = task->imageName;
|
|
|
info.left_path = task->left_path;
|
|
|
info.right_path = task->right_path;
|
|
|
info.cameraSide = task->cameraSide; // 复制相机方位
|
|
|
info.camera_Num = task->camera_Num;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
// 读取左图
|
|
|
long startTime = getcurTime();
|
|
|
cv::Mat left_img;
|
|
|
cv::Mat img16 = cv::imread(task->left_path, cv::IMREAD_UNCHANGED);
|
|
|
|
|
|
if (!img16.empty())
|
|
|
{
|
|
|
|
|
|
if (img16.type() != CV_8U)
|
|
|
{
|
|
|
// printf("=========== 1 %s\n", info.channelName.c_str());
|
|
|
cv::Mat img8;
|
|
|
cv::normalize(img16, img8, 0, 255, cv::NORM_MINMAX);
|
|
|
img8.convertTo(img8, CV_8U);
|
|
|
left_img = img8;
|
|
|
}
|
|
|
else if (img16.type() == CV_8U)
|
|
|
{
|
|
|
// printf("=========== 2%s\n", info.channelName.c_str());
|
|
|
left_img = img16;
|
|
|
}
|
|
|
}
|
|
|
// cv::imwrite(info.channelName+"_ddddd.png", left_img);
|
|
|
// getchar();
|
|
|
|
|
|
// 读取右图
|
|
|
cv::Mat right_img;
|
|
|
img16 = cv::imread(task->right_path, cv::IMREAD_UNCHANGED);
|
|
|
|
|
|
if (!img16.empty())
|
|
|
{
|
|
|
|
|
|
if (img16.type() != CV_8U)
|
|
|
{
|
|
|
// printf("=========== 1 %s\n", info.channelName.c_str());
|
|
|
cv::Mat img8;
|
|
|
cv::normalize(img16, img8, 0, 255, cv::NORM_MINMAX);
|
|
|
img8.convertTo(img8, CV_8U);
|
|
|
right_img = img8;
|
|
|
}
|
|
|
else if (img16.type() == CV_8U)
|
|
|
{
|
|
|
// printf("=========== 2%s\n", info.channelName.c_str());
|
|
|
right_img = img16;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
long endTime = getcurTime();
|
|
|
|
|
|
info.width = left_img.cols;
|
|
|
info.height = left_img.rows;
|
|
|
info.readTimeMs = endTime - startTime;
|
|
|
info.left_img = left_img;
|
|
|
info.right_img = right_img;
|
|
|
|
|
|
// 检查是否成功读取
|
|
|
info.success = !left_img.empty() || !right_img.empty();
|
|
|
|
|
|
if (!info.success)
|
|
|
{
|
|
|
// 记录失败原因
|
|
|
if (left_img.empty() && right_img.empty())
|
|
|
{
|
|
|
info.errorReason = "左右图都读取失败";
|
|
|
}
|
|
|
else if (left_img.empty())
|
|
|
{
|
|
|
info.errorReason = "左图读取失败:" + task->left_path;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
info.errorReason = "右图读取失败:" + task->right_path;
|
|
|
}
|
|
|
|
|
|
printf("[读图错误-%3d] %s\n", task->taskIndex, info.errorReason.c_str());
|
|
|
}
|
|
|
}
|
|
|
catch (const cv::Exception &e)
|
|
|
{
|
|
|
// OpenCV 异常处理
|
|
|
info.success = false;
|
|
|
info.errorReason = std::string("OpenCV 异常:") + e.what();
|
|
|
info.width = 0;
|
|
|
info.height = 0;
|
|
|
info.readTimeMs = 0;
|
|
|
|
|
|
printf("[读图异常-%3d] %s\n", task->taskIndex, e.what());
|
|
|
}
|
|
|
catch (const std::exception &e)
|
|
|
{
|
|
|
// 标准异常处理
|
|
|
info.success = false;
|
|
|
info.errorReason = std::string("异常:") + e.what();
|
|
|
info.width = 0;
|
|
|
info.height = 0;
|
|
|
info.readTimeMs = 0;
|
|
|
|
|
|
printf("[读图异常-%3d] %s\n", task->taskIndex, e.what());
|
|
|
}
|
|
|
catch (...)
|
|
|
{
|
|
|
// 未知异常处理
|
|
|
info.success = false;
|
|
|
info.errorReason = "未知异常";
|
|
|
info.width = 0;
|
|
|
info.height = 0;
|
|
|
info.readTimeMs = 0;
|
|
|
|
|
|
printf("[读图未知异常-%3d]\n", task->taskIndex);
|
|
|
}
|
|
|
|
|
|
// 推送到通知队列并通知主线程
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(m_checkNotifyMutex);
|
|
|
m_checkNotifyQueue.push(info);
|
|
|
}
|
|
|
m_checkNotifyCV.notify_one(); // 立即唤醒主线程
|
|
|
|
|
|
// 更新计数器
|
|
|
m_nCheckNotifiedCount.fetch_add(1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void deal::RecordFailedImg(const FailedImgRecord &record)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(m_productFailedMutex);
|
|
|
m_ProductFailedList.push_back(record);
|
|
|
}
|
|
|
|
|
|
void deal::PrintProductStatistics(const LoadProductImages &product)
|
|
|
{
|
|
|
printf("\n");
|
|
|
printf("╔══════════════════════════════════════════════════════════\n");
|
|
|
printf("║ 产品:%s - 处理完成\n", product.product_id.c_str());
|
|
|
printf("║ ─────────────────────────────────────────────────────── \n");
|
|
|
printf("║ 总计:%zu 对图片\n", product.images.size());
|
|
|
printf("║ 成功:%d 对\n", m_nProductSuccessCount.load());
|
|
|
printf("║ 失败:%d 对\n", m_nProductFailCount.load());
|
|
|
|
|
|
int totalProcessed = m_nProductSuccessCount.load() + m_nProductFailCount.load();
|
|
|
float successRate = (totalProcessed > 0) ? (m_nProductSuccessCount.load() * 100.0f / totalProcessed) : 0;
|
|
|
printf("║ 成功率:%.1f%%\n", successRate);
|
|
|
|
|
|
if (!m_ProductFailedList.empty())
|
|
|
{
|
|
|
printf("║ ─────────────────────────────────────────────────────── \n");
|
|
|
printf("║ 失败列表:\n");
|
|
|
for (size_t i = 0; i < m_ProductFailedList.size() && i < 10; i++)
|
|
|
{
|
|
|
const auto &record = m_ProductFailedList[i];
|
|
|
printf("║ [%zu] 左:%s\n", i, record.left_path.c_str());
|
|
|
printf("║ 右:%s\n", record.right_path.c_str());
|
|
|
printf("║ 错误:%s\n", record.errorReason.c_str());
|
|
|
}
|
|
|
if (m_ProductFailedList.size() > 10)
|
|
|
{
|
|
|
printf("║ ... 还有 %zu 条失败记录\n", m_ProductFailedList.size() - 10);
|
|
|
}
|
|
|
}
|
|
|
printf("╚══════════════════════════════════════════════════════════\n");
|
|
|
printf("\n");
|
|
|
}
|
|
|
int deal::ReJson_product(std::vector<Json_Det_Path> &jsonList, std::string strProductName)
|
|
|
{
|
|
|
// 获取要检测的 json 图片 list
|
|
|
|
|
|
int temstatus = IN_IMG_Status_Start;
|
|
|
int PushNum = 0;
|
|
|
// 开始逐一复测
|
|
|
for (int i = 0; i < jsonList.size(); i++)
|
|
|
{
|
|
|
std::string strJson = jsonList.at(i).strPath_Json;
|
|
|
std::string strimg = jsonList.at(i).strPath_CutImg;
|
|
|
std::ifstream file(strJson);
|
|
|
|
|
|
if (!file.is_open())
|
|
|
{
|
|
|
std::cerr << "Unable to open file!" << std::endl;
|
|
|
return -1;
|
|
|
}
|
|
|
// 读取文件内容到 std::string
|
|
|
std::stringstream buffer;
|
|
|
buffer << file.rdbuf();
|
|
|
std::string json_str = buffer.str(); // 获取 JSON 文件的内容作为字符串
|
|
|
// 显示读取到的 JSON 字符串
|
|
|
// std::cout << "JSON content: " << json_str << std::endl;
|
|
|
cv::Mat cutimg = cv::imread(strimg, 0);
|
|
|
int f0 = strJson.rfind('_');
|
|
|
int f1 = strJson.rfind('.');
|
|
|
int f2 = strJson.rfind('/');
|
|
|
|
|
|
std::string str1 = strJson.substr(f2 + 1, f1 - f2 - 1);
|
|
|
std::string str2 = strJson.substr(f0 + 1, f1 - f0 - 1);
|
|
|
// std::string str3 = strJson.substr(f2 + 1, strJson.size() - f2);
|
|
|
|
|
|
std::cout << str1 << std::endl;
|
|
|
std::cout << str2 << std::endl;
|
|
|
if (str1.find("CA") != std::string::npos)
|
|
|
{
|
|
|
str2 = "CA";
|
|
|
}
|
|
|
else if (str1.find("TA") != std::string::npos)
|
|
|
{
|
|
|
str2 = "TA";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
std::cout << "start " << strJson << std::endl;
|
|
|
|
|
|
std::shared_ptr<CheckResult> result;
|
|
|
// 多线程 互斥 作用域
|
|
|
{
|
|
|
|
|
|
std::shared_ptr<shareImage> temdet = std::make_shared<shareImage>();
|
|
|
temdet->strCameraName = str2;
|
|
|
temdet->strImgProductID = strProductName;
|
|
|
temdet->strChannel = str2;
|
|
|
temdet->strImgName = str1;
|
|
|
|
|
|
std::cout << "strChannel " << temdet->strChannel << std::endl;
|
|
|
|
|
|
temdet->Det_Mode = DET_MODE_ReJson;
|
|
|
temdet->img = cutimg;
|
|
|
temdet->resultJson = json_str;
|
|
|
|
|
|
{
|
|
|
if (i == 0)
|
|
|
{
|
|
|
temdet->Status = IN_IMG_Status_Start;
|
|
|
}
|
|
|
else if (i == jsonList.size() - 1)
|
|
|
{
|
|
|
temdet->Status = IN_IMG_Status_End;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
temdet->Status = IN_IMG_Status_Other;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(temdet);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
printf("reJson Error %d \n", re);
|
|
|
continue;
|
|
|
}
|
|
|
PushNum++;
|
|
|
// 结果异常
|
|
|
}
|
|
|
}
|
|
|
int getresultNum = 0;
|
|
|
while (true)
|
|
|
{
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟消费过程
|
|
|
// 处理结果
|
|
|
|
|
|
std::shared_ptr<CheckResult> checkResult;
|
|
|
int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult);
|
|
|
printf("********************** Get result %d -- %s \n", getresultNum, checkResult->in_shareImage->strChannel.c_str());
|
|
|
saveImg("/home/aidlux/BOE/ReJsonresult/", checkResult);
|
|
|
getresultNum++;
|
|
|
if (getresultNum == PushNum)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
void deal::GetResultThread()
|
|
|
{
|
|
|
std::vector<int> vi;
|
|
|
vi.push_back(18);
|
|
|
auto nRet = set_cpu_id(vi);
|
|
|
printf("bind cpu ret %d, %d\n", nRet, 18);
|
|
|
int re = 0;
|
|
|
|
|
|
int nsleep1 = 2 * 1000;
|
|
|
|
|
|
while (!m_bExit)
|
|
|
{
|
|
|
// 1、拷贝检测结果到队列
|
|
|
GetDealResultToQueu();
|
|
|
usleep(nsleep1);
|
|
|
}
|
|
|
}
|
|
|
void deal::ReadImgThread(int id)
|
|
|
{
|
|
|
|
|
|
int nsleep1 = 200 * 1000;
|
|
|
int readThreadIdx = id;
|
|
|
while (!m_bExit)
|
|
|
{
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费过程
|
|
|
|
|
|
// 读图模式
|
|
|
if (READ_THREAD_TYPE_READIMG == m_nReadThread_type)
|
|
|
{
|
|
|
Thread_ReadImg(readThreadIdx);
|
|
|
}
|
|
|
else if (READ_THREAD_Detect == m_nReadThread_type)
|
|
|
{
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
void deal::testimg(cv::Mat img)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
int deal::updataResltInfo(std::shared_ptr<CheckResult> result)
|
|
|
{
|
|
|
|
|
|
mutex_DetResult_.lock();
|
|
|
std::string productID = result->in_shareImage->strImgProductID;
|
|
|
std::string imgName = result->in_shareImage->strChannel;
|
|
|
// printf("add productID %s imgName %s %d\n", productID.c_str(), imgName.c_str(), result->nresult);
|
|
|
long t1 = getcurTime();
|
|
|
m_DetResult.updata(productID, imgName, result->nresult, t1);
|
|
|
for (int i = 0; i < ERROR_TYPE_COUNT; i++)
|
|
|
{
|
|
|
if (result->defectResultList[i].nresult == 1)
|
|
|
{
|
|
|
m_DetResult.update_qx(result->defectResultList[i].keyName, result->defectResultList[i].num);
|
|
|
}
|
|
|
}
|
|
|
mutex_DetResult_.unlock();
|
|
|
return 0;
|
|
|
}
|
|
|
// 滑动窗口二值化函数
|
|
|
void deal::slidingWindowAutoThreshold(const cv::Mat &src, cv::Mat &dst, int windowSize, int step, double C)
|
|
|
{
|
|
|
// 确保窗口大小为奇数
|
|
|
// if (windowSize % 2 == 0)
|
|
|
// {
|
|
|
// windowSize++;
|
|
|
// }
|
|
|
|
|
|
// 创建目标图像
|
|
|
dst = cv::Mat::zeros(src.size(), CV_8UC1);
|
|
|
|
|
|
// 获取源图像的尺寸
|
|
|
int rows = src.rows;
|
|
|
int cols = src.cols;
|
|
|
int xs = 0;
|
|
|
int xe = windowSize;
|
|
|
int ys = 0;
|
|
|
int ye = windowSize;
|
|
|
for (int y = ye; y < rows;)
|
|
|
{
|
|
|
int xs = 0;
|
|
|
int xe = windowSize;
|
|
|
for (int x = xe; x < cols;)
|
|
|
{
|
|
|
|
|
|
cv::Rect roi;
|
|
|
roi.x = xs;
|
|
|
roi.width = windowSize;
|
|
|
roi.y = ys;
|
|
|
roi.height = windowSize;
|
|
|
|
|
|
cv::Mat window = src(roi);
|
|
|
|
|
|
// 计算窗口中的平均值和标准差
|
|
|
cv::Scalar mean, stdDev;
|
|
|
cv::meanStdDev(window, mean, stdDev);
|
|
|
// printf(" x %d %d y %d %d %f %f \n", xs, xe, ys, ye, mean[0], stdDev[0]);
|
|
|
int T = mean[0] + 20 * stdDev[0];
|
|
|
cv::threshold(window, dst(roi), T, 255, cv::THRESH_BINARY);
|
|
|
|
|
|
// cv::rectangle(src, roi, cv::Scalar(255, 0, 255));
|
|
|
if (xe == cols)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
xs = xs + step;
|
|
|
xe = xs + windowSize;
|
|
|
if (xs < cols && xe > cols)
|
|
|
{
|
|
|
xe = cols;
|
|
|
xs = xe - windowSize;
|
|
|
}
|
|
|
}
|
|
|
if (ye == rows)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
ys = ys + step;
|
|
|
ye = ys + windowSize;
|
|
|
if (ys < rows && ye > rows)
|
|
|
{
|
|
|
ye = rows;
|
|
|
ys = ye - windowSize;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
int deal::SetStatus(int type, int status)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_DetStatus]);
|
|
|
m_DetStatusList[type] = status;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::GetStatus(int type)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_DetStatus]);
|
|
|
|
|
|
return m_DetStatusList[type];
|
|
|
}
|
|
|
bool deal::IsStatus(int type, int status)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_DetStatus]);
|
|
|
if (m_DetStatusList[type] == status)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
int deal::SetStatus_List(int idx, Thread_Status_ status)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_ReadImgThread]);
|
|
|
m_nReadStausList[idx] = status;
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::GetStatus_List(int idx)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_ReadImgThread]);
|
|
|
return m_nReadStausList[idx];
|
|
|
}
|
|
|
bool deal::IsStatus_List(int idx, Thread_Status_ status)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_ReadImgThread]);
|
|
|
if (idx < 0 || idx >= READ_IMG_THREAD_NUM)
|
|
|
{
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (m_nReadStausList[idx] == status)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
int deal::setReadThreadStart()
|
|
|
{
|
|
|
for (int i = 0; i < READ_IMG_THREAD_NUM; i++)
|
|
|
{
|
|
|
SetStatus_List(i, Thread_Status_READY);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::GetReadImgCompleteThreadIdx()
|
|
|
{
|
|
|
for (int i = 0; i < READ_IMG_THREAD_NUM; i++)
|
|
|
{
|
|
|
if (IsStatus_List(i, Thread_Status_COMMPLET))
|
|
|
{
|
|
|
return i;
|
|
|
}
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
bool deal::IsALLComplete()
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_DetStatus]);
|
|
|
|
|
|
for (size_t i = 0; i < READ_IMG_THREAD_NUM; i++)
|
|
|
{
|
|
|
if (m_nReadStausList[i] == ReadImg_Status_COMMPLET)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
int deal::InitCPUIDX()
|
|
|
{
|
|
|
int start = 3;
|
|
|
m_CPUInfo[THREAD_CPU_Main_Det].set(start, 4);
|
|
|
start += 4;
|
|
|
m_CPUInfo[THREAD_CPU_Main_readImg].set(start, READ_IMG_THREAD_NUM);
|
|
|
start += READ_IMG_THREAD_NUM;
|
|
|
m_CPUInfo[THREAD_CPU_Main_saveImg].set(start, Save_IMG_THREAD_NUM);
|
|
|
start += Save_IMG_THREAD_NUM;
|
|
|
m_CPUInfo[THREAD_CPU_CheckSo].set(start, 15);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void deal::Thread_ReadImg(int id)
|
|
|
{
|
|
|
if (!IsStatus_List(id, Thread_Status_READY))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
int re = 0;
|
|
|
std::shared_ptr<JC_IMAGE_INFO_> pImageInfo = nullptr;
|
|
|
re = GetReadImgInfo(pImageInfo);
|
|
|
if (pImageInfo == nullptr)
|
|
|
{
|
|
|
printf("pImageInfo == nullptr=================id %d=============\n", id);
|
|
|
return;
|
|
|
}
|
|
|
pImageInfo->img = cv::imread(pImageInfo->strPath, 0);
|
|
|
m_ReadImgThread_Result[id] = pImageInfo;
|
|
|
|
|
|
// 线程完成读图,设置现场状态为 完成
|
|
|
SetStatus_List(id, Thread_Status_COMMPLET);
|
|
|
|
|
|
// printf("Thread_ReadImg=================id %d %s=============\n", id, pImageInfo->strPath.c_str());
|
|
|
}
|
|
|
|
|
|
int deal::InsertReadImgInfo(std::shared_ptr<JC_IMAGE_INFO_> pImageInfo)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mutex_ReadImgList);
|
|
|
m_ReadImg_queue.push(pImageInfo);
|
|
|
cv_ReadImgList.notify_one(); // 唤醒等待的线程
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::GetReadImgInfo(std::shared_ptr<JC_IMAGE_INFO_> &pImageInfo)
|
|
|
{
|
|
|
// printf("===============waite img info ===============\n");
|
|
|
std::unique_lock<std::mutex> lock(mutex_ReadImgList);
|
|
|
|
|
|
cv_ReadImgList.wait(lock, [this]()
|
|
|
{ return !m_ReadImg_queue.empty(); });
|
|
|
|
|
|
pImageInfo = m_ReadImg_queue.front(); // 获取队首数据
|
|
|
if (pImageInfo == NULL)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
m_ReadImg_queue.pop(); // 弹出队首数据
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int deal::LoadOfflineCheckImg(std::string strImgPath)
|
|
|
{
|
|
|
std::vector<cv::String> img_paths;
|
|
|
cv::glob(strImgPath, img_paths, true);
|
|
|
m_OffLineCheckImgList.erase(m_OffLineCheckImgList.begin(), m_OffLineCheckImgList.end());
|
|
|
m_OffLineCheckImgNameList.erase(m_OffLineCheckImgNameList.begin(), m_OffLineCheckImgNameList.end());
|
|
|
for (int i = 0; i < img_paths.size(); i++)
|
|
|
{
|
|
|
|
|
|
size_t found = img_paths[i].find_last_of("/\\");
|
|
|
|
|
|
// std::cout << img_paths[i] << std::endl;
|
|
|
std::string str = img_paths[i];
|
|
|
m_OffLineCheckImgNameList.push_back(str);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::LoadImgPath_JCSN(std::string strImgPath)
|
|
|
{
|
|
|
|
|
|
std::cout << strImgPath << std::endl;
|
|
|
std::vector<cv::String> img_paths;
|
|
|
|
|
|
cv::glob(strImgPath, img_paths, true);
|
|
|
|
|
|
m_OffImageSNPathList.erase(m_OffImageSNPathList.begin(), m_OffImageSNPathList.end());
|
|
|
|
|
|
for (int i = 0; i < img_paths.size(); i++)
|
|
|
{
|
|
|
|
|
|
std::string path = img_paths[i];
|
|
|
// std::cout << img_paths[i] << std::endl;
|
|
|
|
|
|
// 提取所有文件夹名称
|
|
|
std::vector<std::string> allDirectories = extractAllDirectories(path);
|
|
|
std::string strSN = "";
|
|
|
// 输出所有文件夹名称
|
|
|
std::string strAllPath = "/";
|
|
|
|
|
|
for (const auto &dir : allDirectories)
|
|
|
{
|
|
|
strAllPath += dir;
|
|
|
if (isValidString(dir))
|
|
|
{
|
|
|
strSN = dir;
|
|
|
// std::cout << strSN << std::endl;
|
|
|
break;
|
|
|
}
|
|
|
strAllPath += "/";
|
|
|
}
|
|
|
|
|
|
bool bh = false;
|
|
|
for (int j = 0; j < m_OffImageSNPathList.size(); j++)
|
|
|
{
|
|
|
if (m_OffImageSNPathList.at(j) == strAllPath)
|
|
|
{
|
|
|
bh = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
if (!bh)
|
|
|
{
|
|
|
if (m_OffImageSNPathList.size() < m_nTestNum)
|
|
|
{
|
|
|
m_OffImageSNPathList.push_back(strAllPath);
|
|
|
std::cout << strAllPath << std::endl;
|
|
|
}
|
|
|
|
|
|
// std::cout << strSN << std::endl;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
bool deal::isValidString(const std::string &str)
|
|
|
{
|
|
|
// 检查字符串长度是否为10
|
|
|
if (str.length() < 14 || str.length() > 19)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 检查字符串中的每个字符是否都是字母或数字
|
|
|
for (char c : str)
|
|
|
{
|
|
|
if (!std::isalnum(c))
|
|
|
{ // 如果字符不是字母或数字
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 字符串满足条件
|
|
|
return true;
|
|
|
}
|
|
|
int deal::LoadProductID(std::string strImgPath)
|
|
|
{
|
|
|
m_product_ID_List.erase(m_product_ID_List.begin(), m_product_ID_List.end());
|
|
|
std::vector<cv::String> img_paths;
|
|
|
|
|
|
// tif 格式
|
|
|
{
|
|
|
std::string str_bmp = strImgPath + "/*.ytimage";
|
|
|
std::cout << str_bmp << std::endl;
|
|
|
|
|
|
cv::glob(str_bmp, img_paths, true);
|
|
|
for (int i = 0; i < img_paths.size(); i++)
|
|
|
{
|
|
|
|
|
|
std::string path = img_paths[i];
|
|
|
// 提取所有文件夹名称
|
|
|
std::vector<std::string> allDirectories = extractAllDirectories(path);
|
|
|
std::string strSN = "";
|
|
|
// 输出所有文件夹名称
|
|
|
std::string strAllPath = "/";
|
|
|
|
|
|
for (const auto &dir : allDirectories)
|
|
|
{
|
|
|
// std::cout << dir << std::endl;
|
|
|
strAllPath += dir;
|
|
|
if (isValidString(dir))
|
|
|
{
|
|
|
strSN = dir;
|
|
|
break;
|
|
|
}
|
|
|
strAllPath += "/";
|
|
|
}
|
|
|
|
|
|
bool bh = false;
|
|
|
for (int j = 0; j < m_product_ID_List.size(); j++)
|
|
|
{
|
|
|
if (m_product_ID_List.at(j) == strAllPath)
|
|
|
{
|
|
|
bh = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
if (!bh)
|
|
|
{
|
|
|
if (m_product_ID_List.size() < m_nTestNum)
|
|
|
{
|
|
|
m_product_ID_List.push_back(strAllPath);
|
|
|
std::cout << strAllPath << std::endl;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
int deal::RandDrawImg(cv::Mat srcimg, cv::Mat &randErrorImg)
|
|
|
{
|
|
|
|
|
|
randErrorImg = srcimg.clone();
|
|
|
cv::Rect roi;
|
|
|
roi.x = (rand() % (srcimg.cols - 20 - 20)) + 20;
|
|
|
roi.y = (rand() % (srcimg.rows - 20 - 20)) + 20;
|
|
|
roi.width = (rand() % (100 - 5)) + 5;
|
|
|
roi.height = roi.width;
|
|
|
|
|
|
if (roi.x + roi.width >= srcimg.cols)
|
|
|
{
|
|
|
roi.x = srcimg.cols - roi.width - 1;
|
|
|
/* code */
|
|
|
}
|
|
|
if (roi.y + roi.height >= srcimg.rows)
|
|
|
{
|
|
|
roi.y = srcimg.rows - roi.height - 1;
|
|
|
/* code */
|
|
|
}
|
|
|
randErrorImg(roi).setTo(30);
|
|
|
return 0;
|
|
|
}
|
|
|
void deal::DealImg()
|
|
|
{
|
|
|
}
|
|
|
// 提取所有文件夹名称函数
|
|
|
std::vector<std::string> deal::extractAllDirectories(const std::string &path)
|
|
|
{
|
|
|
std::vector<std::string> directories;
|
|
|
std::string directory;
|
|
|
|
|
|
// 遍历路径中的每个字符
|
|
|
for (char c : path)
|
|
|
{
|
|
|
// 如果遇到路径分隔符,则将当前文件夹名称存储起来
|
|
|
if (c == '/' || c == '\\')
|
|
|
{
|
|
|
if (!directory.empty())
|
|
|
{ // 确保文件夹名称不为空
|
|
|
directories.push_back(directory);
|
|
|
directory.clear(); // 清空当前文件夹名称
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
directory += c; // 将字符添加到当前文件夹名称中
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 将最后一个文件夹名称添加到列表中
|
|
|
if (!directory.empty())
|
|
|
{
|
|
|
directories.push_back(directory);
|
|
|
}
|
|
|
|
|
|
return directories;
|
|
|
} |