|
|
|
@ -5,6 +5,7 @@
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include "CheckUtil.hpp"
|
|
|
|
#include "CheckUtil.hpp"
|
|
|
|
std::string ExtractFileNameWithoutExtension(const std::string &strImgPath)
|
|
|
|
std::string ExtractFileNameWithoutExtension(const std::string &strImgPath)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -101,6 +102,7 @@ deal::deal()
|
|
|
|
m_nCurUseCPUIDX = 0;
|
|
|
|
m_nCurUseCPUIDX = 0;
|
|
|
|
m_nSaveDetprocessImg = 0;
|
|
|
|
m_nSaveDetprocessImg = 0;
|
|
|
|
m_nPushImgCount = 0;
|
|
|
|
m_nPushImgCount = 0;
|
|
|
|
|
|
|
|
m_nResultRecvCount = 0;
|
|
|
|
m_DetResult.Init();
|
|
|
|
m_DetResult.Init();
|
|
|
|
for (int i = 0; i < READ_IMG_THREAD_NUM; i++)
|
|
|
|
for (int i = 0; i < READ_IMG_THREAD_NUM; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -814,6 +816,8 @@ void deal::ResultThread(int id)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
strlog += "/result";
|
|
|
|
strlog += "/result";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 确保日志目录存在(否则 writeLog 报 Failed to open file)
|
|
|
|
|
|
|
|
_sysmkdirs_1(strlog.substr(0, strlog.find_last_of('/')));
|
|
|
|
|
|
|
|
|
|
|
|
writeLog(strlog, m_DetResult.strlist);
|
|
|
|
writeLog(strlog, m_DetResult.strlist);
|
|
|
|
mutex_DetResult_.unlock();
|
|
|
|
mutex_DetResult_.unlock();
|
|
|
|
@ -861,6 +865,7 @@ void deal::GetDealResultToQueu()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mutex_Result_list.lock();
|
|
|
|
mutex_Result_list.lock();
|
|
|
|
m_Result_list.push(checkResult);
|
|
|
|
m_Result_list.push(checkResult);
|
|
|
|
|
|
|
|
m_nResultRecvCount++;
|
|
|
|
mutex_Result_list.unlock();
|
|
|
|
mutex_Result_list.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
@ -903,6 +908,30 @@ bool deal::ReadSystemConfig(const std::string &strPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int deal::GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector<JC_IMAGE_INFO_> &jcImageInfoList)
|
|
|
|
int deal::GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector<JC_IMAGE_INFO_> &jcImageInfoList)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// -f 批量跑新格式: 产品目录下 input 子目录, 只取 _src 原图
|
|
|
|
|
|
|
|
// (如 1M10121544R3B2_t_face_bright_src.jpg, 从图片名解析产品ID和相机名)
|
|
|
|
|
|
|
|
if (fs::is_directory(strSearchImg + "/input"))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
jcImageInfoList.erase(jcImageInfoList.begin(), jcImageInfoList.end());
|
|
|
|
|
|
|
|
std::vector<cv::String> srcImgPaths;
|
|
|
|
|
|
|
|
cv::glob(strSearchImg + "/input/*.jpg", srcImgPaths, false);
|
|
|
|
|
|
|
|
for (int idx = 0; idx < srcImgPaths.size(); idx++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
JC_IMAGE_INFO_ tem;
|
|
|
|
|
|
|
|
int re = GetImgInfo_BACKPLATE_SRC(srcImgPaths.at(idx), &tem);
|
|
|
|
|
|
|
|
if (re != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tem.strProductID == "")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tem.strProductID = strProductID;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
jcImageInfoList.push_back(tem);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 1、获取图片路径
|
|
|
|
// 1、获取图片路径
|
|
|
|
std::vector<cv::String> img_paths;
|
|
|
|
std::vector<cv::String> img_paths;
|
|
|
|
std::string strs1 = strSearchImg + "/*.jpg";
|
|
|
|
std::string strs1 = strSearchImg + "/*.jpg";
|
|
|
|
@ -1000,6 +1029,63 @@ int deal::GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageIn
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -f 批量跑新格式: 解析图片名组装产品信息
|
|
|
|
|
|
|
|
// 图片名示例: 1M10121544R3B2_t_face_bright_src.jpg
|
|
|
|
|
|
|
|
// 产品ID: 第一个 '_' 之前的部分 (1M10121544R3B2)
|
|
|
|
|
|
|
|
// 相机名: 直接匹配文件名中的相机名(t_face_bright / t_face_dark), 只处理后缀为 _src 的原图
|
|
|
|
|
|
|
|
// 通道名: 统一用 t_face
|
|
|
|
|
|
|
|
int deal::GetImgInfo_BACKPLATE_SRC(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (pImageInfo == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string strName = ExtractFileNameWithoutExtension(strImgPath);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 只处理后缀为 _src 的原图, 跳过 _roi 等其它图
|
|
|
|
|
|
|
|
const std::string strSrcSuffix = "_src";
|
|
|
|
|
|
|
|
if (strName.size() <= strSrcSuffix.size() ||
|
|
|
|
|
|
|
|
strName.compare(strName.size() - strSrcSuffix.size(), strSrcSuffix.size(), strSrcSuffix) != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 直接匹配文件名中的相机名(t_face_bright / t_face_dark)
|
|
|
|
|
|
|
|
std::string strCamName = "";
|
|
|
|
|
|
|
|
if (strName.find("t_face_bright") != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
strCamName = "t_face_bright";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (strName.find("t_face_dark") != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
strCamName = "t_face_dark";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strCamName == "")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("GetImgInfo_BACKPLATE_SRC: no camera match, skip %s\n", strImgPath.c_str());
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 产品ID = 文件名第一个 '_' 之前的部分
|
|
|
|
|
|
|
|
std::string strProductID = strName;
|
|
|
|
|
|
|
|
size_t nPos = strName.find('_');
|
|
|
|
|
|
|
|
if (nPos != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
strProductID = strName.substr(0, nPos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pImageInfo->strProductID = strProductID;
|
|
|
|
|
|
|
|
pImageInfo->strCamID = strCamName;
|
|
|
|
|
|
|
|
pImageInfo->strchannelName = "t_face"; // 通道名统一用 t_face
|
|
|
|
|
|
|
|
pImageInfo->strName = strName;
|
|
|
|
|
|
|
|
pImageInfo->strPath = strImgPath;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("strImgPath %s strName %s strProductID %s strCam %s strChannel %s\n",
|
|
|
|
|
|
|
|
strImgPath.c_str(), strName.c_str(), strProductID.c_str(), strCamName.c_str(), pImageInfo->strchannelName.c_str());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
int deal::InsertDetResult(ReadImgInfo tem)
|
|
|
|
int deal::InsertDetResult(ReadImgInfo tem)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_DetResult]);
|
|
|
|
std::lock_guard<std::mutex> lock(mtx_List[Mutex_Type_DetResult]);
|
|
|
|
@ -1203,6 +1289,36 @@ int deal::DetImg()
|
|
|
|
// getchar();
|
|
|
|
// getchar();
|
|
|
|
m_nSystemCheckType = CHECK_TYPE_OFFLING;
|
|
|
|
m_nSystemCheckType = CHECK_TYPE_OFFLING;
|
|
|
|
StartThread(THREAD_RUN_ALL);
|
|
|
|
StartThread(THREAD_RUN_ALL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -8 循环执行:保持常驻,重复处理同一批产品
|
|
|
|
|
|
|
|
if (runConfig.bLoop)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
usleep(1000 * 1000);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -f 批量(不加 -8 只执行一次):等待全部产品处理完成后退出
|
|
|
|
|
|
|
|
// DealImg 线程处理完一批后会清空 m_product_ID_List 并等待结果队列清空
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
usleep(200 * 1000);
|
|
|
|
|
|
|
|
size_t nResultSize = 0;
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex_Result_list);
|
|
|
|
|
|
|
|
nResultSize = m_Result_list.size();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_product_ID_List.empty() && nResultSize <= 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 留时间给结果线程把最后一组结果写完
|
|
|
|
|
|
|
|
usleep(2 * 1000 * 1000);
|
|
|
|
|
|
|
|
printf(">>> -f batch complete, exit \n");
|
|
|
|
|
|
|
|
fflush(NULL);
|
|
|
|
|
|
|
|
_exit(0);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int deal::ReJson_product(std::vector<Json_Det_Path> &jsonList, std::string strProductName)
|
|
|
|
int deal::ReJson_product(std::vector<Json_Det_Path> &jsonList, std::string strProductName)
|
|
|
|
@ -1552,6 +1668,55 @@ int deal::LoadProductID(std::string strImgPath)
|
|
|
|
m_product_ID_List.erase(m_product_ID_List.begin(), m_product_ID_List.end());
|
|
|
|
m_product_ID_List.erase(m_product_ID_List.begin(), m_product_ID_List.end());
|
|
|
|
std::vector<cv::String> img_paths;
|
|
|
|
std::vector<cv::String> img_paths;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -f 批量跑新格式适配(参考 data/img/test-2 结构):
|
|
|
|
|
|
|
|
// <filePath>/<产品ID>_<时间戳>/input/<产品ID>_<相机名>_<位置>_src.jpg
|
|
|
|
|
|
|
|
// 也支持直接传入单个产品目录或产品目录下的 input 目录
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string strPath = strImgPath;
|
|
|
|
|
|
|
|
while (!strPath.empty() && strPath[strPath.size() - 1] == '/')
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
strPath.erase(strPath.size() - 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fs::path rootPath(strPath);
|
|
|
|
|
|
|
|
if (!strPath.empty() && fs::is_directory(rootPath))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 兼容直接传入 input 目录: 使用其上一级产品目录
|
|
|
|
|
|
|
|
if (rootPath.filename() == "input" && rootPath.has_parent_path())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rootPath = rootPath.parent_path();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> productDirList;
|
|
|
|
|
|
|
|
if (fs::is_directory(rootPath / "input"))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 直接传入单个产品目录
|
|
|
|
|
|
|
|
productDirList.push_back(rootPath.string());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 批量根目录: 含 input 子目录的子目录视为一个产品
|
|
|
|
|
|
|
|
for (const auto &entry : fs::directory_iterator(rootPath))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (entry.is_directory() && fs::is_directory(entry.path() / "input"))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
productDirList.push_back(entry.path().string());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!productDirList.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::sort(productDirList.begin(), productDirList.end());
|
|
|
|
|
|
|
|
for (const auto &strProductDir : productDirList)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_product_ID_List.push_back(strProductDir);
|
|
|
|
|
|
|
|
std::cout << "new format product dir: " << strProductDir << std::endl;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// tif 格式
|
|
|
|
// tif 格式
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::string str_bmp = strImgPath + "/*.jpg";
|
|
|
|
std::string str_bmp = strImgPath + "/*.jpg";
|
|
|
|
@ -1600,6 +1765,11 @@ int deal::LoadProductID(std::string strImgPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (m_product_ID_List.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("warning: no product dir/image found under %s\n", strImgPath.c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int deal::DelImg_Cell_ET()
|
|
|
|
int deal::DelImg_Cell_ET()
|
|
|
|
@ -1650,6 +1820,13 @@ int deal::Det_OneProduct_Cell_ET(std::string strProductName, int Idx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
std::string strProductID = GetFileName(strProductName);
|
|
|
|
std::string strProductID = GetFileName(strProductName);
|
|
|
|
|
|
|
|
// -f 批量跑新格式: 产品目录名为 <产品ID>_<时间戳>(如 1M10121544R3B2_20261012.151444.066219)
|
|
|
|
|
|
|
|
// 取第一个 '_' 之前的部分作为产品ID; 旧格式目录名本身即产品ID(无 '_')不受影响
|
|
|
|
|
|
|
|
size_t nProductIDPos = strProductID.find('_');
|
|
|
|
|
|
|
|
if (nProductIDPos != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
strProductID = strProductID.substr(0, nProductIDPos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取图片路径
|
|
|
|
// 获取图片路径
|
|
|
|
std::vector<JC_IMAGE_INFO_> detImgInfoList;
|
|
|
|
std::vector<JC_IMAGE_INFO_> detImgInfoList;
|
|
|
|
@ -1739,6 +1916,33 @@ int deal::Det_OneProduct_Cell_ET(std::string strProductName, int Idx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -f 批量逐个产品处理:等待本产品的检测结果全部返回后,再处理下一个产品,
|
|
|
|
|
|
|
|
// 避免多个产品同时积压在检测队列中(内存/检测器压力过大导致卡死)
|
|
|
|
|
|
|
|
if (AllImgNum > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int nWaitCnt = 0;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int nRecv = 0;
|
|
|
|
|
|
|
|
int nPush = 0;
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex_Result_list);
|
|
|
|
|
|
|
|
nRecv = m_nResultRecvCount;
|
|
|
|
|
|
|
|
nPush = m_nPushImgCount;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nRecv >= nPush)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nWaitCnt % 250 == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf(">>> waiting %s check result %d/%d ...\n", strProductID.c_str(), nRecv, nPush);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
nWaitCnt++;
|
|
|
|
|
|
|
|
usleep(20 * 1000);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_DetResult.one_result_list.push_back(tem_one);
|
|
|
|
m_DetResult.one_result_list.push_back(tem_one);
|
|
|
|
m_DetResult.det_num_all++;
|
|
|
|
m_DetResult.det_num_all++;
|
|
|
|
// if (m_DetResult.det_num_all == 1)
|
|
|
|
// if (m_DetResult.det_num_all == 1)
|
|
|
|
|