feat 添加输出参数接口

dev_lsy
liusiyang 6 days ago
parent e871478bc0
commit 2a5404c6b1

@ -61,6 +61,9 @@ public:
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
int UpdateConfig(void *pconfig, int nConfigType);
// 获取指定相机在更新参数后回传的参数值(strCamera 为相机名) 返回0 成功 其他异常
int GetUpdateParamOut(const std::string &strCamera, UpdateParamOutST &outParam);
std::string GetVersion();
std::string GetErrorInfo();
@ -72,6 +75,9 @@ private:
// 加载分析参数
int LoadCheckConfig(void *p);
// 更新参数后, 按相机从配置中提取需要回传的参数值
int UpdateParamOutConfig();
/// @brief 初始化并且启动程序
/// @return
int InitRun();
@ -139,6 +145,10 @@ private:
ConfigManagerBase *m_pConfigManager;
// 更新参数后需要回传给调用方的参数值: 相机名 -> 参数
std::unordered_map<std::string, UpdateParamOutST> m_UpdateParamOutMap;
std::mutex mtx_UpdateParamOut; // 互斥量, 保护 m_UpdateParamOutMap
// 图片处理线程
// 相机处理模块,负责完成对应相机图片的处理功能。

@ -51,6 +51,52 @@ struct RunInfoST
this->str2 = tem.str2;
}
};
/*******************更新参数回传结构***********************************************************************************************************************/
// 说明: 更新参数(UpdateConfig / 检测前更新参数)时, 算法侧把从 json 读到的参数值填进本结构体,
// 再通过接口返回给调用方。需要回传的字段直接往这里加即可。
struct flaw_info
{
float area; // 缺陷面积
float gray_dis; // 缺陷灰阶
flaw_info()
{
area = 0.0f;
gray_dis = 0.0f;
}
void copy(flaw_info tem)
{
this->area = tem.area;
this->gray_dis = tem.gray_dis;
}
};
struct UpdateParamOutST
{
float pixel_precision_x; // x成像检测精度
float pixel_precision_y; // y成像检测精度
flaw_info aotudian; // 凹凸点参数
flaw_info zangwu; // 脏污参数
flaw_info line; // 线状参数
flaw_info dianzhuang; // 点状参数
flaw_info xianwei; // 纤维参数
flaw_info posun; // 破损参数
UpdateParamOutST()
{
pixel_precision_x = 0.0f;
pixel_precision_y = 0.0f;
}
void copy(UpdateParamOutST tem)
{
this->pixel_precision_x = tem.pixel_precision_x;
this->pixel_precision_y = tem.pixel_precision_y;
this->aotudian.copy(tem.aotudian);
this->zangwu.copy(tem.zangwu);
this->line.copy(tem.line);
this->dianzhuang.copy(tem.dianzhuang);
this->xianwei.copy(tem.xianwei);
this->posun.copy(tem.posun);
}
};
/*******************一般调用流程*************************************************************************************************************************/
/*******************1、初始化 UpdateConfig*************************************************************************************************************************/
/*******************2、初始化 Init 并开启 *************************************************************************************************************************/
@ -84,6 +130,9 @@ public:
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
virtual int UpdateConfig(void *pconfig, int nConfigType) = 0;
// 获取指定相机在更新参数后回传的参数值(strCamera 为相机名) 返回0 成功 其他异常
virtual int GetUpdateParamOut(const std::string &strCamera, UpdateParamOutST &outParam) = 0;
// 返回检测版本信息
virtual std::string GetVersion() = 0;
// 返回错误信息

