update 完善新的缺陷分类

dev_lsy
liusiyang 1 week ago
parent e8fa455ae8
commit bf853544ec

@ -9,21 +9,30 @@
#ifndef AICommonDefine_H_ #ifndef AICommonDefine_H_
#define AICommonDefine_H_ #define AICommonDefine_H_
// AI缺陷分类缺陷的种类(只含主检测+分类的缺陷;支架偏移/支架缺失/把手缺失为传统算法检出,铜箔标签(TBBQ)由标签检测上报,均不走AI分类) // AI缺陷分类缺陷的种类(只含主检测+分类模型输出的类别;支架偏移/支架缺失/把手缺失为传统算法检出,
// 铜箔标签缺陷(TBBQ)同时可能由标签检测上报;顺序需与分类模型输出的 label 顺序一致)
// 判定规则:
// 1) DarkAoHen(暗场凹痕)只有暗场相机存在,明场相机分到该类时按 QiTa(其他)处理;
// 2) DarkAoHen 目前不做检测,分到该类按 OK 处理(不上报缺陷,仅记日志);
// 3) label 超出本表范围(AI_CLass_QX_NAME_count)时,按 TBMark(铜箔标记)处理。
enum AI_CLass_QX_NAME_ enum AI_CLass_QX_NAME_
{ {
AI_CLass_QX_NAME_CGMark, // 把手标记 AI_CLass_QX_NAME_DarkAoHen, // 暗场凹痕(只有暗场检出)
AI_CLass_QX_NAME_BQBMark, // 补强板标记
AI_CLass_QX_NAME_TBMark, // 铜箔标记 AI_CLass_QX_NAME_TBMark, // 铜箔标记
AI_CLass_QX_NAME_QiPao, // 气泡
AI_CLass_QX_NAME_TBBQ, // 标签(铜箔面不良标签)
AI_CLass_QX_NAME_QiTa, // 其他
AI_CLass_QX_NAME_count, AI_CLass_QX_NAME_count,
}; };
// 缺陷项对应在参数中的名称(顺序需与分类模型输出的label顺序一致) // 缺陷项对应在参数中的名称(顺序需与分类模型输出的label顺序一致)
static const std::string AI_CLass_QX_NAME_Names[] = static const std::string AI_CLass_QX_NAME_Names[] =
{ {
"CGMark", "DarkAoHen",
"BQBMark",
"TBMark", "TBMark",
"QiPao",
"TBBQ",
"QiTa",
}; };
#endif #endif

@ -60,10 +60,11 @@ enum ERROR_TYPE_
ERROR_TYPE_ZJ_PianYi, // 1 支架偏移 ERROR_TYPE_ZJ_PianYi, // 1 支架偏移
ERROR_TYPE_ZJ_QueShi, // 2 支架缺失 ERROR_TYPE_ZJ_QueShi, // 2 支架缺失
ERROR_TYPE_CGMo_QueShi, // 3 把手缺失 ERROR_TYPE_CGMo_QueShi, // 3 把手缺失
ERROR_TYPE_CGMark, // 4 把手标记 ERROR_TYPE_DarkAoHen, // 4 暗场凹痕
ERROR_TYPE_BQBMark, // 5 补强板标记 ERROR_TYPE_QiPao, // 5 气泡
ERROR_TYPE_TBBQ, // 6 铜箔标签 ERROR_TYPE_TBBQ, // 6 铜箔标签
ERROR_TYPE_TBMark, // 7 铜箔标记 ERROR_TYPE_TBMark, // 7 铜箔标记
ERROR_TYPE_QiTa, // 8 其他
ERROR_TYPE_COUNT, ERROR_TYPE_COUNT,
}; };
extern std::vector<std::string> QX_Result_Names; extern std::vector<std::string> QX_Result_Names;

@ -429,10 +429,15 @@ int ImageResultJudge::ResultJudge(std::shared_ptr<ImageAllResult> pImageResult)
std::string resultType = "OK"; std::string resultType = "OK";
// PIN_PianYi, 不受区域参数控制; // 不受区域参数控制的缺陷类型:区域参数未配置/未开启时,仍按"检出即 NG"上报
if (!Judge_Status && (config_qx_type == CONFIG_QX_NAME_cell_ZJ_PianYi || config_qx_type == CONFIG_QX_NAME_cell_ZJ_QueShi || config_qx_type == CONFIG_QX_NAME_cell_CGMo_QueShi)) // ZJ_PianYi/ZJ_QueShi/CGMo_QueShi:传统算法检出
{ // TBBQ(铜箔标签):标签检测(或AI分类)给出,本身已按 BQ_Detect 开关/检出结果判定,不再受区域参数控制
pQxLog->AddCheckstr(PrintLevel_3, "qx info", " ZJ_PianYi | ZJ_QueShi | CGMo_QueShi: region param not used -> report NG by base judge"); if (!Judge_Status && (config_qx_type == CONFIG_QX_NAME_cell_ZJ_PianYi ||
config_qx_type == CONFIG_QX_NAME_cell_ZJ_QueShi ||
config_qx_type == CONFIG_QX_NAME_cell_CGMo_QueShi ||
config_qx_type == CONFIG_QX_NAME_cell_TBBQ))
{
pQxLog->AddCheckstr(PrintLevel_3, "qx info", " %s: region param not used -> report NG by base judge", qx_name.c_str());
Judge_Status = true; Judge_Status = true;
bNG_Status = true; bNG_Status = true;
} }