@ -238,6 +238,8 @@ int ALLImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType)
break;
case CHECK_CONFIG_Module:
m_pConfigManager = (ConfigManagerBase *)pconfig;
// 更新参数后, 立即按相机提取需要回传的参数值
UpdateParamOutConfig();
break;
default:
break;
@ -246,6 +248,128 @@ int ALLImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType)
return 0;
}
// 缺陷项 -> 回传结构体字段 的对应关系
struct QX_FIELD_MAP_
{
int nQxType; // 缺陷类型(CONFIG_QX_NAME_)
flaw_info UpdateParamOutST::*pField; // 回传结构体中对应的缺陷参数
};
// 从单个相机的配置中提取需要回传的参数值
// 取值位置与 ImageResultJudge::GetParamidx() 保持一致:
// 成像精度 <- commonCheckConfig.baseConfig.fImage_Scale_x / y
// 缺陷面积/灰阶 <- 第0个节点第0个区域的参数, 按缺陷名(param_name)匹配
static void FillUpdateParamOut(const AnalysisyConfigST &config, UpdateParamOutST &outParam)
{
// 1、成像检测精度
outParam.pixel_precision_x = config.commonCheckConfig.baseConfig.fImage_Scale_x;
outParam.pixel_precision_y = config.commonCheckConfig.baseConfig.fImage_Scale_y;
// 2、缺陷参数(面积/灰阶)
if (config.commonCheckConfig.nodeConfigArr.size() <= 0)
{
return;
}
const CommonConfigNodeST &node = config.commonCheckConfig.nodeConfigArr.at(0);
if (node.regionConfigArr.size() <= 0)
{
return;
}
const RegionConfigST &region = node.regionConfigArr.at(0);
const CheckConfig_Regions_type &typeParam = region.checkConfig_Regions_type[ANALYSIS_TYPE_TF];
const QX_FIELD_MAP_ qxFieldMap[] = {
{CONFIG_QX_NAME_cell_aotudian, &UpdateParamOutST::aotudian},
{CONFIG_QX_NAME_cell_zangwu, &UpdateParamOutST::zangwu},
{CONFIG_QX_NAME_cell_line, &UpdateParamOutST::line},
{CONFIG_QX_NAME_cell_dianzhuang, &UpdateParamOutST::dianzhuang},
{CONFIG_QX_NAME_cell_xianwei, &UpdateParamOutST::xianwei},
{CONFIG_QX_NAME_cell_posun, &UpdateParamOutST::posun},
};
const int nQxFieldNum = sizeof(qxFieldMap) / sizeof(qxFieldMap[0]);
for (int i = 0; i < nQxFieldNum; i++)
{
const std::string strQxName = CONFIG_QX_NAME_Names[qxFieldMap[i].nQxType];
flaw_info *pOut = &(outParam.*(qxFieldMap[i].pField));
for (int j = 0; j < typeParam.checkConfig_Regions_Param.size(); j++)
{
const CheckConfig_Regions_Param &param = typeParam.checkConfig_Regions_Param.at(j);
if (param.param_name != strQxName || param.paramArr.size() <= 0)
{
continue;
}
pOut->area = param.paramArr.at(0).area; // 缺陷面积
pOut->gray_dis = param.paramArr.at(0).hj; // 缺陷灰阶
break;
}
}
}
int ALLImgCheckAnalysisy::UpdateParamOutConfig()
{
std::lock_guard<std::mutex> lock(mtx_UpdateParamOut);
m_UpdateParamOutMap.clear();
if (m_pConfigManager == nullptr)
{
return 1;
}
// 每个相机一份参数(Config_instances_ 的 key 为 json 中的 cameraCode)
for (const auto &config : m_pConfigManager->Config_instances_)
{
if (!config.second)
{
continue;
}
AnalysisyConfigST analysisyConfig;
if (config.second->GetConfig(ConfigType_Analysisy_Common_XL, &analysisyConfig) != 0)
{
continue;
}
UpdateParamOutST paramOut;
FillUpdateParamOut(analysisyConfig, paramOut);
m_UpdateParamOutMap[config.first] = paramOut;
}
printf("ALLImgCheckAnalysisy::UpdateParamOutConfig cam num %zu \n", m_UpdateParamOutMap.size());
return m_UpdateParamOutMap.size() > 0 ? 0 : 2;
}
int ALLImgCheckAnalysisy::GetUpdateParamOut(const std::string &strCamera, UpdateParamOutST &outParam)
{
std::lock_guard<std::mutex> lock(mtx_UpdateParamOut);
auto it = m_UpdateParamOutMap.find(strCamera);
if (it != m_UpdateParamOutMap.end())
{
outParam.copy(it->second);
return 0;
}
// 兜底: 缓存中没有时, 直接按相机名从参数模块实时取一次
if (m_pConfigManager != nullptr)
{
auto itConfig = m_pConfigManager->Config_instances_.find(strCamera);
if (itConfig != m_pConfigManager->Config_instances_.end() && itConfig->second)
{
AnalysisyConfigST analysisyConfig;
if (itConfig->second->GetConfig(ConfigType_Analysisy_Common_XL, &analysisyConfig) == 0)
{
FillUpdateParamOut(analysisyConfig, outParam);
m_UpdateParamOutMap[strCamera] = outParam;
return 0;
}
}
}
return 1;
}
std::string ALLImgCheckAnalysisy::GetVersion()
{
return std::string("BOE_2.0.5");

@ -310,6 +310,112 @@ int deal::InitConfig()
return 0;
}
// 测试用: 仅加载配置, 调用 GetUpdateParamOut 把各相机的参数导出到 txt
// 不启动检测线程, 不加载模型
int deal::DumpUpdateParamOut(const std::string &strOutPath)
{
// 1、读取系统参数(含配置根目录 Config_Root_Path)
if (!ReadSystemConfig(FILE_SYSTEM_RUN_CONFIG))
{
printf("[outparam] ReadSystemConfig error\n");
return 1;
}
// 2、初始化参数模块并加载 param_*.json
InitConfig();
int re = LoadAnalysisConfig();
if (re != 0)
{
printf("[outparam] LoadAnalysisConfig error %d, Config_Root_Path = %s\n",
re, m_system_param.config_Root_Path.c_str());
return 2;
}
// 3、走“更新参数”流程(内部会按相机填充回传参数)
m_pALLImgCheckAnalysisy = ALLImgCheckBase::GetInstance();
if (m_pALLImgCheckAnalysisy == NULL || m_pConfigManager == NULL)
{
printf("[outparam] GetInstance error\n");
return 3;
}
re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)m_pConfigManager, CHECK_CONFIG_Module);
if (re != 0)
{
printf("[outparam] UpdateConfig Module error %d\n", re);
return 4;
}
// 4、逐相机调用 GetUpdateParamOut 并写入 txt
std::ofstream ofs(strOutPath);
if (!ofs.is_open())
{
printf("[outparam] open out file fail: %s\n", strOutPath.c_str());
return 5;
}
ofs << "============ UpdateParamOut (cameraCode -> param) ============" << std::endl;
ofs << "Config_Root_Path : " << m_system_param.config_Root_Path << std::endl;
ofs << "camera num : " << m_pConfigManager->Config_instances_.size() << std::endl;
ofs << std::endl;
// 输出一行缺陷参数
auto writeFlaw = [&ofs](const std::string &strName, const flaw_info &info)
{
char line[128];
sprintf(line, " %-12s area %-14.6f gray_dis %.6f", strName.c_str(), info.area, info.gray_dis);
ofs << line << std::endl;
};
int nSucc = 0;
for (const auto &config : m_pConfigManager->Config_instances_)
{
const std::string strCamera = config.first;
UpdateParamOutST paramOut;
int rGet = m_pALLImgCheckAnalysisy->GetUpdateParamOut(strCamera, paramOut);
ofs << "----------------- camera: " << strCamera
<< " GetUpdateParamOut = " << rGet << " -----------------" << std::endl;
if (rGet != 0)
{
ofs << " GetUpdateParamOut Fail " << rGet << std::endl
<< std::endl;
printf("[outparam] cam %-8s GetUpdateParamOut Fail %d\n", strCamera.c_str(), rGet);
continue;
}
{
char line[128];
sprintf(line, " pixel_precision_x %.6f pixel_precision_y %.6f",
paramOut.pixel_precision_x, paramOut.pixel_precision_y);
ofs << line << std::endl;
}
ofs << " qx area / gray_dis" << std::endl;
writeFlaw("aotudian", paramOut.aotudian);
writeFlaw("zangwu", paramOut.zangwu);
writeFlaw("line", paramOut.line);
writeFlaw("dianzhuang", paramOut.dianzhuang);
writeFlaw("xianwei", paramOut.xianwei);
writeFlaw("posun", paramOut.posun);
ofs << std::endl;
printf("[outparam] cam %-8s ok pixel %.6f/%.6f aotudian(%.6f,%.6f) zangwu(%.6f,%.6f) line(%.6f,%.6f)\n",
strCamera.c_str(), paramOut.pixel_precision_x, paramOut.pixel_precision_y,
paramOut.aotudian.area, paramOut.aotudian.gray_dis,
paramOut.zangwu.area, paramOut.zangwu.gray_dis,
paramOut.line.area, paramOut.line.gray_dis);
nSucc++;
}
ofs << "============ end, camera ok num " << nSucc << " ============" << std::endl;
ofs.close();
printf("[outparam] dump done, cam ok %d / %zu, file: %s\n",
nSucc, m_pConfigManager->Config_instances_.size(), strOutPath.c_str());
return nSucc > 0 ? 0 : 6;
}
int deal::InitExtractImg()
{
m_pextractImg = ExtractBase::GetInstance();

@ -517,6 +517,9 @@ public:
~deal();
int start();
// 测试用: 仅加载配置, 调用 GetUpdateParamOut 把各相机的参数导出到 txt
int DumpUpdateParamOut(const std::string &strOutPath);
private:
// 初始化
int Init();

@ -92,6 +92,7 @@ int main(int argc, char *argv[])
cout << "*** 6、./test_JBL_Check -rjson filepath: 单张复测filepath xx/xx/3A3K380001B1DK_20240408_152157_Main_0_2_L255" << endl;
cout << "*** 6、./test_JBL_Check -rjsonall filepath: 一套图复测filepath xx/xx/" << endl;
cout << "*** 7、./test_CellAOI -decode [dir]: 批量解码 .ytimage → .png 到 /home/aidlux/BOE/CELL_AOI/decode_img" << endl;
cout << "*** 8、./test_CellAOI -outparam [txt]: 导出各相机更新参数后的参数值到 txt默认 ./UpdateParamOut.txt" << endl;
cout << "******************************************************" << endl;
return 0;
@ -106,6 +107,9 @@ int main(int argc, char *argv[])
bool bDecodeMode = false;
std::string decodeInputDir;
bool bOutParamMode = false;
std::string outParamTxt = "./UpdateParamOut.txt";
if (argc > 1 && string(argv[1]) != "-h")
{
@ -158,6 +162,15 @@ int main(int argc, char *argv[])
{
test.runConfig.det_Type = RUNTYPE_RUN_Merge_Img;
}
else if (string(argv[i]) == "-outparam")
{
bOutParamMode = true;
if (i + 1 < argc && argv[i + 1][0] != '-')
{
outParamTxt = string(argv[i + 1]);
i++;
}
}
if (string(argv[i]) == "-s")
{
test.runConfig.bSaveProcessImg = true;
@ -310,6 +323,18 @@ int main(int argc, char *argv[])
return (successCount > 0) ? 0 : -1;
}
// ====== 参数导出模式 (-outparam) ======
if (bOutParamMode)
{
printf("\n========== 参数导出模式 (-outparam) ==========\n");
printf(" 输出文件: %s\n", outParamTxt.c_str());
printf("==============================================\n\n");
int re = test.DumpUpdateParamOut(outParamTxt);
printf("[outparam] DumpUpdateParamOut return %d\n", re);
return re;
}
test.runConfig.print("config");
// getchar();
signal(SIGINT, handler);

Loading…
Cancel
Save