@ -20,7 +20,7 @@
// AI缺陷分类模型开关:当前暂无分类模型(Class.engine),分类流程代码先预留; // AI缺陷分类模型开关:当前暂无分类模型(Class.engine),分类流程代码先预留;
// 待分类模型部署后,将 AI_CLASS_MODEL_ENABLE 置 1,即可恢复 AI_QX_Class_Thread 中的AI分类流程 // 待分类模型部署后,将 AI_CLASS_MODEL_ENABLE 置 1,即可恢复 AI_QX_Class_Thread 中的AI分类流程
#define AI_CLASS_MODEL_ENABLE 0 #define AI_CLASS_MODEL_ENABLE 1
// 把手提取/判定参数(下面宏是“未配置 JSON 时”的默认值;现场可在参数 JSON 的 Handle_Detect.form.handle_param // 把手提取/判定参数(下面宏是“未配置 JSON 时”的默认值;现场可在参数 JSON 的 Handle_Detect.form.handle_param
// 下按注释标注的键名配置同名参数覆盖它们,按产品/现场情况调整,无需改代码重编译): // 下按注释标注的键名配置同名参数覆盖它们,按产品/现场情况调整,无需改代码重编译):
@ -107,25 +107,13 @@ static std::string ClsTrimStr(const std::string &str)
return str.substr(begin, end - begin + 1); return str.substr(begin, end - begin + 1);
} }
// 组装程序内默认缺陷名称列表(AI_CLass_QX_NAME_Names) // 分类映射配置:分类label -> 缺陷名称
static std::vector<std::string> BuildDefaultAIQXNames()
{
std::vector<std::string> vecNames;
for (int i = 0; i < AI_CLass_QX_NAME_count; i++)
{
vecNames.push_back(AI_CLass_QX_NAME_Names[i]);
}
return vecNames;
}
// 分类映射配置:缺陷名称列表(索引=行序) + 分类label->缺陷名称 映射
struct ClsLabelConfig struct ClsLabelConfig
{ {
std::vector<std::string> vecNames; // 缺陷名称列表
std::map<int, std::string> mapLabelName; // 分类 label -> 缺陷名称 std::map<int, std::string> mapLabelName; // 分类 label -> 缺陷名称
}; };
// 读取分类映射配置(每行:label索引:缺陷名称;冒号后名称按行序构成缺陷名称列表;# 后内容忽略) // 读取分类映射配置(每行:label索引:缺陷名称;# 后内容忽略)
static ClsLabelConfig ReadClsLabelConfig(const std::string &strFilePath) static ClsLabelConfig ReadClsLabelConfig(const std::string &strFilePath)
{ {
ClsLabelConfig config; ClsLabelConfig config;
@ -156,13 +144,12 @@ static ClsLabelConfig ReadClsLabelConfig(const std::string &strFilePath)
} }
continue; continue;
} }
// label索引:缺陷名称(冒号后名称按行序构成缺陷名称列表) // label索引:缺陷名称
std::string strKey = ClsTrimStr(strLine.substr(0, nPos)); std::string strKey = ClsTrimStr(strLine.substr(0, nPos));
std::string strValue = ClsTrimStr(strLine.substr(nPos + 1)); std::string strValue = ClsTrimStr(strLine.substr(nPos + 1));
if (!strKey.empty() && !strValue.empty()) if (!strKey.empty() && !strValue.empty())
{ {
config.mapLabelName[atoi(strKey.c_str())] = strValue; config.mapLabelName[atoi(strKey.c_str())] = strValue;
config.vecNames.push_back(strValue); // 行序即缺陷类型索引
} }
} }
return config; return config;
@ -175,27 +162,16 @@ static const ClsLabelConfig &GetClsLabelConfig()
return config; return config;
} }
// 获取缺陷名称列表:优先取配置文件的名称列表,读不到用程序内默认列表
static const std::vector<std::string> &GetAIQXNameList()
{
static const std::vector<std::string> vecDefaultNames = BuildDefaultAIQXNames();
const ClsLabelConfig &config = GetClsLabelConfig();
if (!config.vecNames.empty())
{
return config.vecNames;
}
return vecDefaultNames;
}
// 缺陷名称 -> AI_CLass 枚举(找不到返回 count 表示无效) // 缺陷名称 -> AI_CLass 枚举(找不到返回 count 表示无效)
// 注意:按程序内 AI_CLass_QX_NAME_Names 的枚举顺序匹配,而不是映射文件的行序,
// 避免 BM_cls.txt 行数/顺序与枚举不一致时类别错位
static int ClsNameToAItype(const std::string &strName) static int ClsNameToAItype(const std::string &strName)
{ {
const std::vector<std::string> &vecNames = GetAIQXNameList(); for (int i = 0; i < AI_CLass_QX_NAME_count; i++)
for (size_t i = 0; i < vecNames.size(); i++)
{ {
if (strName == vecNames[i]) if (strName == AI_CLass_QX_NAME_Names[i])
{ {
return (int)i; return i;
} }
} }
return AI_CLass_QX_NAME_count; return AI_CLass_QX_NAME_count;
@ -221,32 +197,31 @@ static std::map<int, int> BuildLabelTypeMap()
return mapLabelType; return mapLabelType;
} }
// 获取分类 label 对应的 AI 缺陷类型:优先配置文件(只读一次),读不到用默认顺序 // 获取分类 label 对应的 AI 缺陷类型:优先配置文件(只读一次),读不到按 label 顺序兜底
static int GetClsTypeByLabel(int nLabel) // 规则:
// ① label 超出 [0, AI_CLass_QX_NAME_count)(含推理失败返回的负值)→ 视为 TBMark;
// ② DarkAoHen(暗场凹痕)只有暗场相机存在:明场相机分到该类时按 QiTa(其他)处理。
static int GetClsTypeByLabel(int nLabel, bool bIsDark)
{ {
// ① 超出程序的类别表(模型类别数与程序不一致)→ 统一按铜箔标记处理
if (nLabel < 0 || nLabel >= AI_CLass_QX_NAME_count)
{
return AI_CLass_QX_NAME_TBMark;
}
// 未被映射文件覆盖时,按程序内 AI_CLass_QX_NAME_Names 的顺序与 label 对应
int cls_num = nLabel;
static const std::map<int, int> mapLabelType = BuildLabelTypeMap(); static const std::map<int, int> mapLabelType = BuildLabelTypeMap();
std::map<int, int>::const_iterator it = mapLabelType.find(nLabel); std::map<int, int>::const_iterator it = mapLabelType.find(nLabel);
if (it != mapLabelType.end()) if (it != mapLabelType.end())
{ {
return it->second; cls_num = it->second;
} }
// 映射文件未读到、或该 label 未在文件中配置时,按程序内默认顺序兜底(避免文件缺失/不全导致异常) // ② 暗场凹痕只有暗场检出:明场分到该类时按"其他"处理
int cls_num = AI_CLass_QX_NAME_count; if (cls_num == AI_CLass_QX_NAME_DarkAoHen && !bIsDark)
switch (nLabel)
{ {
case 0: cls_num = AI_CLass_QX_NAME_QiTa;
cls_num = AI_CLass_QX_NAME_CGMark;
break;
case 1:
cls_num = AI_CLass_QX_NAME_BQBMark;
break;
case 2:
cls_num = AI_CLass_QX_NAME_TBMark;
break;
default:
cls_num = AI_CLass_QX_NAME_CGMark;
break;
} }
return cls_num; return cls_num;
} }
@ -3520,8 +3495,34 @@ int ImgCheckAnalysisy::AI_QX_Class_Thread()
pAIDet = AI_Factory->Class; pAIDet = AI_Factory->Class;
} }
int deal_image_width = pAIDet->input_0.width; // 明/暗场判定:相机名含 "dark" 视为暗场(与 ALIGN_REUSE_*、暗场检测模型判定一致)
int deal_image_height = pAIDet->input_0.height; std::string strProductName, strCameraName;
GetProductCameraStr(strProductName, strCameraName);
const bool bIsDark = !ReplaceDarkWithBright(strCameraName).empty();
int deal_image_width = pAIDet ? pAIDet->input_0.width : 0;
int deal_image_height = pAIDet ? pAIDet->input_0.height : 0;
// 分类模型不可用(未加载/未初始化/输入尺寸异常):全部按 TBMark 兑底(与无分类模型时行为一致);
// 否则裁剪/推理会失败,且 blob 的 AIclasstype 保持默认值 0 会被当成“支架偏移”上报
if (!pAIDet || !pAIDet->m_bInitSuccess || deal_image_width <= 0 || deal_image_height <= 0)
{
int defaultqx = AIClassTypeToConfigType(AI_CLass_QX_NAME_TBMark);
for (int i = 0; i < blobs.blobCount; i++)
{
blobs.blobTab[i].AIclasstype = defaultqx;
}
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "QX_Class",
" class model not ready(m_bInitSuccess %d, input [w %d h %d]), all %d qx -> TBMark(%d)",
pAIDet ? (int)pAIDet->m_bInitSuccess : 0, deal_image_width, deal_image_height, blobs.blobCount, defaultqx);
return 0;
}
// 先统一置为无效类型:分类未提交/失败(裁剪失败、label 非法等)的 blob 不会落到某个真实缺陷类型上
for (int i = 0; i < blobs.blobCount; i++)
{
blobs.blobTab[i].AIclasstype = CONFIG_QX_NAME_count;
}
const int totalTasks = blobs.blobCount; const int totalTasks = blobs.blobCount;
int submitted = 0; int submitted = 0;
@ -3538,8 +3539,8 @@ int ImgCheckAnalysisy::AI_QX_Class_Thread()
ERROR_DOTS_BLOB_DATA *pblob = &blobs.blobTab[submitted]; ERROR_DOTS_BLOB_DATA *pblob = &blobs.blobTab[submitted];
if (pblob->ErrType == ERR_TYPE_2) if (pblob->ErrType == ERR_TYPE_2)
{ {
// ERR_TYPE_2不参与分类,按默认AI类别(把手标记)处理 // ERR_TYPE_2 不参与分类,按默认类别(铜箔标记)处理
pblob->AIclasstype = CONFIG_QX_NAME_cell_CGMark; pblob->AIclasstype = AIClassTypeToConfigType(AI_CLass_QX_NAME_TBMark);
submitted++; submitted++;
completed++; completed++;
continue; continue;
@ -3567,6 +3568,9 @@ int ImgCheckAnalysisy::AI_QX_Class_Thread()
} }
else else
{ {
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "QX_Class",
"blob idx %d crop class img failed(re %d) roi[%d %d %d %d] -> skip",
submitted, re, roi.x, roi.y, roi.width, roi.height);
completed++; completed++;
} }
@ -3582,8 +3586,24 @@ int ImgCheckAnalysisy::AI_QX_Class_Thread()
int temClass = result->cls_label; int temClass = result->cls_label;
// 分类 label 映射:优先读映射配置文件(BM_cls.txt),读不到用默认顺序 // label 越界(含推理失败返回的负值):按规则统一视为 TBMark
int cls_num = GetClsTypeByLabel(temClass); if (temClass < 0 || temClass >= AI_CLass_QX_NAME_count)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "QX_Class",
"blob idx %d invalid class label %d (valid 0~%d), use TBMark",
result->id, temClass, AI_CLass_QX_NAME_count - 1);
}
// 分类 label 映射:优先读映射配置文件(BM_cls.txt),读不到按 label 顺序;
// 明场分到暗场凹痕(DarkAoHen)时按 QiTa 处理
int cls_num = GetClsTypeByLabel(temClass, bIsDark);
// 明细日志:原始 label -> 最终类别(仅 -s / 详细日志级别输出)
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "QX_Class",
"blob idx %d label %d -> %s score %.3f (dark %d)",
result->id, temClass,
(cls_num >= 0 && cls_num < AI_CLass_QX_NAME_count) ? AI_CLass_QX_NAME_Names[cls_num].c_str() : "invalid",
result->cls_score, (int)bIsDark);
// std::string strclassName = AI_CLass_QX_NAME_Names[cls_num]; // std::string strclassName = AI_CLass_QX_NAME_Names[cls_num];
// printf("AI Class num %d = %s %f\n", cls_num, strclassName.c_str(), result->cls_score); // printf("AI Class num %d = %s %f\n", cls_num, strclassName.c_str(), result->cls_score);
@ -3856,21 +3876,25 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
int ImgCheckAnalysisy::AIClassTypeToConfigType(int nAIQXType) int ImgCheckAnalysisy::AIClassTypeToConfigType(int nAIQXType)
{ {
// 只有主检测+分类的缺陷在映射表中;支架偏移/支架缺失/把手缺失(传统检出)、铜箔标签(标签检测)不走AI分类 // AI 分类类别 -> 缺陷类型;支架偏移/支架缺失/把手缺失为传统算法检出,不在本表内
int resultError_type = CONFIG_QX_NAME_cell_CGMark; // 未知类别(含 AI_CLass_QX_NAME_count 及越界值)统一按铜箔标记处理
int resultError_type = CONFIG_QX_NAME_cell_TBMark;
switch (nAIQXType) switch (nAIQXType)
{ {
case AI_CLass_QX_NAME_CGMark: case AI_CLass_QX_NAME_DarkAoHen:
resultError_type = CONFIG_QX_NAME_cell_CGMark; resultError_type = CONFIG_QX_NAME_cell_DarkAoHen;
break;
case AI_CLass_QX_NAME_BQBMark:
resultError_type = CONFIG_QX_NAME_cell_BQBMark;
break; break;
case AI_CLass_QX_NAME_TBMark: case AI_CLass_QX_NAME_TBMark:
resultError_type = CONFIG_QX_NAME_cell_TBMark; resultError_type = CONFIG_QX_NAME_cell_TBMark;
break; break;
case AI_CLass_QX_NAME_count: // 无效类别(分类映射配置中不存在):不参与缺陷分析 case AI_CLass_QX_NAME_QiPao:
resultError_type = CONFIG_QX_NAME_count; resultError_type = CONFIG_QX_NAME_cell_QiPao;
break;
case AI_CLass_QX_NAME_TBBQ:
resultError_type = CONFIG_QX_NAME_cell_TBBQ;
break;
case AI_CLass_QX_NAME_QiTa:
resultError_type = CONFIG_QX_NAME_cell_QiTa;
break; break;
default: default:
break; break;
@ -3910,12 +3934,20 @@ int ImgCheckAnalysisy::BLobToDetResult()
int config_qx_type = blobs.blobTab[i].AIclasstype; int config_qx_type = blobs.blobTab[i].AIclasstype;
if (config_qx_type < 0 || config_qx_type >= CONFIG_QX_NAME_count) if (config_qx_type < 0 || config_qx_type >= CONFIG_QX_NAME_count)
{ {
// AI 分类无对应缺陷类型(无效类别)时,不参与缺陷结果分析 // AI 分类无对应缺陷类型(无效类别/分类失败)时,不参与缺陷结果分析
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult",
"blob idx %d invalid AIclasstype %d skip", i, config_qx_type); "blob idx %d invalid AIclasstype %d skip", i, config_qx_type);
continue; continue;
} }
// 暗场凹痕目前不做检测:分到该类的 blob 直接按 OK 处理(不产生缺陷条目,仅记日志)
if (config_qx_type == CONFIG_QX_NAME_cell_DarkAoHen)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult",
"blob idx %d AIclasstype DarkAoHen -> OK (not detected yet), skip", i);
continue;
}
float JudgArea = blobs.blobTab[i].JudgArea; float JudgArea = blobs.blobTab[i].JudgArea;
float fsecondArea = JudgArea; float fsecondArea = JudgArea;
std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type];

@ -36,28 +36,31 @@ static const std::string WHITE_BLCAK_Names[] =
{ {
"black", "black",
"white"}; "white"};
// 检测缺陷的种类 // 检测缺陷的种类(前 7 项与 defect_list.json 前 7 条一一对应,勿随意调整顺序;
// 新增类型统一追加在末尾,结果名称/代码按名称对齐,不依赖下标)
enum CONFIG_QX_NAME_ enum CONFIG_QX_NAME_
{ {
CONFIG_QX_NAME_cell_ZJ_PianYi, // 分类 支架偏移 CONFIG_QX_NAME_cell_ZJ_PianYi, // 分类 支架偏移
CONFIG_QX_NAME_cell_ZJ_QueShi, // 分类 支架缺失 CONFIG_QX_NAME_cell_ZJ_QueShi, // 分类 支架缺失
CONFIG_QX_NAME_cell_CGMo_QueShi, // 分类 把手缺失 CONFIG_QX_NAME_cell_CGMo_QueShi, // 分类 把手缺失
CONFIG_QX_NAME_cell_CGMark, // 分类 把手标记 CONFIG_QX_NAME_cell_DarkAoHen, // 分类 暗场凹痕(AI分类,仅暗场;目前不检测)
CONFIG_QX_NAME_cell_BQBMark, // 分类 补强板标记 CONFIG_QX_NAME_cell_QiPao, // 分类 气泡(AI分类)
CONFIG_QX_NAME_cell_TBBQ, // 分类 铜箔标签 CONFIG_QX_NAME_cell_TBBQ, // 分类 铜箔标签(标签检测 / AI分类)
CONFIG_QX_NAME_cell_TBMark, // 分类 铜箔标记 CONFIG_QX_NAME_cell_TBMark, // 分类 铜箔标记(AI分类)
CONFIG_QX_NAME_cell_QiTa, // 分类 其他(AI分类)
CONFIG_QX_NAME_count, CONFIG_QX_NAME_count,
}; };
// 缺陷项对应在参数中的名称 // 缺陷项对应在参数中的名称(Check_Param 的表单键名;顺序与上面对应)
static std::vector<std::string> CONFIG_QX_NAME_Names = static std::vector<std::string> CONFIG_QX_NAME_Names =
{ {
"ZJ_PianYi", "ZJ_PianYi",
"ZJ_QueShi", "ZJ_QueShi",
"CGMo_QueShi", "CGMo_QueShi",
"CGMark", "DarkAoHen",
"BQBMark", "QiPao",
"TBBQ", "TBBQ",
"TBMark", "TBMark",
"QiTa",
}; };
// 分析类型 // 分析类型

@ -10,6 +10,7 @@
#include "ConfigManager.h" #include "ConfigManager.h"
#include <regex> #include <regex>
#include "ConfigBase.h" #include "ConfigBase.h"
#include "CheckConfigDefine.h"
#include "../../AlgorithmModule/include/ImgCheckConfig.h" #include "../../AlgorithmModule/include/ImgCheckConfig.h"
ConfigManager::ConfigManager() ConfigManager::ConfigManager()
{ {
@ -22,25 +23,29 @@ ConfigManager::~ConfigManager()
std::vector<ReadFlawCode> m_FlawCodeList; std::vector<ReadFlawCode> m_FlawCodeList;
// 缺陷结果名称/代码默认值(下标与 CONFIG_QX_NAME_ 一一对应;使用英文缺陷名,与 CONFIG_QX_NAME_Names 一致;
// defect_list.json 中 desc 与 CONFIG_QX_NAME_Names 同名的条目会按名称覆盖这里的值)
std::vector<std::string> QX_Result_Names = std::vector<std::string> QX_Result_Names =
{ {
"ZJ_PianYi", "ZJ_PianYi",
"ZJ_QueShi", "ZJ_QueShi",
"CGMo_QueShi", "CGMo_QueShi",
"CGMark", "DarkAoHen",
"BQBMark", "QiPao",
"TBBQ", "TBBQ",
"TBMark", "TBMark",
"QiTa",
}; };
std::vector<std::string> QX_Result_Code = std::vector<std::string> QX_Result_Code =
{ {
"M701201", "M701201",
"M200214", "M200214",
"M200215", "M200215",
"M200216", "M200230", // TODO 暗场凹痕:缺陷代码待平台确认
"M200217", "M200231", // TODO 气泡:缺陷代码待平台确认
"M200218", "M200218",
"M200219", "M200219",
"M200232", // TODO 其他:缺陷代码待平台确认
}; };
int ReadFlawCodeConfig(std::string json_path) int ReadFlawCodeConfig(std::string json_path)
@ -85,18 +90,36 @@ int ReadFlawCodeConfig(std::string json_path)
} }
m_FlawCodeList.push_back(tem); m_FlawCodeList.push_back(tem);
} }
for(int i = 0; i < m_FlawCodeList.size(); i++) // 结果名称/代码表按“缺陷名称”与程序内缺陷类型(CONFIG_QX_NAME_Names)对齐:
// defect_list.json 的 desc 字段(可用';'分隔多个名称)与 CONFIG_QX_NAME_Names 同名时覆盖名称/代码。
// 不再按下标覆盖:缺陷列表新增/减少/换序时不会把 A 类型的名称/代码写到 B 类型上。
while (QX_Result_Names.size() < (size_t)CONFIG_QX_NAME_count)
{ {
if(i >= QX_Result_Names.size()) { QX_Result_Names.push_back("");
QX_Result_Names.push_back(m_FlawCodeList.at(i).flaw_name);
QX_Result_Code.push_back(m_FlawCodeList.at(i).flaw_code);
} }
else while (QX_Result_Code.size() < (size_t)CONFIG_QX_NAME_count)
{ {
QX_Result_Names.at(i) = m_FlawCodeList.at(i).flaw_name; QX_Result_Code.push_back("");
QX_Result_Code.at(i) = m_FlawCodeList.at(i).flaw_code; }
for (size_t i = 0; i < m_FlawCodeList.size(); i++)
{
for (int iqx = 0; iqx < CONFIG_QX_NAME_count; iqx++)
{
bool bMatch = false;
for (size_t k = 0; k < m_FlawCodeList.at(i).config_flaw_name.size(); k++)
{
if (m_FlawCodeList.at(i).config_flaw_name.at(k) == CONFIG_QX_NAME_Names.at(iqx))
{
bMatch = true;
break;
}
}
if (bMatch)
{
QX_Result_Names.at(iqx) = m_FlawCodeList.at(i).flaw_name;
QX_Result_Code.at(iqx) = m_FlawCodeList.at(i).flaw_code;
}
} }
} }
return 0; return 0;
} }

Loading…
Cancel
Save