Compare commits

...

17 Commits

@ -102,7 +102,7 @@ int main(int argc, char *argv[])
GPU_Config gpu; GPU_Config gpu;
gpu.gpu_0 = true; gpu.gpu_0 = true;
gpu.gpu_1 = true; gpu.gpu_1 = false;
AI_Factory->InitALLAIModle(gpu); AI_Factory->InitALLAIModle(gpu);
std::shared_ptr<AIModel_Base> BOE_Edge_Detect = AI_Factory->BOE_Edge_Detect; std::shared_ptr<AIModel_Base> BOE_Edge_Detect = AI_Factory->BOE_Edge_Detect;

@ -154,6 +154,7 @@ public:
private: private:
public: public:
std::shared_ptr<AIModel_Base> Defect; std::shared_ptr<AIModel_Base> Defect;
std::shared_ptr<AIModel_Base> Defect_QueXi;
std::shared_ptr<AIModel_Base> Class; std::shared_ptr<AIModel_Base> Class;
std::shared_ptr<AIModel_Base> Pin_Loc; std::shared_ptr<AIModel_Base> Pin_Loc;

@ -42,20 +42,31 @@ int AIFactory::InitALLAIModle(GPU_Config gupconfig)
Defect = AIModel_Base::GetInstance(); Defect = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config; AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig); edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/Defect.engine"; edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/KK/Defect.engine";
edge_config.strName = "CA_Det"; edge_config.strName = "Det";
edge_config.inputType = AIModel_Base::Input_HWC; edge_config.inputType = AIModel_Base::Input_CHW;
edge_config.Stream_num = 2; edge_config.Stream_num = 2;
Defect->Init(edge_config); Defect->Init(edge_config);
} }
if (!Defect_QueXi)
{
Defect_QueXi = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/KK/QueXi.engine";
edge_config.strName = "QueXi_Det";
edge_config.inputType = AIModel_Base::Input_CHW;
edge_config.Stream_num = 2;
Defect_QueXi->Init(edge_config);
}
if (!Class) if (!Class)
{ {
Class = AIModel_Base::GetInstance(); Class = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config jbl_config; AIModel_Base::AIModelRun_Config jbl_config;
jbl_config.gpuconfig.copy(gupconfig); jbl_config.gpuconfig.copy(gupconfig);
jbl_config.strPath = "/home/aidlux/BOE/UseModel_ZB/Class_10.engine"; jbl_config.strPath = "/home/aidlux/BOE/UseModel_ZB/KK/Class.engine";
jbl_config.inputType = AIModel_Base::Input_HWC; jbl_config.inputType = AIModel_Base::Input_CHW;
jbl_config.strName = "CA_Class"; jbl_config.strName = "Class";
jbl_config.IsClass = true; jbl_config.IsClass = true;
Class->Init(jbl_config); Class->Init(jbl_config);
} }
@ -64,9 +75,9 @@ int AIFactory::InitALLAIModle(GPU_Config gupconfig)
Pin_Loc = AIModel_Base::GetInstance(); Pin_Loc = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config; AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig); edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/PinLoc.engine"; edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/KK/PinLoc.engine";
edge_config.strName = "TA_Det"; edge_config.strName = "Pin_Loc";
edge_config.inputType = AIModel_Base::Input_HWC; edge_config.inputType = AIModel_Base::Input_CHW;
edge_config.Stream_num = 2; edge_config.Stream_num = 2;
Pin_Loc->Init(edge_config); Pin_Loc->Init(edge_config);
} }
@ -75,9 +86,9 @@ int AIFactory::InitALLAIModle(GPU_Config gupconfig)
Align_Outer = AIModel_Base::GetInstance(); Align_Outer = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config; AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig); edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/AlignOuter.engine"; edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/KK/AlignOuter.engine";
edge_config.strName = "Align"; edge_config.strName = "Align_Outer";
edge_config.inputType = AIModel_Base::Input_HWC; edge_config.inputType = AIModel_Base::Input_CHW;
Align_Outer->Init(edge_config); Align_Outer->Init(edge_config);
} }
if (!Align_Inner) if (!Align_Inner)
@ -85,9 +96,9 @@ int AIFactory::InitALLAIModle(GPU_Config gupconfig)
Align_Inner = AIModel_Base::GetInstance(); Align_Inner = AIModel_Base::GetInstance();
AIModel_Base::AIModelRun_Config edge_config; AIModel_Base::AIModelRun_Config edge_config;
edge_config.gpuconfig.copy(gupconfig); edge_config.gpuconfig.copy(gupconfig);
edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/AlignInner.engine"; edge_config.strPath = "/home/aidlux/BOE/UseModel_ZB/KK/AlignInner.engine";
edge_config.strName = "Mark"; edge_config.strName = "Align_Inner";
edge_config.inputType = AIModel_Base::Input_HWC; edge_config.inputType = AIModel_Base::Input_CHW;
Align_Inner->Init(edge_config); Align_Inner->Init(edge_config);
} }
m_bInitSucc = true; m_bInitSucc = true;

@ -78,11 +78,14 @@ set(ModuleName "")
# #
set(CMAKE_INSTALL_PREFIX /usr/local/zb_socket CACHE PATH "Install path prefix" FORCE) set(CMAKE_INSTALL_PREFIX /usr/local/zb_socket CACHE PATH "Install path prefix" FORCE)
set(HEADER_FILES include/ImgCheckBase.h include/ImgCheckConfig.h) set(HEADER_FILES include/ImgCheckBase.h include/ImgCheckConfig.h)
# _socket
set_target_properties(TY_Check PROPERTIES OUTPUT_NAME "TY_Check_socket")
# #
install(TARGETS TY_Check install(TARGETS TY_Check
LIBRARY DESTINATION lib # CMAKE_INSTALL_PREFIX/lib LIBRARY DESTINATION lib # CMAKE_INSTALL_PREFIX/lib
ARCHIVE DESTINATION lib/static ARCHIVE DESTINATION lib/static
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
PUBLIC_HEADER DESTINATION include) # CMAKE_INSTALL_PREFIX/include PUBLIC_HEADER DESTINATION include) # CMAKE_INSTALL_PREFIX/include
# # _socket
install(FILES ${HEADER_FILES} DESTINATION include) install(FILES include/ImgCheckBase.h DESTINATION include RENAME ImgCheckBase_socket.h)
install(FILES include/ImgCheckConfig.h DESTINATION include RENAME ImgCheckConfig_socket.h)

@ -13,31 +13,27 @@
enum AI_CLass_QX_NAME_ enum AI_CLass_QX_NAME_
{ {
AI_CLass_QX_NAME_aotudian, // 凹凸点 AI_CLass_QX_NAME_PIN_PoSun, // PIN破损
AI_CLass_QX_NAME_PIN_QueShi, // PIN缺失
AI_CLass_QX_NAME_BTB_DuanLie, // BTB断裂
AI_CLass_QX_NAME_LianXi, // 连锡
AI_CLass_QX_NAME_QueXi, // 缺锡
AI_CLass_QX_NAME_YiWu, // 异物
AI_CLass_QX_NAME_C_BianXing, // C型卡口异常
AI_CLass_QX_NAME_other, // 其他 AI_CLass_QX_NAME_other, // 其他
AI_CLass_QX_NAME_line, // 线状
AI_CLass_QX_NAME_zangwu, // 脏污
AI_CLass_QX_NAME_dianzhuang, // 点状
AI_CLass_QX_NAME_posun, // 破损
AI_CLass_QX_NAME_xianwei, // 纤维
AI_CLass_QX_NAME_shuizi, // 水渍
AI_CLass_QX_NAME_danban, // 淡斑
AI_CLass_QX_NAME_fuchen, // 浮尘
AI_CLass_QX_NAME_count, AI_CLass_QX_NAME_count,
}; };
// 缺陷项对应在参数中的名称 // 缺陷项对应在参数中的名称
static const std::string AI_CLass_QX_NAME_Names[] = static const std::string AI_CLass_QX_NAME_Names[] =
{ {
"aotudian", "PIN_PoSun",
"qx", "PIN_QueShi",
"line", "BTB_DuanLie",
"zangwu", "LianXi",
"dianzhuang", "QueXi",
"posun", "YiWu",
"xianwei", "C_BianXing",
"shuizi", "other",
"danban",
"fuchen",
}; };
#endif #endif

@ -65,6 +65,11 @@ public:
std::string GetErrorInfo(); std::string GetErrorInfo();
// 获取模板外接矩形
const cv::RotatedRect &GetTplOuterRect() const { return m_tplOuterRect; }
// 获取模板 pin blob 轮廓点集
const std::vector<std::vector<cv::Point>> &GetTplPinContours() const { return m_tplPinContours; }
private: private:
// 加载运行参数 // 加载运行参数
int LoadRunConfig(void *p); int LoadRunConfig(void *p);
@ -125,6 +130,9 @@ private:
int InitAIFactory(); int InitAIFactory();
// 初始化模板
int InitTemplateMask();
private: private:
// 图片处理线程 // 图片处理线程
std::shared_ptr<std::thread> ptr_thread_Run; std::shared_ptr<std::thread> ptr_thread_Run;
@ -170,6 +178,9 @@ private:
std::string m_strTest; std::string m_strTest;
// 模板信息
cv::RotatedRect m_tplOuterRect; // 模板外接矩形
std::vector<std::vector<cv::Point>> m_tplPinContours; // 模板 pin blob 轮廓点集
}; };

@ -133,6 +133,10 @@ public:
int Init(std::string strcameraName); int Init(std::string strcameraName);
int StartCheck(std::shared_ptr<CameraResult> pCamera_Check_Result); int StartCheck(std::shared_ptr<CameraResult> pCamera_Check_Result);
// 设置模板信息并转发给各个检测核心
void SetTplInfo(const cv::RotatedRect &outerRect,
const std::vector<std::vector<cv::Point>> &pinContours);
private: private:
// 开启线程 // 开启线程
int StartThread(); int StartThread();

@ -51,6 +51,9 @@ public:
static float Cal2PointAngle(cv::Point p_left, cv::Point p_right); static float Cal2PointAngle(cv::Point p_left, cv::Point p_right);
// 获取 RotatedRect 长轴的方向角(归一化到 [0, 180) 度) // 获取 RotatedRect 长轴的方向角(归一化到 [0, 180) 度)
static float getLongAxisAngle(const cv::RotatedRect rect); static float getLongAxisAngle(const cv::RotatedRect rect);
// 排序RotatedRect的四个顶点
static std::vector<cv::Point2f> sort_vertices(cv::RotatedRect rrect);
// 找图片的最大外轮廓 // 找图片的最大外轮廓
static std::vector<cv::Point> getLargestContourROI(const cv::Mat &binaryImg, bool &found); static std::vector<cv::Point> getLargestContourROI(const cv::Mat &binaryImg, bool &found);
@ -59,6 +62,9 @@ public:
//创建目录 //创建目录
static int CreateDir(const std::string &dir); static int CreateDir(const std::string &dir);
// 异步存图
static int SaveImgAsync(const std::string &path, const cv::Mat &img);
// 点的距离是否过小 // 点的距离是否过小
static bool bcalDis(cv::Point p1, cv::Point p2, int disT); static bool bcalDis(cv::Point p1, cv::Point p2, int disT);
static double calDis(cv::Point p1, cv::Point p2); static double calDis(cv::Point p1, cv::Point p2);

@ -3,7 +3,7 @@
* @Date: 2025-09-11 15:32:52 * @Date: 2025-09-11 15:32:52
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-14 17:41:14 * @LastEditTime: 2025-09-14 17:41:14
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/include/ImageDetBase.h * @FilePath: /BOE_ZB_SOCKET_Detect/AlgorithmModule/include/ImageDetBase.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
#ifndef ImageDetBase_H_ #ifndef ImageDetBase_H_

@ -80,6 +80,10 @@ public:
int creatsavedir(); int creatsavedir();
// 设置模板信息(模板外接矩形 + 模板 pin blob 轮廓点集)
void SetTplInfo(const cv::RotatedRect &outerRect,
const std::vector<std::vector<cv::Point>> &pinContours);
private: private:
// 加载运行参数 // 加载运行参数
int LoadRunConfig(void *p); int LoadRunConfig(void *p);
@ -195,7 +199,7 @@ private:
int BLobToDetResult(); int BLobToDetResult();
//自适应参数区域更新 //自适应参数区域更新
int Adapt_Config(Mat img, Rect roi, bool b_update); int Adapt_Config(cv::RotatedRect tplOuterRect, cv::RotatedRect curOuterRect, cv::Mat& det_img);
std::shared_ptr<AIFactory> AI_Factory; std::shared_ptr<AIFactory> AI_Factory;
@ -287,6 +291,13 @@ private:
cv::Point m_old_cur_markLine_mark1; cv::Point m_old_cur_markLine_mark1;
cv::Point m_old_cur_markLine_mark2; cv::Point m_old_cur_markLine_mark2;
std::vector<RegionConfigST> m_old_cur_regionConfigArr; std::vector<RegionConfigST> m_old_cur_regionConfigArr;
// 模板信息
cv::RotatedRect m_tplOuterRect; // 模板外接矩形
cv::RotatedRect m_outer_rroi;
cv::RotatedRect m_inner_rroi;
std::vector<std::vector<cv::Point>> m_tplPinContours; // 模板 pin blob 轮廓点集
std::vector<std::vector<cv::Point>> m_curPinContours; // 当前 pin blob 轮廓点集
}; };
#endif #endif

@ -47,19 +47,15 @@ struct VERSION_INFO
// 检测错误代码 // 检测错误代码
enum ERROR_TYPE_ enum ERROR_TYPE_
{ {
ERROR_TYPE_OK, // 1 疑是 ERROR_TYPE_OK, // 0 正常/疑是
ERROR_TYPE_aotudian, // 2 凹凸点 ERROR_TYPE_PIN_PoSun, // 1 PIN破损
ERROR_TYPE_other, // 3 其他 ERROR_TYPE_PIN_QueShi, // 2 PIN缺失
ERROR_TYPE_line, // 4 线状 ERROR_TYPE_BTB_DuanLie, // 3 BTB断裂
ERROR_TYPE_zangwu, // 5 脏污 ERROR_TYPE_LianXi, // 4 连锡
ERROR_TYPE_edge, // 6 边缘 ERROR_TYPE_QueXi, // 5 缺锡
ERROR_TYPE_ymhs, // 7 研磨划伤 ERROR_TYPE_YiWu, // 6 异物
ERROR_TYPE_dianzhuang, // 8 点状 ERROR_TYPE_C_BianXing, // 7 C型卡口异常
ERROR_TYPE_posun, // 9 破损 ERROR_TYPE_other, // 8 其他
ERROR_TYPE_xianwei, // 10 纤维
ERROR_TYPE_shuizi, // 11 水渍
ERROR_TYPE_danban, // 12 淡斑
ERROR_TYPE_fuchen, // 13 浮尘
ERROR_TYPE_COUNT, ERROR_TYPE_COUNT,
}; };
extern std::vector<std::string> QX_Result_Names; extern std::vector<std::string> QX_Result_Names;

@ -3,7 +3,7 @@
* @Date: 2025-08-04 21:26:32 * @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-13 16:05:08 * @LastEditTime: 2025-08-13 16:05:08
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Pin_QX_Det.h * @FilePath: /BOE_ZB_SOCKET/AlgorithmModule/include/Pin_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
/* /*
@ -11,7 +11,7 @@
* @Date: 2025-08-04 21:26:32 * @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-04 21:29:05 * @LastEditTime: 2025-08-04 21:29:05
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Pin_QX_Det.h * @FilePath: /BOE_ZB_SOCKET/AlgorithmModule/include/Pin_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
/* /*
@ -59,10 +59,6 @@ public:
BaseCheckFunction *pBaseCheckFunction; BaseCheckFunction *pBaseCheckFunction;
std::string strChannel; std::string strChannel;
std::vector<QX_Result> qx_result;
std::vector<Det_ROI_Config> pin_det_roi;
std::vector<cv::Point> Det_region;
bool bSaveResultImg; bool bSaveResultImg;
DetConfigResult() DetConfigResult()
{ {
@ -72,106 +68,7 @@ public:
{ {
pBaseCheckFunction = NULL; pBaseCheckFunction = NULL;
strChannel = ""; strChannel = "";
qx_result.clear();
pin_det_roi.clear();
Det_region.clear();
bSaveResultImg = false;
}
};
enum Det_ROI_Type
{
Det_ROI_Type_UP,
Det_ROI_Type_DOWN,
Det_ROI_Type_LEFT,
Det_ROI_Type_RIGHT,
};
// 边缘搜索定位结果
struct Pin_AI_Result
{
int nresult;
cv::RotatedRect bigroi;
cv::RotatedRect smallroi;
bool buseOfft;
int offt_x;
int offt_y;
cv::Mat H;
Pin_AI_Result()
{
Init();
}
void Init()
{
buseOfft = false;
nresult = 0;
offt_x = 0;
offt_y = 0;
bigroi = cv::RotatedRect(cv::Point2f(0, 0), cv::Size2f(0, 0), 0);
smallroi = cv::RotatedRect(cv::Point2f(0, 0), cv::Size2f(0, 0), 0);
if (!H.empty())
{
H.release();
/* code */
}
}
};
enum SaveProcessType
{
Save_Close, // 不保存
Save_Filter, // 过滤的
Save_ALL, // 全部
};
struct DetConfig
{
int ncamId; // 相机ID
BaseCheckFunction *pBaseCheckFunction;
std::string strChannel; // 通道
int nthresholdvalue; // 背景阈值
int nAIErodesize; // 边缘腐蚀强度
bool bSaveResultImg; // 保存结果图片
SaveProcessType saveProcessImg; // 保存过程图片
bool bUseDrawRoi_Check; // 是否用绘制的ROI进行校验
cv::Rect drawRoi; // 绘制的 ROi;
cv::Mat drawMask; // 绘制的maksk
DetConfig()
{
Init();
}
void Init()
{
pBaseCheckFunction = NULL;
ncamId = 0;
nthresholdvalue = 1;
nAIErodesize = 7;
bSaveResultImg = false; bSaveResultImg = false;
saveProcessImg = Save_Close;
bUseDrawRoi_Check = false;
drawRoi = cv::Rect(0, 0, 0, 0);
if (!drawMask.empty())
{
drawMask.release();
/* code */
}
}
void Print()
{
printf("nthresholdvalue:%d;nAIErodesize %d;bSaveResultImg %s SaveProcessImg %d\n",
nthresholdvalue, nAIErodesize, BOOL_TO_STR(bSaveResultImg), saveProcessImg);
printf("bUseDrawRoi_Check %s roi %s \n",
BOOL_TO_STR(bUseDrawRoi_Check), CheckUtil::GetRectString(drawRoi).c_str());
}
bool IsSaveProcessImg()
{
if (saveProcessImg != Save_Close)
{
return true;
}
return false;
} }
}; };
@ -179,30 +76,18 @@ public:
Pin_QX_Det(std::shared_ptr<DetLog>& log_ref); Pin_QX_Det(std::shared_ptr<DetLog>& log_ref);
~Pin_QX_Det(); ~Pin_QX_Det();
int Detect(const cv::Mat &img, DetConfigResult *pDetConfig); int GetPinMask(const cv::Mat &img, DetConfigResult *pDetConfig, Mat &mask);
private: private:
int InitModel_Pin(); int InitModel_Pin();
int creatsavedir();
private: private:
bool m_bInitSucc; // 是否初始化成功 bool m_bInitSucc; // 是否初始化成功
// 检测结果
std::shared_ptr<Pin_AI_Result> m_pCheckResult_Pin;
std::shared_ptr<DetLog>& m_pdetlog; std::shared_ptr<DetLog>& m_pdetlog;
bool m_bInitialized;
bool m_bModelSucc;
bool m_bModel_Mark_Succ;
bool m_bshowimg; bool m_bshowimg;
cv::Mat showimg; cv::Mat showimg;
std::string m_strRootPath_Pin;
std::string m_strSavePath_Pin;
std::string m_strLastDate;
ImageStorage *m_pImageStorage;
std::shared_ptr<AIFactory> AI_Factory; std::shared_ptr<AIFactory> AI_Factory;

@ -3,7 +3,7 @@
* @Date: 2025-09-11 15:32:52 * @Date: 2025-09-11 15:32:52
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-22 16:56:41 * @LastEditTime: 2025-09-22 16:56:41
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/AI_Edge_Algin.cpp * @FilePath: /BOE_ZB_SOCKET_Detect/AlgorithmModule/src/AI_Edge_Algin.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */

@ -12,99 +12,6 @@
#include "AI_Factory.h" #include "AI_Factory.h"
#include <fstream> #include <fstream>
std::vector<ReadFlawCode> m_FlawCodeList;
std::vector<std::string> QX_Result_Names =
{
"OK",
"aotudian",
"other",
"line",
"zangwu",
"edge",
"ymhs",
"dianzhuang",
"posun",
"xianwei",
"shuizi",
"danban",
"fuchen",
};
std::vector<std::string> QX_Result_Code =
{
"P0000",
"MA507",
"MA508",
"MA506",
"MA504",
"MA503",
"MA502",
"MA505",
"MA501",
"P0001",
"P0002",
"P0003",
"P0004",
};
int ReadFlawCodeConfig(std::string json_path)
{
m_FlawCodeList.erase(m_FlawCodeList.begin(), m_FlawCodeList.end());
std::string strPath = json_path;
printf("ReadFlawCodeConfig path %s\n", strPath.c_str());
Json::CharReaderBuilder builder;
builder["collectComments"] = true;
Json::Value root;
std::string err;
std::ifstream ifs(strPath);
if (!ifs.is_open())
{
printf("error:file is open\n");
return 0;
}
if (!Json::parseFromStream(builder, ifs, &root, &err))
{
printf("error:parseFromStream\n");
return 0;
}
for (int i = 0; i < root.size(); i++)
{
// printf("Node idx %d /%d \n", i, root.size());
ReadFlawCode tem;
tem.flaw_name = root[i]["zh_name"].asString();
tem.flaw_code = root[i]["en_name"].asString();
string desc = root[i]["desc"].asString();
{
std::istringstream stream(desc);
std::string token;
// 使用 getline 按照分号分割
while (std::getline(stream, token, ';'))
{
tem.config_flaw_name.push_back(token);
}
}
m_FlawCodeList.push_back(tem);
}
for(int i = 0; i < m_FlawCodeList.size(); i++)
{
if(i >= QX_Result_Names.size()) {
QX_Result_Names.push_back(m_FlawCodeList.at(i).flaw_name);
QX_Result_Code.push_back(m_FlawCodeList.at(i).flaw_code);
}
else
{
QX_Result_Names.at(i) = m_FlawCodeList.at(i).flaw_name;
QX_Result_Code.at(i) = m_FlawCodeList.at(i).flaw_code;
}
}
return 0;
}
double calculateDistanceBetweenRectCenters(const cv::Rect &rect1, const cv::Rect &rect2, float fx, float fy) double calculateDistanceBetweenRectCenters(const cv::Rect &rect1, const cv::Rect &rect2, float fx, float fy)
{ {
// 计算矩形1的中心点 // 计算矩形1的中心点
@ -128,6 +35,9 @@ ALLImgCheckAnalysisy::ALLImgCheckAnalysisy()
{ {
m_strTest = ""; m_strTest = "";
m_pdetlog = std::make_shared<DetLog>();
m_bInitSucc = false;
m_bExit = false;
} }
ALLImgCheckAnalysisy::~ALLImgCheckAnalysisy() ALLImgCheckAnalysisy::~ALLImgCheckAnalysisy()
@ -180,6 +90,20 @@ int ALLImgCheckAnalysisy::RunStart(void *pconfig1)
m_nErrorCode = re; m_nErrorCode = re;
return m_nErrorCode; return m_nErrorCode;
} }
re = InitTemplateMask();
if (CHECK_OK != re)
{
m_nErrorCode = re;
return m_nErrorCode;
}
// 把模板信息下发到各个相机检测实例
for (auto &item : m_pCameraCheckAnalysisyList)
{
if (item.second)
{
item.second->SetTplInfo(m_tplOuterRect, m_tplPinContours);
}
}
m_nErrorCode = CHECK_OK; m_nErrorCode = CHECK_OK;
printf(">>>> ALLImgCheckAnalysisy Start Succ \n"); printf(">>>> ALLImgCheckAnalysisy Start Succ \n");
@ -238,6 +162,21 @@ int ALLImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType)
break; break;
case CHECK_CONFIG_Module: case CHECK_CONFIG_Module:
m_pConfigManager = (ConfigManagerBase *)pconfig; m_pConfigManager = (ConfigManagerBase *)pconfig;
// 参数更新时,若系统已初始化,则重新计算模板并下发给各相机
if (m_bInitSucc)
{
re = InitTemplateMask();
if (re == 0)
{
for (auto &item : m_pCameraCheckAnalysisyList)
{
if (item.second)
{
item.second->SetTplInfo(m_tplOuterRect, m_tplPinContours);
}
}
}
}
break; break;
default: default:
break; break;
@ -301,12 +240,146 @@ int ALLImgCheckAnalysisy::InitAIFactory()
GPU_Config gpu; GPU_Config gpu;
gpu.gpu_0 = true; gpu.gpu_0 = true;
gpu.gpu_1 = true; gpu.gpu_1 = false;
AI_Factory->InitALLAIModle(gpu); AI_Factory->InitALLAIModle(gpu);
return 0; return 0;
} }
int ALLImgCheckAnalysisy::InitTemplateMask()
{
std::shared_ptr<AIFactory> AI_Factory = AIFactory::GetInstance();
if (!AI_Factory || !AI_Factory->Align_Outer || !AI_Factory->Pin_Loc)
{
return -1;
}
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "---Init Tpl---" , "start");
// 模板图路径,暂时使用固定路径
string tplImgPath = "/home/aidlux/BOE/ZB_SOCKET/Tpl/tpl.bmp"; // 模板图片路径
Mat tplImg = imread(tplImgPath, IMREAD_UNCHANGED);
if (tplImg.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "", "Failed to load template image!");
return -2;
}
// 模板外接矩形,通过模型Align_Outer得到
RotatedRect tplOuterRect; // 模板外接矩形
std::shared_ptr<AIModel_Base> pSocket_Align;
pSocket_Align = AI_Factory->Align_Outer;
cv::Size sz;
sz.width = pSocket_Align->input_0.width;
sz.height = pSocket_Align->input_0.height;
cv::Mat detImg;
cout << "imgSize: " << tplImg.size() << ", " << "detImgSize: " << detImg.size() << ", " << "szSize: " << sz << endl;
cv::resize(tplImg, detImg, sz);
int re = 0;
cv::Mat mask;
if (detImg.channels() != 1)
{
cv::cvtColor(detImg, detImg, cv::COLOR_RGB2GRAY);
}
re = pSocket_Align->AIDet(detImg, mask);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "Init Tpl", "AICheck_Edge----error %d ", re);
int re123 = 100 + re;
return re123;
}
// 找到最大轮廓
bool found;
std::vector<cv::Point> boundingBox = CheckUtil::getLargestContourROI(mask, found);
if (!found)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "AI_Edge_Algin ", "No contours found!----error ");
return 4;
}
// 边缘轮廓点集还原为原图坐标并计算得到RotateROI
if (sz.width <= 0 || sz.height <= 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "AI_Edge_Algin ", "invalid model input size!----error ");
return 5;
}
// 检测小图 到 原图 的缩放比例
const float scale_x = static_cast<float>(tplImg.cols) / sz.width;
const float scale_y = static_cast<float>(tplImg.rows) / sz.height;
// 轮廓点还原到原图坐标系
std::vector<cv::Point2f> srcContour;
srcContour.reserve(boundingBox.size());
for (const auto &pt : boundingBox)
{
srcContour.emplace_back(pt.x * scale_x, pt.y * scale_y);
}
if (srcContour.size() < 3)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "AI_Edge_Algin ", "contour points too few!----error ");
return 6;
}
tplOuterRect = cv::minAreaRect(srcContour);
// 模板Pinmask通过模型Pin_Loc得到
Mat tplPinMask; // 模板mask
std::shared_ptr<AIModel_Base> pSocket_Pin;
pSocket_Pin = AI_Factory->Pin_Loc;
sz.width = pSocket_Pin->input_0.width;
sz.height = pSocket_Pin->input_0.height;
cv::Mat pinImg = tplImg(tplOuterRect.boundingRect()).clone(); // 裁剪模板图像为外接矩形区域
cout << "imgSize: " << tplImg.size() << ", " << "pinImgSize: " << pinImg.size() << ", " << "szSize: " << sz << endl;
cv::resize(pinImg, detImg, sz);
if (detImg.channels() != 1)
{
cv::cvtColor(detImg, detImg, cv::COLOR_RGB2GRAY);
}
re = pSocket_Pin->AIDet(detImg, tplPinMask);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "AI_Pin ", "AICheck_Pin----error %d ", re);
int re123 = 100 + re;
return re123;
}
// 统计tplPinMask的blob边缘点并绘制到tplImg上
vector<vector<Point>> pin_contours;
vector<Vec4i> hierarchy;
cv::findContours(tplPinMask, pin_contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// mask 尺寸 -> 裁剪图(pinImg) 尺寸 的缩放比例
const float pin_scale_x = (tplPinMask.cols > 0) ? static_cast<float>(pinImg.cols) / tplPinMask.cols : 0.0f;
const float pin_scale_y = (tplPinMask.rows > 0) ? static_cast<float>(pinImg.rows) / tplPinMask.rows : 0.0f;
// 将轮廓点从 mask 坐标系 映射回 tplImg 坐标系
m_tplPinContours.clear();
m_tplPinContours.reserve(pin_contours.size());
for (size_t i = 0; i < pin_contours.size(); i++)
{
std::vector<cv::Point> mapped;
mapped.reserve(pin_contours[i].size());
for (const auto &pt : pin_contours[i])
{
mapped.emplace_back(cvRound(pt.x * pin_scale_x),
cvRound(pt.y * pin_scale_y));
}
m_tplPinContours.push_back(mapped);
}
// 保存模板外接矩形
m_tplOuterRect = tplOuterRect;
// 绘制到 tplImg 上
{
Mat showImg = pinImg.clone();
cv::drawContours(pinImg, m_tplPinContours, -1, Scalar(0, 255, 0), 2);
cv::imwrite("/home/aidlux/BOE/ZB_SOCKET/Tpl/tpl_pin_contours.png", pinImg);
}
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "---Init Tpl---" , "end");
return 0;
}
int ALLImgCheckAnalysisy::LoadRunConfig(void *p) int ALLImgCheckAnalysisy::LoadRunConfig(void *p)
{ {
return 0; return 0;
@ -370,14 +443,6 @@ int ALLImgCheckAnalysisy::ExitSystem()
int ALLImgCheckAnalysisy::InitCameraCheckAnalysisy() int ALLImgCheckAnalysisy::InitCameraCheckAnalysisy()
{ {
string defect_list_file = m_pConfigManager->GetJsonPath();
if (defect_list_file == "") {
defect_list_file = "/var/aidlux/efs/model/defect_list.json";
}
else{
defect_list_file += "/defect_list.json";
}
ReadFlawCodeConfig(defect_list_file);
m_pCameraCheckAnalysisyList.clear(); m_pCameraCheckAnalysisyList.clear();
for (const auto &config : m_pConfigManager->Config_instances_) for (const auto &config : m_pConfigManager->Config_instances_)
{ {
@ -418,7 +483,8 @@ int ALLImgCheckAnalysisy::InitData()
int ALLImgCheckAnalysisy::Det_Product(std::shared_ptr<Product> &product) int ALLImgCheckAnalysisy::Det_Product(std::shared_ptr<Product> &product)
{ {
string cur_time_s = CheckUtil::getCurTimeHMS();
printf("[%s]>>>>>>>>>>>>>>>Det_Product****************det Start************\n", cur_time_s.c_str());
// 处理每个相机 // 处理每个相机
while (true) while (true)
{ {
@ -447,8 +513,8 @@ int ALLImgCheckAnalysisy::Det_Product(std::shared_ptr<Product> &product)
// AnalysiyAll(0); // AnalysiyAll(0);
SetProductResult(product); SetProductResult(product);
product->SetCheckEnd(); product->SetCheckEnd();
string cur_time = CheckUtil::getCurTimeHMS(); string cur_time_e = CheckUtil::getCurTimeHMS();
printf("[%s]>>>>>>>>>>>>>>>Det_Product****************det End************\n", cur_time.c_str()); printf("[%s]>>>>>>>>>>>>>>>Det_Product****************det End************\n", cur_time_e.c_str());
return 0; return 0;
} }

@ -7,6 +7,7 @@
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp
*/ */
#include "CameraCheckAnalysisy.hpp" #include "CameraCheckAnalysisy.hpp"
#include "ImgCheckAnalysisy.hpp"
#include "CheckUtil.hpp" #include "CheckUtil.hpp"
#include "Define.h" #include "Define.h"
@ -601,6 +602,19 @@ int CameraCheckAnalysisy::Init(std::string strcameraName)
return 0; return 0;
} }
void CameraCheckAnalysisy::SetTplInfo(const cv::RotatedRect &outerRect,
const std::vector<std::vector<cv::Point>> &pinContours)
{
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
{
auto *p = static_cast<ImgCheckAnalysisy *>(m_pImgCheckAnalysisy[i]);
if (p)
{
p->SetTplInfo(outerRect, pinContours);
}
}
}
int CameraCheckAnalysisy::StartCheck(std::shared_ptr<CameraResult> pCamera_Check_Result) int CameraCheckAnalysisy::StartCheck(std::shared_ptr<CameraResult> pCamera_Check_Result)
{ {
if (m_bHaveImgeDet) if (m_bHaveImgeDet)

@ -3,7 +3,7 @@
* @Date: 2025-09-13 20:39:37 * @Date: 2025-09-13 20:39:37
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-17 16:39:47 * @LastEditTime: 2025-09-17 16:39:47
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/CameraResult.cpp * @FilePath: /BOE_ZB_SOCKET_Detect/AlgorithmModule/src/CameraResult.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
#include "CameraResult.h" #include "CameraResult.h"

@ -419,6 +419,26 @@ float CheckUtil::getLongAxisAngle(cv::RotatedRect rect) {
return long_axis_angle; return long_axis_angle;
} }
std::vector<cv::Point2f> CheckUtil::sort_vertices(cv::RotatedRect rrect) {
cv::Point2f pts[4];
rrect.points(pts);
std::vector<cv::Point2f> vertices(pts, pts + 4);
// 按 y 坐标升序排序
std::sort(vertices.begin(), vertices.end(),
[](const cv::Point2f& a, const cv::Point2f& b) {
return a.y < b.y;
});
if (vertices[0].x > vertices[1].x)
std::swap(vertices[0], vertices[1]);
if (vertices[2].x > vertices[3].x)
std::swap(vertices[2], vertices[3]);
return vertices;
}
std::vector<cv::Point> CheckUtil::getLargestContourROI(const cv::Mat &binaryImg, bool &found) std::vector<cv::Point> CheckUtil::getLargestContourROI(const cv::Mat &binaryImg, bool &found)
{ {
std::vector<std::vector<cv::Point>> contours; std::vector<std::vector<cv::Point>> contours;
@ -481,6 +501,32 @@ int CheckUtil::CreateDir(const std::string &dir)
return ret; return ret;
} }
int CheckUtil::SaveImgAsync(const std::string &path, const cv::Mat &img)
{
if (path.empty() || img.empty())
{
return -1;
}
// 拷贝图像,避免异步线程执行时原图像被释放或修改
cv::Mat imgCopy = img.clone();
// 创建保存路径的父目录
std::string::size_type pos = path.find_last_of('/');
if (pos != std::string::npos)
{
std::string parentDir = path.substr(0, pos);
CheckUtil::CreateDir(parentDir);
}
// 启动后台线程异步存图
std::thread([path, imgCopy]() {
cv::imwrite(path, imgCopy);
}).detach();
return 0;
}
bool CheckUtil::bcalDis(cv::Point p1, cv::Point p2, int disT) bool CheckUtil::bcalDis(cv::Point p1, cv::Point p2, int disT)
{ {
double dis = std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); double dis = std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));

@ -3,7 +3,7 @@
* @Date: 2025-09-13 20:39:37 * @Date: 2025-09-13 20:39:37
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-23 14:29:12 * @LastEditTime: 2025-09-23 14:29:12
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/CameraResult.cpp * @FilePath: /BOE_ZB_SOCKET_Detect/AlgorithmModule/src/CameraResult.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
#include "ImageAllResult.h" #include "ImageAllResult.h"

@ -1044,41 +1044,29 @@ int ImageResultJudge::ConfigTypeToResultType(int nconfigType)
{ {
switch (nconfigType) switch (nconfigType)
{ {
case CONFIG_QX_NAME_cell_aotudian: case CONFIG_QX_NAME_PIN_PoSun:
resultError_type = ERROR_TYPE_aotudian; resultError_type = ERROR_TYPE_PIN_PoSun;
break; break;
case CONFIG_QX_NAME_cell_other: case CONFIG_QX_NAME_PIN_QueShi:
resultError_type = ERROR_TYPE_other; resultError_type = ERROR_TYPE_PIN_QueShi;
break;
case CONFIG_QX_NAME_cell_line:
resultError_type = ERROR_TYPE_line;
break;
case CONFIG_QX_NAME_cell_zangwu:
resultError_type = ERROR_TYPE_zangwu;
break; break;
case CONFIG_QX_NAME_cell_edge: case CONFIG_QX_NAME_BTB_DuanLie:
resultError_type = ERROR_TYPE_edge; resultError_type = ERROR_TYPE_BTB_DuanLie;
break; break;
case CONFIG_QX_NAME_cell_ymhs: case CONFIG_QX_NAME_LianXi:
resultError_type = ERROR_TYPE_ymhs; resultError_type = ERROR_TYPE_LianXi;
break; break;
case CONFIG_QX_NAME_cell_dianzhuang: case CONFIG_QX_NAME_QueXi:
resultError_type = ERROR_TYPE_dianzhuang; resultError_type = ERROR_TYPE_QueXi;
break; break;
case CONFIG_QX_NAME_cell_posun: case CONFIG_QX_NAME_YiWu:
resultError_type = ERROR_TYPE_posun; resultError_type = ERROR_TYPE_YiWu;
break; break;
case CONFIG_QX_NAME_cell_xianwei: case CONFIG_QX_NAME_C_BianXing:
resultError_type = ERROR_TYPE_xianwei; resultError_type = ERROR_TYPE_C_BianXing;
break; break;
case CONFIG_QX_NAME_cell_shuizi: case CONFIG_QX_NAME_other:
resultError_type = ERROR_TYPE_shuizi; resultError_type = ERROR_TYPE_other;
break;
case CONFIG_QX_NAME_cell_danban:
resultError_type = ERROR_TYPE_danban;
break;
case CONFIG_QX_NAME_cell_fuchen:
resultError_type = ERROR_TYPE_fuchen;
break; break;
default: default:

@ -3,7 +3,7 @@
* @Date: 2025-09-11 15:32:52 * @Date: 2025-09-11 15:32:52
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-16 09:40:36 * @LastEditTime: 2025-09-16 09:40:36
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/ImageStorage.cpp * @FilePath: /BOE_ZB_SOCKET_Detect/AlgorithmModule/src/ImageStorage.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
#include "ImageStorage.h" #include "ImageStorage.h"

@ -210,6 +210,13 @@ int ImgCheckAnalysisy::creatsavedir()
return 0; return 0;
} }
void ImgCheckAnalysisy::SetTplInfo(const cv::RotatedRect &outerRect,
const std::vector<std::vector<cv::Point>> &pinContours)
{
m_tplOuterRect = outerRect;
m_tplPinContours = pinContours;
}
int ImgCheckAnalysisy::LoadRunConfig(void *p) int ImgCheckAnalysisy::LoadRunConfig(void *p)
{ {
if (p == NULL) if (p == NULL)
@ -363,241 +370,45 @@ cv::Scalar ImgCheckAnalysisy::calc_blob_info_withstats(cv::Mat &img, const cv::M
return cv::Scalar(worb, energy, hj); return cv::Scalar(worb, energy, hj);
} }
Point2f GetCoorPoint(Point2f point, Mat img_mat) int ImgCheckAnalysisy::Adapt_Config(RotatedRect tplOuterRect, RotatedRect curOuterRect, Mat& det_img){
{ vector<cv::Point2f> cur_vertices = CheckUtil::sort_vertices(curOuterRect);
// 越界判定 vector<cv::Point2f> tpl_vertices = CheckUtil::sort_vertices(tplOuterRect);
int coor_img_rect_x = point.x-400;
int coor_img_rect_y = point.y-400;
int coor_img_rect_w = 800;
int coor_img_rect_h = 800;
if (coor_img_rect_x < 0)
{
coor_img_rect_x = 0;
coor_img_rect_w = min(400, img_mat.cols);
}
if (coor_img_rect_y < 0)
{
coor_img_rect_y = 0;
coor_img_rect_h = min(400, img_mat.rows);
}
if (coor_img_rect_x + coor_img_rect_w > img_mat.cols)
{
coor_img_rect_w = img_mat.cols - coor_img_rect_x;
}
if (coor_img_rect_y + coor_img_rect_h > img_mat.rows)
{
coor_img_rect_h = img_mat.rows - coor_img_rect_y;
}
if (coor_img_rect_x < 0 || coor_img_rect_y < 0 || coor_img_rect_x + coor_img_rect_w > img_mat.cols || coor_img_rect_y + coor_img_rect_h > img_mat.rows)
{
return point;
}
Mat coor_img_mat = img_mat(Rect(coor_img_rect_x, coor_img_rect_y, coor_img_rect_w, coor_img_rect_h));
Mat coor_img_bin;
threshold(coor_img_mat, coor_img_bin, 50, 255, THRESH_BINARY);
// 6. 查找轮廓
std::vector<std::vector<cv::Point>> contours;
cv::findContours(coor_img_bin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
if (contours.empty())
{
return point;
}
double maxArea = 0;
int maxAreaIdx = -1;
for (size_t i = 0; i < contours.size(); ++i)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxAreaIdx = i;
}
}
if (maxAreaIdx < 0 || maxArea < 100)
{
return point;
}
cv::RotatedRect rect = cv::minAreaRect(contours[maxAreaIdx]);
Point2f vertices[4];
rect.points(vertices);
int cornerIdx = 0;
float minDist = FLT_MAX;
for (int i = 0; i < 4; i++)
{
float dist = std::pow(vertices[i].x - 400, 2) + std::pow(vertices[i].y - 400, 2);
if (dist < minDist)
{
minDist = dist;
cornerIdx = i;
}
}
Point2f new_point;
new_point.x = vertices[cornerIdx].x + coor_img_rect_x;
new_point.y = vertices[cornerIdx].y + coor_img_rect_y;
new_point.x = std::max(0.0f, std::min(new_point.x, static_cast<float>(img_mat.cols - 1))); cv::Point2f src_pts[3] = {
new_point.y = std::max(0.0f, std::min(new_point.y, static_cast<float>(img_mat.rows - 1))); cur_vertices[0], // 对应左上
cur_vertices[1], // 对应右上
cur_vertices[2] // 对应左下
};
cv::Point2f dst_pts[3] = {
tpl_vertices[0], // 左上
tpl_vertices[1], // 右上
tpl_vertices[2] // 左下
};
cv::Mat affine_mat = cv::getAffineTransform(src_pts, dst_pts);
return new_point; // 仿射变换
} cv::warpAffine(det_img, det_img, affine_mat, det_img.size());
int GetEdgeRoi(Mat img, Rect &new_roi, float scale_x, float scale_y){ // 将m_outer_rroi和m_inner_rroi变换到模板图像坐标系下
if (img.empty()) auto transformRotatedRect = [&affine_mat](cv::RotatedRect &rrect)
{ {
return 1; const double *M = affine_mat.ptr<double>(0);
}
// 缩小,减少耗时
Mat r_img;
int resize_width = static_cast<int>(img.cols / scale_x); cv::Point2f pts[4];
int resize_height = static_cast<int>(img.rows / scale_y); rrect.points(pts);
resize(img, r_img, Size(resize_width, resize_height), 0, 0, INTER_LINEAR);
// 二值化找最大连通域 std::vector<cv::Point2f> transformed_pts(4);
Mat r_img_bin; for (int i = 0; i < 4; i++)
threshold(r_img, r_img_bin, 15, 255, THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours;
cv::findContours(r_img_bin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
if (contours.empty())
{
return 2;
}
double maxArea = 0;
int maxAreaIdx = -1;
for (size_t i = 0; i < contours.size(); ++i)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxAreaIdx = i;
}
}
if (maxAreaIdx < 0)
{ {
return 3; float x = static_cast<float>(M[0] * pts[i].x + M[1] * pts[i].y + M[2]);
float y = static_cast<float>(M[3] * pts[i].x + M[4] * pts[i].y + M[5]);
transformed_pts[i] = cv::Point2f(x, y);
} }
rrect = cv::minAreaRect(transformed_pts);
};
cv::Rect small_roi = cv::boundingRect(contours[maxAreaIdx]); transformRotatedRect(m_outer_rroi);
Rect roi; transformRotatedRect(m_inner_rroi);
roi.x = static_cast<int>(small_roi.x * scale_x);
roi.y = static_cast<int>(small_roi.y * scale_y);
roi.width = static_cast<int>(small_roi.width * scale_x);
roi.height = static_cast<int>(small_roi.height * scale_y);
roi.x = std::max(0, roi.x);
roi.y = std::max(0, roi.y);
roi.width = std::min(roi.width, img.cols - roi.x);
roi.height = std::min(roi.height, img.rows - roi.y);
new_roi = roi;
return 0;
}
int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update){
if (img.empty()) {
std::cerr << "Error: Input image 'img' is empty!" << std::endl;
return -1;
}
if(!b_update){
return 1;
}
int get_edge_roi = GetEdgeRoi(img, cur_roi, 20, 20);
if(get_edge_roi != 0){
return 2;
}
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "-------------------start--------------");
/*计算xy偏移缩放比例*/
// 拷贝原始数据
if(m_old_productROI.width == 0 || m_old_productROI.height == 0){
m_old_productROI = m_AnalysisyConfig.baseFunction.markLine.productROI;
m_old_cur_edgeDet_region = m_AnalysisyConfig.baseFunction.edgeDet.region;
m_old_cur_markLine_region = m_AnalysisyConfig.baseFunction.markLine.region;
m_old_cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1;
m_old_cur_markLine_mark2 = m_AnalysisyConfig.baseFunction.markLine.mark_local_2;
m_old_cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr;
}
Rect old_roi = m_old_productROI;
Point old_center(old_roi.x + old_roi.width / 2, old_roi.y + old_roi.height / 2);
Point new_center(cur_roi.x + cur_roi.width / 2, cur_roi.y + cur_roi.height / 2);
int x_offset = new_center.x - old_center.x;
int y_offset = new_center.y - old_center.y;
float scale_x = (float)cur_roi.width / (float)old_roi.width;
float scale_y = (float)cur_roi.height / (float)old_roi.height;
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "old_roi = %d %d %d %d", old_roi.x, old_roi.y, old_roi.width, old_roi.height);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "cur_roi = %d %d %d %d", cur_roi.x, cur_roi.y, cur_roi.width, cur_roi.height);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "x_offset = %d y_offset = %d", x_offset, y_offset);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "scale_x = %f scale_y = %f", scale_x, scale_y);
if(abs(x_offset) < 50 && abs(y_offset) < 50 && abs(scale_x - 1) < 0.0001 && abs(scale_y - 1) < 0.0001 ){
return 3;
}
/*获取待修改的region引用*/
std::vector<cv::Point>& cur_edgeDet_region = m_AnalysisyConfig.baseFunction.edgeDet.region;
std::vector<cv::Point>& cur_markLine_region = m_AnalysisyConfig.baseFunction.markLine.region;
cv::Point& cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1;
cv::Point& cur_markLine_mark2 = m_AnalysisyConfig.baseFunction.markLine.mark_local_2;
std::vector<RegionConfigST>& cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr;
/*进行修改*/
// rect
m_AnalysisyConfig.baseFunction.markLine.productROI = cur_roi;
// point
cur_markLine_mark1.x = m_old_cur_markLine_mark1.x + x_offset;
cur_markLine_mark1.y = m_old_cur_markLine_mark1.y + y_offset;
cur_markLine_mark1 = Point((cur_markLine_mark1.x - new_center.x) * scale_x + new_center.x, (cur_markLine_mark1.y - new_center.y) * scale_y + new_center.y);
cur_markLine_mark2.x = m_old_cur_markLine_mark2.x + x_offset;
cur_markLine_mark2.y = m_old_cur_markLine_mark2.y + y_offset;
cur_markLine_mark2 = Point((cur_markLine_mark2.x - new_center.x) * scale_x + new_center.x, (cur_markLine_mark2.y - new_center.y) * scale_y + new_center.y);
// region
for(int i = 0; i < cur_edgeDet_region.size(); i++){
cur_edgeDet_region[i].x = m_old_cur_edgeDet_region[i].x + x_offset;
cur_edgeDet_region[i].y = m_old_cur_edgeDet_region[i].y + y_offset;
cur_edgeDet_region[i] = Point((cur_edgeDet_region[i].x - new_center.x) * scale_x + new_center.x, (cur_edgeDet_region[i].y - new_center.y) * scale_y + new_center.y);
}
for(int i = 0; i < cur_markLine_region.size(); i++){
cur_markLine_region[i].x = m_old_cur_markLine_region[i].x + x_offset;
cur_markLine_region[i].y = m_old_cur_markLine_region[i].y + y_offset;
cur_markLine_region[i] = Point((cur_markLine_region[i].x - new_center.x) * scale_x + new_center.x, (cur_markLine_region[i].y - new_center.y) * scale_y + new_center.y);
}
for(int i = 0 ; i < cur_regionConfigArr.size(); i++){
for(int j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size(); j++){
cur_regionConfigArr[i].basicInfo.pointArry[j].x = m_old_cur_regionConfigArr[i].basicInfo.pointArry[j].x + x_offset;
cur_regionConfigArr[i].basicInfo.pointArry[j].y = m_old_cur_regionConfigArr[i].basicInfo.pointArry[j].y + y_offset;
cur_regionConfigArr[i].basicInfo.pointArry[j] = Point((cur_regionConfigArr[i].basicInfo.pointArry[j].x - new_center.x) * scale_x + new_center.x, (cur_regionConfigArr[i].basicInfo.pointArry[j].y - new_center.y) * scale_y + new_center.y);
}
}
/*show*/
// Mat show_img = img.clone();
// cv::rectangle(show_img, m_AnalysisyConfig.baseFunction.markLine.productROI, Scalar(255), 5);
// if(cur_edgeDet_region.size() >=2){
// for(int i = 0 ; i < cur_edgeDet_region.size() - 1; i++){
// cv::line(show_img, cur_edgeDet_region[i], cur_edgeDet_region[i+1], Scalar(255), 20);
// }
// }
// if(cur_markLine_region.size() >=2){
// for(int i = 0 ; i < cur_markLine_region.size() - 1; i++){
// cv::line(show_img, cur_markLine_region[i], cur_markLine_region[i+1], Scalar(255), 20);
// }
// }
// if(cur_regionConfigArr.size() >=2){
// for(int i = 0 ; i < cur_regionConfigArr.size(); i++){
// for(int j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size()-1; j++){
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry[j], cur_regionConfigArr[i].basicInfo.pointArry[j+1], Scalar(255), 20);
// }
// }
// }
// imwrite(m_AnalysisyConfig.commonCheckConfig.baseConfig.strCamearName +"_show_img.tiff", show_img);
return 0; return 0;
} }
@ -646,11 +457,8 @@ int ImgCheckAnalysisy::CheckRun()
long time_edge_s = CheckUtil::getcurTime(); long time_edge_s = CheckUtil::getcurTime();
/*AI 边缘定位(内外边缘)*/ /*AI 边缘定位(内外边缘)*/
cv::RotatedRect outer_roi;
cv::RotatedRect inner_roi;
// 模型定位内外边缘 // 模型定位内外边缘
int reedge = AI_Edge(m_CheckResult_shareP->in_shareImage->img, outer_roi, inner_roi); int reedge = AI_Edge(m_CheckResult_shareP->in_shareImage->img, m_outer_rroi, m_inner_rroi);
m_outer_roi = outer_roi.boundingRect();
if (reedge != 0) if (reedge != 0)
{ {
m_pdetlog->AddCheckstr(PrintLevel_0, "Error", "AI_Edge is error type = %d", reedge); m_pdetlog->AddCheckstr(PrintLevel_0, "Error", "AI_Edge is error type = %d", reedge);
@ -662,20 +470,96 @@ int ImgCheckAnalysisy::CheckRun()
m_pdetlog->AddCheckstr(PrintLevel_0, "2、pre detect", "-------------------------AI_Edge------------succ---time %ld----\n", time_edge_e - time_edge_s); m_pdetlog->AddCheckstr(PrintLevel_0, "2、pre detect", "-------------------------AI_Edge------------succ---time %ld----\n", time_edge_e - time_edge_s);
// 计算内外边缘夹角 // 计算内外边缘夹角
float aouter = CheckUtil::getLongAxisAngle(outer_roi); float aouter = CheckUtil::getLongAxisAngle(m_outer_rroi);
float ainner = CheckUtil::getLongAxisAngle(inner_roi); float ainner = CheckUtil::getLongAxisAngle(m_inner_rroi);
float diff_align = std::fabs(aouter - ainner); float diff_align = std::fabs(aouter - ainner);
diff_align = std::fmod(diff_align, 180.0f); // 模 180 度 diff_align = std::fmod(diff_align, 180.0f); // 模 180 度
/*投影对齐模板*/ // 两条直线的夹角取锐角min(diff, 180 - diff)
Adapt_Config(m_CheckResult_shareP->in_shareImage->img, m_outer_roi, m_pbaseCheckFunction->markLine.badapt_region); if (diff_align > 90.0f)
{
diff_align = 180.0f - diff_align;
}
// 1. 使用 ALign_Config.angle_diff 卡控内外边缘夹角(未配置时默认 10 度)
float angleTh = 10.0f;
if (m_pbaseCheckFunction != NULL && m_pbaseCheckFunction->ALign_Config.angle_diff > 0.0f)
{
angleTh = m_pbaseCheckFunction->ALign_Config.angle_diff;
}
// 2. 使用 ALign_Config.x_offset / y_offset (mm) 卡控内外边缘中心偏移mm 转像素)
float offX_px = 0.0f;
float offY_px = 0.0f;
if (m_pbaseCheckFunction != NULL)
{
if (m_fImgage_Scale_X > 0.0f)
{
offX_px = m_pbaseCheckFunction->ALign_Config.x_offset / m_fImgage_Scale_X;
}
if (m_fImgage_Scale_Y > 0.0f)
{
offY_px = m_pbaseCheckFunction->ALign_Config.y_offset / m_fImgage_Scale_Y;
}
}
// 3. 内外边缘中心坐标偏移(像素)
float dx_px = std::fabs(m_outer_rroi.center.x - m_inner_rroi.center.x);
float dy_px = std::fabs(m_outer_rroi.center.y - m_inner_rroi.center.y);
bool bAngleErr = diff_align > angleTh;
bool bOffsetXErr = (offX_px > 0.0f) && (dx_px > offX_px);
bool bOffsetYErr = (offY_px > 0.0f) && (dy_px > offY_px);
bool bOffsetErr = bOffsetXErr || bOffsetYErr;
// 角度超差或中心偏移超差 -> 添加到缺陷列表
if (bAngleErr || bOffsetErr)
{
QX_ERROR_INFO_ alignErr;
alignErr.Idx = static_cast<int>(m_pDetResult->pQx_ErrorList->size());
// roi 用整张检测图区域detImg 坐标系)
cv::Rect tplRect = m_tplOuterRect.boundingRect();
alignErr.roi = cv::Rect(0, 0, tplRect.width, tplRect.height);
alignErr.area = alignErr.roi.width * alignErr.roi.height;
alignErr.JudgArea = alignErr.area * m_fImgage_Scale_X * m_fImgage_Scale_Y;
alignErr.flen = tplRect.width * m_fImgage_Scale_X;
alignErr.fbreadth = tplRect.height * m_fImgage_Scale_Y;
alignErr.nconfig_qx_type = CONFIG_QX_NAME_other;
alignErr.qx_name = CONFIG_QX_NAME_Names[CONFIG_QX_NAME_other];
alignErr.grayDis = diff_align; // 记录内外边缘夹角(度)
alignErr.detRegionidxList.push_back(0);
alignErr.detlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Align Check",
"outer-inner angle diff %.2f deg", diff_align);
m_pDetResult->pQx_ErrorList->push_back(alignErr);
if (bAngleErr)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Align Check", "angle diff %.2f deg > %.2f", diff_align, angleTh);
}
if (bOffsetXErr)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Align Check", "center offset dx %.1f px > %.1f px",
dx_px, offX_px);
}
if (bOffsetYErr)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Align Check", "center offset dy %.1f px > %.1f px",
dy_px, offY_px);
}
}
/*投影对齐模板*/
Adapt_Config(m_tplOuterRect, m_outer_rroi, m_CheckResult_shareP->in_shareImage->img);
m_outer_roi = m_tplOuterRect.boundingRect();
m_Crop_Roi_paramImg = m_outer_roi; m_Crop_Roi_paramImg = m_outer_roi;
m_pImageAllResult->pDetResult->CutRoi = m_outer_roi; m_pImageAllResult->pDetResult->CutRoi = m_outer_roi;
m_pImageAllResult->pDetResult->Param_CropRoi = m_Crop_Roi_paramImg; m_pImageAllResult->pDetResult->Param_CropRoi = m_Crop_Roi_paramImg;
long time_calan_e = CheckUtil::getcurTime(); long time_calan_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "2.1、pre detect", "-------------------------CalAn------------succ---time %ld----\n", time_calan_e - time_edge_s); m_pdetlog->AddCheckstr(PrintLevel_0, "2.1、pre detect", "-------------------------CalAndAffine------------succ---time %ld----\n", time_calan_e - time_edge_s);
/*生成 检测的图片*/ /*生成 检测的图片*/
cv::Mat image; cv::Mat image;
@ -696,7 +580,7 @@ int ImgCheckAnalysisy::CheckRun()
ImgPreDet(); ImgPreDet();
/*更新检测区域*/ /*更新检测区域*/
Update_DetRoiList(); // Update_DetRoiList();
m_pdetlog->AddCheckstr(PrintLevel_0, "3、pre detect", "-------------------------pre Det--------------- \n"); m_pdetlog->AddCheckstr(PrintLevel_0, "3、pre detect", "-------------------------pre Det--------------- \n");
@ -1457,12 +1341,10 @@ int ImgCheckAnalysisy::ConfigCheck(cv::Mat img)
int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg) int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
{ {
std::shared_ptr<AIModel_Base> pAIDet; // 依次使用多个检测模型,各模型输出 mask 取并集作为最终 outmask
// printf("=====>>>>AI_Detect_Thread m_strCurDetChannel %s \n", m_strCurDetChannel.c_str()); std::vector<std::shared_ptr<AIModel_Base>> pAIDetList;
{ pAIDetList.push_back(AI_Factory->Defect);
// printf("=====>>>>AI_Detect_Thread USE CA %s \n", m_strCurDetChannel.c_str()); pAIDetList.push_back(AI_Factory->Defect_QueXi);
pAIDet = AI_Factory->Defect;
}
std::string strBaseLog = "AI_Detect"; std::string strBaseLog = "AI_Detect";
@ -1478,8 +1360,8 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
cutRoi.width = img.cols - 0; cutRoi.width = img.cols - 0;
cutRoi.height = img.rows - 0; cutRoi.height = img.rows - 0;
int deal_image_width = pAIDet->input_0.width; int deal_image_width = pAIDetList[0]->input_0.width;
int deal_image_height = pAIDet->input_0.height; int deal_image_height = pAIDetList[0]->input_0.height;
int re = CheckUtil::cutSmallImg(img, SmallRoiList, cutRoi, deal_image_width, deal_image_height, 0, 0); int re = CheckUtil::cutSmallImg(img, SmallRoiList, cutRoi, deal_image_width, deal_image_height, 0, 0);
@ -1515,19 +1397,24 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
ResultImg = cv::Mat::zeros(img.size(), CV_8UC1); ResultImg = cv::Mat::zeros(img.size(), CV_8UC1);
const int totalTasks = SmallRoiList.size(); const int totalTasks = SmallRoiList.size();
int submitted = 0;
int completed = 0;
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_"; // std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
t2 = CheckUtil::getcurTime(); t2 = CheckUtil::getcurTime();
// 依次用多个模型做检测,所有模型输出的 mask 取并集作为最终 outmask
for (size_t m = 0; m < pAIDetList.size(); m++)
{
std::shared_ptr<AIModel_Base> pAIDet = pAIDetList[m];
int submitted = 0;
int completed = 0;
while (completed < totalTasks) while (completed < totalTasks)
{ {
// 如果任务还没提交完,且当前处理任务数 < 2提交新任务 // 如果任务还没提交完,且当前处理任务数 < 10,提交新任务
if (submitted < totalTasks && runner->GetProcessingCount() < 10) if (submitted < totalTasks && runner->GetProcessingCount() < 10)
{ {
std::shared_ptr<AIMulThreadRunBase::AITask> task = std::make_shared<AIMulThreadRunBase::AITask>(); std::shared_ptr<AIMulThreadRunBase::AITask> task = std::make_shared<AIMulThreadRunBase::AITask>();
task->id = completed; task->id = submitted;
task->roi = SmallRoiList.at(submitted); task->roi = SmallRoiList.at(submitted);
task->input = img(SmallRoiList.at(submitted)).clone(); task->input = img(SmallRoiList.at(submitted)).clone();
task->output = std::make_shared<cv::Mat>(); task->output = std::make_shared<cv::Mat>();
@ -1550,13 +1437,28 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
cv::Mat &outimg = *(result->output); cv::Mat &outimg = *(result->output);
if (!outimg.empty()) if (!outimg.empty())
{ {
outimg.copyTo(ResultImg(result->roi), outimg); // 多个模型的结果取并集
cv::Mat roiMat = ResultImg(result->roi);
cv::bitwise_or(roiMat, outimg, roiMat);
}
// 同一 roi 的多个模型结果取并集后存入 AI_Qx_MaskList
bool bFind = false;
for (auto &item : m_pImageAllResult->AI_Qx_MaskList)
{
if (item->roi == result->roi)
{
cv::bitwise_or(item->AI_mask, outimg, item->AI_mask);
bFind = true;
break;
} }
}
if (!bFind)
{ {
std::shared_ptr<ImageAllResult::AI_Det_MaskImg> temAIresult = std::make_shared<ImageAllResult::AI_Det_MaskImg>(); std::shared_ptr<ImageAllResult::AI_Det_MaskImg> temAIresult = std::make_shared<ImageAllResult::AI_Det_MaskImg>();
temAIresult->roi = result->roi; temAIresult->roi = result->roi;
temAIresult->AI_inImg = result->input; temAIresult->AI_inImg = result->input;
temAIresult->AI_mask = outimg; temAIresult->AI_mask = outimg.clone();
m_pImageAllResult->AI_Qx_MaskList.push_back(temAIresult); m_pImageAllResult->AI_Qx_MaskList.push_back(temAIresult);
} }
completed++; completed++;
@ -1566,9 +1468,10 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
} }
}
t3 = CheckUtil::getcurTime(); t3 = CheckUtil::getcurTime();
float mean_AI = (t3 - t2) / SmallRoiList.size(); float mean_AI = (t3 - t2) / (SmallRoiList.size() * pAIDetList.size());
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run Time: sum %ld pre %ld Run %ld mean One Small Img %f", t3 - t1, t2 - t1, t3 - t2, mean_AI); m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run Time: sum %ld pre %ld Run %ld mean One Small Img %f", t3 - t1, t2 - t1, t3 - t2, mean_AI);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End"); m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
@ -1613,7 +1516,7 @@ 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)
{ {
pblob->AIclasstype = CONFIG_QX_NAME_cell_ymhs; pblob->AIclasstype = CONFIG_QX_NAME_YiWu;
submitted++; submitted++;
completed++; completed++;
continue; continue;
@ -1660,47 +1563,39 @@ int ImgCheckAnalysisy::AI_QX_Class_Thread()
switch (temClass) switch (temClass)
{ {
case 0: case 0:
cls_num = AI_CLass_QX_NAME_aotudian; cls_num = AI_CLass_QX_NAME_PIN_PoSun;
break; break;
case 1: case 1:
cls_num = AI_CLass_QX_NAME_other; cls_num = AI_CLass_QX_NAME_PIN_QueShi;
break; break;
case 2: case 2:
cls_num = AI_CLass_QX_NAME_line; cls_num = AI_CLass_QX_NAME_BTB_DuanLie;
break; break;
case 3: case 3:
cls_num = AI_CLass_QX_NAME_zangwu; cls_num = AI_CLass_QX_NAME_LianXi;
break; break;
case 4: case 4:
cls_num = AI_CLass_QX_NAME_dianzhuang; cls_num = AI_CLass_QX_NAME_QueXi;
break; break;
case 5: case 5:
cls_num = AI_CLass_QX_NAME_posun; cls_num = AI_CLass_QX_NAME_YiWu;
break; break;
case 6: case 6:
cls_num = AI_CLass_QX_NAME_xianwei; cls_num = AI_CLass_QX_NAME_C_BianXing;
break; break;
case 7: case 7:
cls_num = AI_CLass_QX_NAME_shuizi; cls_num = AI_CLass_QX_NAME_other;
break;
case 8:
cls_num = AI_CLass_QX_NAME_danban;
break;
case 9:
cls_num = AI_CLass_QX_NAME_fuchen;
break; break;
default: default:
cls_num = AI_CLass_QX_NAME_zangwu; cls_num = AI_CLass_QX_NAME_other;
break; break;
} }
@ -1890,77 +1785,40 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
float fs_resize_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols; float fs_resize_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols;
float fs_resize_y = m_pImageAllResult->resultImg.rows * 1.0f / m_pImageAllResult->detImg.rows; float fs_resize_y = m_pImageAllResult->resultImg.rows * 1.0f / m_pImageAllResult->detImg.rows;
// 要绘制结果 // 绘制模板 pin 轮廓(绿色)与当前 pin 轮廓(红色)
if (m_pbaseCheckFunction && m_pbaseCheckFunction->edgeDet.bDrawResult) for (const auto &contour : m_tplPinContours)
{
for (const auto &r : m_Edge_DetConfig.pin_det_roi)
{ {
cv::Rect droi; std::vector<cv::Point> draw_pts;
droi.x = r.roi.x * fs_resize_x; draw_pts.reserve(contour.size());
droi.y = r.roi.y * fs_resize_y; for (const auto &pt : contour)
droi.width = r.roi.width * fs_resize_x;
droi.height = r.roi.height * fs_resize_y;
cv::rectangle(m_CheckResult_shareP->resultimg, droi, cv::Scalar(255, 0, 255), 1); // 黄色角点
}
if (m_Edge_DetConfig.Det_region.size() > 2)
{
for (int i = 0; i < m_Edge_DetConfig.Det_region.size() - 1; i++)
{
cv::Point p1;
p1.x = m_Edge_DetConfig.Det_region[i].x * fs_resize_x;
p1.y = m_Edge_DetConfig.Det_region[i].y * fs_resize_y;
cv::Point p2;
p2.x = m_Edge_DetConfig.Det_region[i + 1].x * fs_resize_x;
p2.y = m_Edge_DetConfig.Det_region[i + 1].y * fs_resize_y;
cv::line(m_CheckResult_shareP->resultimg, p1, p2, cv::Scalar(0, 255, 255));
}
{ {
cv::Point p1; draw_pts.emplace_back(cvRound(pt.x * fs_resize_x), cvRound(pt.y * fs_resize_y));
p1.x = m_Edge_DetConfig.Det_region[0].x * fs_resize_x;
p1.y = m_Edge_DetConfig.Det_region[0].y * fs_resize_y;
cv::Point p2;
p2.x = m_Edge_DetConfig.Det_region[m_Edge_DetConfig.Det_region.size() - 1].x * fs_resize_x;
p2.y = m_Edge_DetConfig.Det_region[m_Edge_DetConfig.Det_region.size() - 1].y * fs_resize_y;
cv::line(m_CheckResult_shareP->resultimg, p1, p2, cv::Scalar(0, 255, 255));
} }
cv::polylines(m_CheckResult_shareP->resultimg, draw_pts, true, cv::Scalar(255, 255, 0), 1);
} }
} for (const auto &contour : m_curPinContours)
if (m_pbaseCheckFunction && m_pbaseCheckFunction->markLine.region.size() > 1)
{ {
std::vector<cv::Point> product_roi_show; std::vector<cv::Point> draw_pts;
for (const auto &pt : m_pbaseCheckFunction->markLine.region) draw_pts.reserve(contour.size());
for (const auto &pt : contour)
{ {
cv::Point draw_pt; draw_pts.emplace_back(cvRound(pt.x * fs_resize_x), cvRound(pt.y * fs_resize_y));
draw_pt.x = (pt.x - m_Crop_Roi_paramImg.x) * fs_resize_x;
draw_pt.y = (pt.y - m_Crop_Roi_paramImg.y) * fs_resize_y;
product_roi_show.push_back(draw_pt);
} }
cv::polylines(m_CheckResult_shareP->resultimg, draw_pts, true, cv::Scalar(255, 0, 255), 1);
cv::polylines(
m_CheckResult_shareP->resultimg,
product_roi_show,
true,
cv::Scalar(0, 255, 0),
1);
} }
if (m_pEdge_Align_Result.get() != NULL)
{
if (m_pbaseCheckFunction->markLine.bDraw) // 绘制m_inner_rroi蓝色
{
for (size_t i = 0; i < m_pEdge_Align_Result->markresulList.size(); i++)
{ {
// if (m_pEdge_Align_Result->markresulList[i].status == Mark_Result_Status_OK) cv::Point2f vertices[4];
m_inner_rroi.points(vertices);
std::vector<cv::Point> draw_pts;
draw_pts.reserve(4);
for (int i = 0; i < 4; i++)
{ {
cv::Point p; draw_pts.emplace_back(cvRound((vertices[i].x - m_Crop_Roi_paramImg.x) * fs_resize_x),
p.x = m_pEdge_Align_Result->markresulList[i].det_Local_DetImg.x * fs_resize_x; cvRound((vertices[i].y - m_Crop_Roi_paramImg.y) * fs_resize_y));
p.y = m_pEdge_Align_Result->markresulList[i].det_Local_DetImg.y * fs_resize_y;
cv::circle(m_CheckResult_shareP->resultimg, p, 5, cv::Scalar(0, 255, 0));
}
}
} }
cv::polylines(m_CheckResult_shareP->resultimg, draw_pts, true, cv::Scalar(255, 0, 0), 1);
} }
// cv::imwrite("sss.png", m_CheckResult_shareP->resultimg); // cv::imwrite("sss.png", m_CheckResult_shareP->resultimg);
@ -1970,38 +1828,32 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
int ImgCheckAnalysisy::AIClassTypeToConfigType(int nAIQXType) int ImgCheckAnalysisy::AIClassTypeToConfigType(int nAIQXType)
{ {
int resultError_type = CONFIG_QX_NAME_cell_aotudian; int resultError_type = CONFIG_QX_NAME_other;
switch (nAIQXType) switch (nAIQXType)
{ {
case AI_CLass_QX_NAME_aotudian: case AI_CLass_QX_NAME_PIN_PoSun:
resultError_type = CONFIG_QX_NAME_cell_aotudian; resultError_type = CONFIG_QX_NAME_PIN_PoSun;
break; break;
case AI_CLass_QX_NAME_other: case AI_CLass_QX_NAME_PIN_QueShi:
resultError_type = CONFIG_QX_NAME_cell_other; resultError_type = CONFIG_QX_NAME_PIN_QueShi;
break;
case AI_CLass_QX_NAME_line:
resultError_type = CONFIG_QX_NAME_cell_line;
break; break;
case AI_CLass_QX_NAME_zangwu: case AI_CLass_QX_NAME_BTB_DuanLie:
resultError_type = CONFIG_QX_NAME_cell_zangwu; resultError_type = CONFIG_QX_NAME_BTB_DuanLie;
break; break;
case AI_CLass_QX_NAME_dianzhuang: case AI_CLass_QX_NAME_LianXi:
resultError_type = CONFIG_QX_NAME_cell_dianzhuang; resultError_type = CONFIG_QX_NAME_LianXi;
break; break;
case AI_CLass_QX_NAME_posun: case AI_CLass_QX_NAME_QueXi:
resultError_type = CONFIG_QX_NAME_cell_posun; resultError_type = CONFIG_QX_NAME_QueXi;
break; break;
case AI_CLass_QX_NAME_xianwei: case AI_CLass_QX_NAME_YiWu:
resultError_type = CONFIG_QX_NAME_cell_xianwei; resultError_type = CONFIG_QX_NAME_YiWu;
break; break;
case AI_CLass_QX_NAME_shuizi: case AI_CLass_QX_NAME_C_BianXing:
resultError_type = CONFIG_QX_NAME_cell_shuizi; resultError_type = CONFIG_QX_NAME_C_BianXing;
break; break;
case AI_CLass_QX_NAME_danban: case AI_CLass_QX_NAME_other:
resultError_type = CONFIG_QX_NAME_cell_danban; resultError_type = CONFIG_QX_NAME_other;
break;
case AI_CLass_QX_NAME_fuchen:
resultError_type = CONFIG_QX_NAME_cell_fuchen;
break; break;
default: default:
break; break;
@ -2036,76 +1888,171 @@ int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
m_Edge_DetConfig.bSaveResultImg = true; m_Edge_DetConfig.bSaveResultImg = true;
} }
// m_pbaseCheckFunction->print("Pin_Qx_Det"); // m_pbaseCheckFunction->print("Pin_Qx_Det");
int re = m_Pin_QX_Det.Detect(img, &m_Edge_DetConfig); Mat pin_mask;
if (re == 0) int re = m_Pin_QX_Det.GetPinMask(img, &m_Edge_DetConfig, pin_mask);
// 统计tplPinMask的blob边缘点并绘制到tplImg上
vector<vector<Point>> pin_contours;
vector<Vec4i> hierarchy;
cv::findContours(pin_mask, pin_contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
//缩放比例
const float pin_scale_x = (pin_mask.cols > 0) ? static_cast<float>(img.cols) / pin_mask.cols : 0.0f;
const float pin_scale_y = (pin_mask.rows > 0) ? static_cast<float>(img.rows) / pin_mask.rows : 0.0f;
// 将轮廓点从 mask 坐标系 映射回 tplImg 坐标系
m_curPinContours.clear();
m_curPinContours.reserve(pin_contours.size());
for (size_t i = 0; i < pin_contours.size(); i++)
{ {
for (const auto r : m_Edge_DetConfig.qx_result) std::vector<cv::Point> mapped;
mapped.reserve(pin_contours[i].size());
for (const auto &pt : pin_contours[i])
{ {
QX_ERROR_INFO_ temerror; mapped.emplace_back(cvRound(pt.x * pin_scale_x),
temerror.roi = r.roi_src; cvRound(pt.y * pin_scale_y));
temerror.Idx = m_pDetResult->pQx_ErrorList->size(); }
temerror.area = r.area_pixel; m_curPinContours.push_back(mapped);
temerror.JudgArea = r.area_pixel * m_fImgage_Scale_X * m_fImgage_Scale_Y; }
temerror.JudgArea_second = temerror.JudgArea;
temerror.energy = 99999999;
temerror.flen = std::max(r.roi_src.width, r.roi_src.height);
temerror.fbreadth = std::min(r.roi_src.width, r.roi_src.height);
temerror.nconfig_qx_type = CONFIG_QX_NAME_cell_edge;
temerror.qx_name = CONFIG_QX_NAME_Names[CONFIG_QX_NAME_cell_edge];
temerror.maxValue = 0;
temerror.grayDis = 255;
temerror.density = 0;
temerror.fUpIou = 0;
// 根据模板Pin和当前Pin轮廓进行对比判断当前有无缺失和偏移
{ {
cv::Point pCenter; // 计算轮廓中心点(外接矩形中心)
pCenter.x = temerror.roi.x + temerror.roi.width * 0.5; auto getCenter = [](const std::vector<cv::Point> &contour) -> cv::Point2f
pCenter.y = temerror.roi.y + temerror.roi.height * 0.5;
int nmaxregionIdx = 0;
for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
{ {
const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion]; cv::Rect r = cv::boundingRect(contour);
double result = cv::pointPolygonTest(polygon, pCenter, false); return cv::Point2f(r.x + r.width * 0.5f, r.y + r.height * 0.5f);
if (result < 0) };
const int nTpl = static_cast<int>(m_tplPinContours.size());
const int nCur = static_cast<int>(m_curPinContours.size());
if (nTpl > 0)
{
// 1、统计模板 pin 中心与外包矩形
std::vector<cv::Point2f> tplCenters(nTpl);
std::vector<cv::Rect> tplRects(nTpl);
for (int i = 0; i < nTpl; i++)
{
tplCenters[i] = getCenter(m_tplPinContours[i]);
tplRects[i] = cv::boundingRect(m_tplPinContours[i]);
}
// 2、当前 pin 中心与外包矩形
std::vector<cv::Point2f> curCenters(nCur);
std::vector<cv::Rect> curRects(nCur);
for (int i = 0; i < nCur; i++)
{
curCenters[i] = getCenter(m_curPinContours[i]);
curRects[i] = cv::boundingRect(m_curPinContours[i]);
}
std::vector<bool> curUsed(nCur, false);
// 3、偏移阈值由基础参数 pin_x_offset / pin_y_offset (mm) 换算为像素
float offsetThX = 0.0f;
float offsetThY = 0.0f;
if (m_pbaseCheckFunction != NULL)
{
if (m_fImgage_Scale_X > 0.0f)
{
offsetThX = m_pbaseCheckFunction->pinDet.pin_x_offset / m_fImgage_Scale_X;
}
if (m_fImgage_Scale_Y > 0.0f)
{
offsetThY = m_pbaseCheckFunction->pinDet.pin_y_offset / m_fImgage_Scale_Y;
}
}
// 上报缺失/偏移缺陷(缺陷类型可按需调整)
auto reportPinError = [&](int pinIdx, const cv::Point2f &tplCenter, const std::string &reason, int nconfig_qx_type)
{
QX_ERROR_INFO_ pinErr;
pinErr.Idx = static_cast<int>(m_pDetResult->pQx_ErrorList->size());
cv::Rect r = cv::boundingRect(m_tplPinContours[pinIdx]);
pinErr.roi = r;
pinErr.area = static_cast<int>(cv::contourArea(m_tplPinContours[pinIdx]));
pinErr.JudgArea = pinErr.area * m_fImgage_Scale_X * m_fImgage_Scale_Y;
int longSide = (r.width > r.height) ? r.width : r.height;
int shortSide = (r.width < r.height) ? r.width : r.height;
pinErr.flen = longSide * m_fImgage_Scale_X;
pinErr.fbreadth = shortSide * m_fImgage_Scale_Y;
pinErr.nconfig_qx_type = nconfig_qx_type;
pinErr.qx_name = CONFIG_QX_NAME_Names[nconfig_qx_type];
pinErr.detRegionidxList.push_back(0);
pinErr.detlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Pin Check",
"pin %d center(%d,%d) %s",
pinIdx, static_cast<int>(tplCenter.x), static_cast<int>(tplCenter.y),
reason.c_str());
m_pDetResult->pQx_ErrorList->push_back(pinErr);
};
int nMiss = 0;
int nOffset = 0;
// 4、逐个模板 pin 找与其相交且未被占用的当前 pin
for (int i = 0; i < nTpl; i++)
{
int bestIdx = -1;
double bestDist = 1e12;
for (int j = 0; j < nCur; j++)
{
if (curUsed[j])
{ {
continue; continue;
} }
nmaxregionIdx = iregion;
// 完全与模板没有相交 -> 不算候选
cv::Rect inter = tplRects[i] & curRects[j];
if (inter.width <= 0 || inter.height <= 0)
{
continue;
} }
temerror.detRegionidxList.push_back(nmaxregionIdx); float dx = tplCenters[i].x - curCenters[j].x;
float dy = tplCenters[i].y - curCenters[j].y;
double d = std::sqrt(static_cast<double>(dx) * dx + static_cast<double>(dy) * dy);
if (d < bestDist)
{
bestDist = d;
bestIdx = j;
}
} }
// { // 没有相交的当前 pin -> 缺失
// cv::Point pCenter; if (bestIdx < 0)
// pCenter.x = temerror.roi.x + temerror.roi.width * 0.5; {
// pCenter.y = temerror.roi.y + temerror.roi.height * 0.5; nMiss++;
// int nmaxregionIdx = 0; reportPinError(i, tplCenters[i], "miss", CONFIG_QX_NAME_PIN_QueShi);
// for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++) m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "pin %d MISS", i);
// { continue;
// const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion]; }
// double result = cv::pointPolygonTest(polygon, pCenter, false);
// if (result < 0)
// {
// continue;
// }
// temerror.detRegionidxList.push_back(iregion);
// }
// if (temerror.detRegionidxList.size() <= 0)
// {
// temerror.detRegionidxList.push_back(0);
// }
// }
m_pDetResult->pQx_ErrorList->push_back(temerror); curUsed[bestIdx] = true;
// x 或 y 方向偏移超过配置阈值 -> 偏移
float dx = tplCenters[i].x - curCenters[bestIdx].x;
float dy = tplCenters[i].y - curCenters[bestIdx].y;
float absDx = std::fabs(dx);
float absDy = std::fabs(dy);
if (absDx > offsetThX || absDy > offsetThY)
{
nOffset++;
char buf[64];
snprintf(buf, sizeof(buf), "offset dx %.1f dy %.1f", absDx, absDy);
reportPinError(i, tplCenters[i], buf, CONFIG_QX_NAME_PIN_PianYi);
m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "pin %d OFFSET dx %.1f dy %.1f", i, absDx, absDy);
}
} }
m_pdetlog->AddCheckstr(PrintLevel_1, "Pin_Qx_Det", " succ qx num %ld", m_Edge_DetConfig.qx_result.size()); m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "tpl %d cur %d miss %d offset %d", nTpl, nCur, nMiss, nOffset);
// printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen);
} }
else }
if (m_Edge_DetConfig.bSaveResultImg)
{ {
m_pdetlog->AddCheckstr(PrintLevel_1, "Pin_Qx_Det", " error %d", re); Mat showimg;
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
cv::drawContours(showimg, m_curPinContours, -1, cv::Scalar(0, 0, 255), 1);
cv::drawContours(showimg, m_tplPinContours, -1, cv::Scalar(0, 255, 0), 1);
imwrite("pin_contours.png", showimg);
} }
return 0; return 0;

@ -5,52 +5,18 @@
#include <random> #include <random>
#include "CheckErrorCodeDefine.hpp" #include "CheckErrorCodeDefine.hpp"
int Pin_QX_Det::creatsavedir()
{
std::string curDate = CheckUtil::getCurrentDate();
if (curDate == m_strLastDate)
{
return 0;
}
m_strLastDate = curDate;
m_strSavePath_Pin = m_strRootPath_Pin + curDate + "/";
CheckUtil::CreateDir(m_strSavePath_Pin);
return 0;
return 0;
}
Pin_QX_Det::Pin_QX_Det(std::shared_ptr<DetLog> &log_ref) Pin_QX_Det::Pin_QX_Det(std::shared_ptr<DetLog> &log_ref)
: m_pdetlog(log_ref) : m_pdetlog(log_ref)
{ {
m_bInitialized = false;
m_bModelSucc = false;
m_bModel_Mark_Succ = false;
m_bshowimg = false;
m_strRootPath_Pin = "/home/aidlux/BOE/Pin/";
creatsavedir();
std::string m_strSavePath; std::string m_strSavePath;
m_pImageStorage = ImageStorage::getInstance();
AI_Factory = AIFactory::GetInstance(); AI_Factory = AIFactory::GetInstance();
} }
Pin_QX_Det::~Pin_QX_Det() Pin_QX_Det::~Pin_QX_Det()
{ {
} }
int Pin_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
{
// if (!pDetConfig->pBaseCheckFunction->edgeDet.bOpen)
// {
// return 0;
// }
m_bshowimg = false;
if (pDetConfig->bSaveResultImg)
{
m_bshowimg = true;
}
int Pin_QX_Det::GetPinMask(const cv::Mat &img, DetConfigResult *pDetConfig, Mat &mask)
{
std::shared_ptr<AIModel_Base> pSocket_Pin; std::shared_ptr<AIModel_Base> pSocket_Pin;
pSocket_Pin = AI_Factory->Pin_Loc; pSocket_Pin = AI_Factory->Pin_Loc;
cv::Size sz; cv::Size sz;
@ -62,7 +28,6 @@ int Pin_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
cv::resize(img, detImg, sz); cv::resize(img, detImg, sz);
int re = 0; int re = 0;
cv::Mat mask;
if (detImg.channels() != 1) if (detImg.channels() != 1)
{ {
cv::cvtColor(detImg, detImg, cv::COLOR_RGB2GRAY); cv::cvtColor(detImg, detImg, cv::COLOR_RGB2GRAY);
@ -71,27 +36,16 @@ int Pin_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
re = pSocket_Pin->AIDet(detImg, mask); re = pSocket_Pin->AIDet(detImg, mask);
if (re != 0) if (re != 0)
{ {
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge----error %d ", re); m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Pin ", "AICheck_Pin----error %d ", re);
int re123 = 100 + re; int re123 = 100 + re;
return re123; return re123;
} }
if (pDetConfig->pBaseCheckFunction->saveImg.bSaveAlginImg)
{
}
if (pDetConfig->bSaveResultImg) if (pDetConfig->bSaveResultImg)
{ {
cv::imwrite(pDetConfig->strChannel +"_pin_" +"in.png", detImg); cv::imwrite(pDetConfig->strChannel +"_pin_" +"in.png", detImg);
cv::imwrite(pDetConfig->strChannel +"_pin_" +"out_mask.png", mask); cv::imwrite(pDetConfig->strChannel +"_pin_" +"out_mask.png", mask);
} }
if (m_bshowimg)
{
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
}
return 0; return 0;
} }

@ -3,7 +3,7 @@
* @Date: 2025-09-13 19:26:19 * @Date: 2025-09-13 19:26:19
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-17 18:10:38 * @LastEditTime: 2025-09-17 18:10:38
* @FilePath: /BOE_CELL_AOI_Detect/AlgorithmModule/src/Product.cpp * @FilePath: /BOE_ZB_SOCKET_Detect/AlgorithmModule/src/Product.cpp
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* *
*/ */

@ -32,11 +32,13 @@ set(ModuleName "")
# #
set(CMAKE_INSTALL_PREFIX /usr/local/polet CACHE PATH "Install path prefix" FORCE) set(CMAKE_INSTALL_PREFIX /usr/local/polet CACHE PATH "Install path prefix" FORCE)
set(HEADER_FILES include/ConfigBase.h) set(HEADER_FILES include/ConfigBase.h)
# _socket
set_target_properties(Config PROPERTIES OUTPUT_NAME "Config_socket")
# #
install(TARGETS Config install(TARGETS Config
LIBRARY DESTINATION lib # CMAKE_INSTALL_PREFIX/lib LIBRARY DESTINATION lib # CMAKE_INSTALL_PREFIX/lib
ARCHIVE DESTINATION lib/static ARCHIVE DESTINATION lib/static
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
PUBLIC_HEADER DESTINATION include) # CMAKE_INSTALL_PREFIX/include PUBLIC_HEADER DESTINATION include) # CMAKE_INSTALL_PREFIX/include
# # _socket
install(FILES ${HEADER_FILES} DESTINATION include) install(FILES include/ConfigBase.h DESTINATION include RENAME ConfigBase_socket.h)

@ -39,35 +39,29 @@ static const std::string WHITE_BLCAK_Names[] =
// 检测缺陷的种类 // 检测缺陷的种类
enum CONFIG_QX_NAME_ enum CONFIG_QX_NAME_
{ {
CONFIG_QX_NAME_cell_aotudian, // 分类 凹凸点 CONFIG_QX_NAME_PIN_PoSun, // 分类 PIN破损
CONFIG_QX_NAME_cell_other, // 分类 其他 CONFIG_QX_NAME_PIN_QueShi, // 分类 PIN缺失
CONFIG_QX_NAME_cell_line, // 分类 线状 CONFIG_QX_NAME_BTB_DuanLie, // 分类 BTB断裂
CONFIG_QX_NAME_cell_zangwu, // 分类 脏污 CONFIG_QX_NAME_LianXi, // 分类 连锡
CONFIG_QX_NAME_cell_edge, // 分类 边缘 CONFIG_QX_NAME_QueXi, // 分类 缺锡
CONFIG_QX_NAME_cell_ymhs, // 分类 异物 CONFIG_QX_NAME_YiWu, // 分类 异物
CONFIG_QX_NAME_cell_dianzhuang, // 分类 点状 CONFIG_QX_NAME_C_BianXing, // 分类 C型卡口异常
CONFIG_QX_NAME_cell_posun, // 分类 破损 CONFIG_QX_NAME_other, // 分类 其他
CONFIG_QX_NAME_cell_xianwei, // 分类 纤维 CONFIG_QX_NAME_PIN_PianYi, // 分类 PIN偏移
CONFIG_QX_NAME_cell_shuizi, // 分类 水渍
CONFIG_QX_NAME_cell_danban, // 分类 淡斑
CONFIG_QX_NAME_cell_fuchen, // 分类 浮尘
CONFIG_QX_NAME_count, CONFIG_QX_NAME_count,
}; };
// 缺陷项对应在参数中的名称 // 缺陷项对应在参数中的名称
static std::vector<std::string> CONFIG_QX_NAME_Names = static std::vector<std::string> CONFIG_QX_NAME_Names =
{ {
"aotudian", "PIN_PoSun",
"PIN_QueShi",
"BTB_DuanLie",
"LianXi",
"QueXi",
"YiWu",
"C_BianXing",
"other", "other",
"line", "PIN_PianYi",
"zangwu",
"edge",
"ymhs",
"dianzhuang",
"posun",
"xianwei",
"shuizi",
"danban",
"fuchen",
}; };
// 分析类型 // 分析类型
@ -1018,52 +1012,44 @@ struct ChannelCheckFunction
}; };
// 基础检测功能 mark // 基础检测功能 mark
struct Base_Function_MarkLine struct Base_Function_ALign
{ {
bool bOpen; // 是否开启 bool bOpen; // 是否开启
bool bDraw; // 是否绘制 float angle_diff;
bool badapt_region; // 是否自适应区域 float x_offset;
cv::Rect productROI; float y_offset;
std::vector<cv::Point> region;
cv::Point mark_local_1;
cv::Point mark_local_2;
Base_Function_MarkLine() Base_Function_ALign()
{ {
Init(); Init();
} }
void Init() void Init()
{ {
bOpen = false; bOpen = false;
bDraw = false; angle_diff = 0.0;
badapt_region = false; x_offset = 0.0;
mark_local_1 = cv::Point(0, 0); y_offset = 0.0;
mark_local_2 = cv::Point(0, 0);
productROI = cv::Rect(0, 0, 0, 0);
region.clear();
} }
void copy(Base_Function_MarkLine tem) void copy(Base_Function_ALign tem)
{ {
this->bOpen = tem.bOpen; this->bOpen = tem.bOpen;
this->region.assign(tem.region.begin(), tem.region.end()); this->angle_diff = tem.angle_diff;
this->productROI = tem.productROI; this->x_offset = tem.x_offset;
this->bDraw = tem.bDraw; this->y_offset = tem.y_offset;
this->badapt_region = tem.badapt_region;
this->mark_local_1 = tem.mark_local_1;
this->mark_local_2 = tem.mark_local_2;
} }
void print(std::string str) void print(std::string str)
{ {
printf("%s>>bOpen %d bDraw %d badapt_region %d mark1 [%d %d] mark2 [%d %d] \n", str.c_str(), printf("%s>>bOpen %d angle_diff %f x_offset %f y_offset %f \n", str.c_str(),
bOpen, bDraw, badapt_region,mark_local_1.x, mark_local_1.y, mark_local_2.x, mark_local_2.y); bOpen, angle_diff, x_offset, y_offset);
} }
std::string GetInfo(std::string str) std::string GetInfo(std::string str)
{ {
char buffer[256]; char buffer[256];
sprintf(buffer, "%s>>bOpen %d bDraw %d badapt_region %d mark1 [%d %d] mark2 [%d %d] \n", str.c_str(), sprintf(buffer, "%s>>bOpen %d angle_diff %f x_offset %f y_offset %f \n", str.c_str(),
bOpen, bDraw, badapt_region,mark_local_1.x, mark_local_1.y, mark_local_2.x, mark_local_2.y); bOpen, angle_diff, x_offset, y_offset);
std::string str123 = buffer; std::string str123 = buffer;
return str123; return str123;
} }
@ -1206,91 +1192,43 @@ struct Base_Function_BigNG
} }
}; };
// 基础检测功能 CELL AOI 边缘缺陷检测 // 基础检测功能 CELL AOI 边缘缺陷检测
struct Base_Function_Edge_Det struct Base_Function_Pin_Det
{ {
bool bOpen; // 是否开启 bool bOpen; // 是否开启
int Search_threshold; // 搜索边缘阈值 float pin_x_offset; // pin x 偏移
int Det_threshold; // 缺陷检测阈值 float pin_y_offset; // pin y 偏移
int Det_Range; // 检测范围
int QX_Widht_min; // 缺陷宽度-最小
int QX_Widht_max;
int QX_Height_min;
int QX_Height_max;
bool queJiao_LU_Open;
bool queJiao_RU_Open;
bool queJiao_LD_Open;
bool queJiao_RD_Open;
int queJiao_width;
int queJiao_height;
bool bDrawRoi;
cv::Rect draw_ROI;
std::vector<cv::Point> region;
bool bDrawResult; // 是否绘制结果 bool bDrawResult; // 是否绘制结果
Base_Function_Edge_Det() Base_Function_Pin_Det()
{ {
Init(); Init();
} }
void Init() void Init()
{ {
bOpen = false; bOpen = false;
Search_threshold = 30; pin_x_offset = 0;
Det_threshold = 30; pin_y_offset = 0;
Det_Range = 100;
QX_Widht_min = 10;
QX_Widht_max = 100;
QX_Height_min = 10;
QX_Height_max = 100;
queJiao_LU_Open = false;
queJiao_RU_Open = false;
queJiao_LD_Open = false;
queJiao_RD_Open = false;
queJiao_width = 50;
queJiao_height = 50;
bDrawRoi = false;
draw_ROI = cv::Rect(0, 0, 0, 0);
region.clear();
region.erase(region.begin(), region.end());
bDrawResult = false; bDrawResult = false;
} }
void copy(Base_Function_Edge_Det tem) void copy(Base_Function_Pin_Det tem)
{ {
this->bOpen = tem.bOpen; this->bOpen = tem.bOpen;
this->Search_threshold = tem.Search_threshold; this->pin_x_offset = tem.pin_x_offset;
this->Det_threshold = tem.Det_threshold; this->pin_y_offset = tem.pin_y_offset;
this->Det_Range = tem.Det_Range;
this->QX_Widht_min = tem.QX_Widht_min;
this->QX_Widht_max = tem.QX_Widht_max;
this->QX_Height_min = tem.QX_Height_min;
this->QX_Height_max = tem.QX_Height_max;
this->queJiao_LU_Open = tem.queJiao_LU_Open;
this->queJiao_RU_Open = tem.queJiao_RU_Open;
this->queJiao_LD_Open = tem.queJiao_LD_Open;
this->queJiao_RD_Open = tem.queJiao_RD_Open;
this->queJiao_width = tem.queJiao_width;
this->queJiao_height = tem.queJiao_height;
this->region.assign(tem.region.begin(), tem.region.end());
this->draw_ROI = tem.draw_ROI;
this->bDrawRoi = tem.bDrawRoi;
this->bDrawResult = tem.bDrawResult; this->bDrawResult = tem.bDrawResult;
} }
void print(std::string str) void print(std::string str)
{ {
printf("%s>>bOpen %d Search_threshold %d Det_threshold %d Det_Range %d QX_Widht [%d %d] QX_Height [%d %d]\n", str.c_str(), printf("%s>>bOpen %d pin_x_offset %f pin_y_offset %f bDrawResult %d\n", str.c_str(),
bOpen, Search_threshold, Det_threshold, Det_Range, QX_Widht_min, QX_Widht_max, QX_Height_min, QX_Height_max); bOpen, pin_x_offset, pin_y_offset, bDrawResult);
} }
std::string GetInfo(std::string str) std::string GetInfo(std::string str)
{ {
char buffer[256]; char buffer[256];
sprintf(buffer, "%s>>bOpen %d Search_threshold %d Det_threshold %d Det_Range %d QX_Widht [%d %d] QX_Height [%d %d]\n", str.c_str(), sprintf(buffer, "%s>>bOpen %d pin_x_offset %f pin_y_offset %f bDrawResult %d\n", str.c_str(),
bOpen, Search_threshold, Det_threshold, Det_Range, QX_Widht_min, QX_Widht_max, QX_Height_min, QX_Height_max); bOpen, pin_x_offset, pin_y_offset, bDrawResult);
std::string str123 = buffer; std::string str123 = buffer;
return str123; return str123;
} }
@ -1298,8 +1236,8 @@ struct Base_Function_Edge_Det
// 基础检测功能 // 基础检测功能
struct BaseCheckFunction struct BaseCheckFunction
{ {
Base_Function_MarkLine markLine; Base_Function_ALign ALign_Config;
Base_Function_Edge_Det edgeDet; Base_Function_Pin_Det pinDet;
Base_Function_SaveImg saveImg; Base_Function_SaveImg saveImg;
Base_Function_BigNG bigNG; Base_Function_BigNG bigNG;
BaseCheckFunction() BaseCheckFunction()
@ -1308,31 +1246,31 @@ struct BaseCheckFunction
} }
void Init() void Init()
{ {
markLine.Init(); ALign_Config.Init();
edgeDet.Init(); pinDet.Init();
saveImg.Init(); saveImg.Init();
bigNG.Init(); bigNG.Init();
} }
void copy(BaseCheckFunction tem) void copy(BaseCheckFunction tem)
{ {
this->markLine.copy(tem.markLine); this->ALign_Config.copy(tem.ALign_Config);
this->edgeDet.copy(tem.edgeDet); this->pinDet.copy(tem.pinDet);
this->saveImg.copy(tem.saveImg); this->saveImg.copy(tem.saveImg);
this->bigNG.copy(tem.bigNG); this->bigNG.copy(tem.bigNG);
} }
void print(std::string str) void print(std::string str)
{ {
printf("******* %s *********\n", str.c_str()); printf("******* %s *********\n", str.c_str());
markLine.print("markLine"); ALign_Config.print("ALign_Config");
edgeDet.print("edgeDet"); pinDet.print("pinDet");
saveImg.print("saveImg"); saveImg.print("saveImg");
bigNG.print("bigNG"); bigNG.print("bigNG");
} }
std::string GetInfo(std::string str) std::string GetInfo(std::string str)
{ {
std::string str123 = ""; std::string str123 = "";
str123 += markLine.GetInfo("markLine"); str123 += ALign_Config.GetInfo("ALign_Config");
str123 += edgeDet.GetInfo("edgeDet"); str123 += pinDet.GetInfo("pinDet");
str123 += saveImg.GetInfo("saveImg"); str123 += saveImg.GetInfo("saveImg");
str123 += bigNG.GetInfo("bigNG"); str123 += bigNG.GetInfo("bigNG");
// str123 += "\n"; // str123 += "\n";

@ -3,7 +3,7 @@
* @Date: 2025-09-11 15:32:54 * @Date: 2025-09-11 15:32:54
* @LastEditors: xiewenji 527774126@qq.com * @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-09-13 18:49:40 * @LastEditTime: 2025-09-13 18:49:40
* @FilePath: /BOE_CELL_AOI_Detect/ConfigModule/include/ConfigBase.h * @FilePath: /BOE_ZB_SOCKET_Detect/ConfigModule/include/ConfigBase.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
#ifndef ConfigBase_H_ #ifndef ConfigBase_H_

@ -20,21 +20,19 @@ ConfigManager::~ConfigManager()
{ {
} }
std::vector<ReadFlawCode> m_FlawCodeList;
std::vector<std::string> QX_Result_Names = std::vector<std::string> QX_Result_Names =
{ {
"OK", "OK",
"aotudian", "PIN_PoSun",
"PIN_QueShi",
"BTB_DuanLie",
"LianXi",
"QueXi",
"YiWu",
"C_BianXing",
"other", "other",
"line",
"zangwu",
"edge",
"ymhs",
"dianzhuang",
"posun",
"xianwei",
"shuizi",
"danban",
"fuchen",
}; };
std::vector<std::string> QX_Result_Code = std::vector<std::string> QX_Result_Code =
{ {
@ -47,10 +45,6 @@ std::vector<std::string> QX_Result_Code =
"MA502", "MA502",
"MA505", "MA505",
"MA501", "MA501",
"P0001",
"P0002",
"P0003",
"P0004",
}; };
int ReadFlawCodeConfig(std::string json_path) int ReadFlawCodeConfig(std::string json_path)

@ -775,78 +775,25 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
auto value_f = value; auto value_f = value;
// std::cout << value_f << std::endl; // std::cout << value_f << std::endl;
// getchar(); // getchar();
_config.markLine.bOpen = value_f["isOpen"].asBool(); _config.ALign_Config.bOpen = value_f["isOpen"].asBool();
if (_config.markLine.bOpen) if (_config.ALign_Config.bOpen)
{ {
if (value_f["form"]["ALign_Config"]["angle_diff"])
{
auto crop_roi = value_f["form"]["ALign_Config"]["Product_ROI"];
// 2、读取区域点
{
auto value_region = value_f["form"]["ALign_Config"]["Product_ROI"];
if (value_region.isArray())
{
for (int idx = 0; idx < value_region.size(); idx++)
{
cv::Point p;
p.x = value_region[idx][0].asInt();
p.y = value_region[idx][1].asInt();
_config.markLine.region.emplace_back(p);
}
if (_config.markLine.region.size() > 0)
{
_config.markLine.productROI = boundingRect(_config.markLine.region);
}
}
}
// printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size());
}
if (value_f["form"]["ALign_Config"]["bDraw"])
{
_config.markLine.bDraw = value_f["form"]["ALign_Config"]["bDraw"].asBool();
}
if (value_f["form"]["ALign_Config"]["badapt_region"])
{
_config.markLine.badapt_region = value_f["form"]["ALign_Config"]["badapt_region"].asBool();
}
{ {
auto value_circl = value_f["form"]["ALign_Config"]["mark_1_Local"]["path"]; _config.ALign_Config.angle_diff = value_f["form"]["ALign_Config"]["angle_diff"].asFloat();
if (value_circl.isArray())
{
if (value_circl[0][0])
{
_config.markLine.mark_local_1.x = value_circl[0][0].asInt();
}
if (value_circl[0][1])
{
_config.markLine.mark_local_1.y = value_circl[0][1].asInt();
}
} }
} if (value_f["form"]["ALign_Config"]["x_offset"])
{
auto value_circl = value_f["form"]["ALign_Config"]["mark_2_Local"]["path"];
if (value_circl.isArray())
{
if (value_circl[0][0])
{ {
_config.markLine.mark_local_2.x = value_circl[0][0].asInt(); _config.ALign_Config.x_offset = value_f["form"]["ALign_Config"]["x_offset"].asFloat();
} }
if (value_circl[0][1]) if (value_f["form"]["ALign_Config"]["y_offset"])
{ {
_config.markLine.mark_local_2.y = value_circl[0][1].asInt(); _config.ALign_Config.y_offset = value_f["form"]["ALign_Config"]["y_offset"].asFloat();
} }
} }
}
// _config.markLine.print("dfe");
// getchar();
}
else else
{ {
_config.markLine.Init(); _config.ALign_Config.Init();
} }
} }
if ("Pin_QX_Detect" == strCode) if ("Pin_QX_Detect" == strCode)
@ -854,108 +801,28 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
auto value_f = value; auto value_f = value;
// std::cout << value_f << std::endl; // std::cout << value_f << std::endl;
// getchar(); // getchar();
_config.edgeDet.bOpen = value_f["isOpen"].asBool(); _config.pinDet.bOpen = value_f["isOpen"].asBool();
if (_config.edgeDet.bOpen) if (_config.pinDet.bOpen)
{
if (value_f["form"]["Search_Config"]["Search_threshold"])
{
_config.edgeDet.Search_threshold = value_f["form"]["Search_Config"]["Search_threshold"].asInt();
}
if (value_f["form"]["Detect_Config"]["Det_threshold"])
{
_config.edgeDet.Det_threshold = value_f["form"]["Detect_Config"]["Det_threshold"].asInt();
}
if (value_f["form"]["Detect_Config"]["Det_Range"])
{
_config.edgeDet.Det_Range = value_f["form"]["Detect_Config"]["Det_Range"].asInt();
}
if (value_f["form"]["Detect_Config"]["QX_Widht_min"])
{
_config.edgeDet.QX_Widht_min = value_f["form"]["Detect_Config"]["QX_Widht_min"].asInt();
}
if (value_f["form"]["Detect_Config"]["QX_Widht_max"])
{
_config.edgeDet.QX_Widht_max = value_f["form"]["Detect_Config"]["QX_Widht_max"].asInt();
}
if (value_f["form"]["Detect_Config"]["QX_Height_min"])
{
_config.edgeDet.QX_Height_min = value_f["form"]["Detect_Config"]["QX_Height_min"].asInt();
}
if (value_f["form"]["Detect_Config"]["QX_Height_max"])
{
_config.edgeDet.QX_Height_max = value_f["form"]["Detect_Config"]["QX_Height_max"].asInt();
}
///============================================
if (value_f["form"]["Jiao_Config"]["LU_Jiao"])
{
_config.edgeDet.queJiao_LU_Open = value_f["form"]["Jiao_Config"]["LU_Jiao"].asBool();
}
if (value_f["form"]["Jiao_Config"]["RU_Jiao"])
{
_config.edgeDet.queJiao_RU_Open = value_f["form"]["Jiao_Config"]["RU_Jiao"].asBool();
}
if (value_f["form"]["Jiao_Config"]["LD_Jiao"])
{
_config.edgeDet.queJiao_LD_Open = value_f["form"]["Jiao_Config"]["LD_Jiao"].asBool();
}
if (value_f["form"]["Jiao_Config"]["RD_Jiao"])
{
_config.edgeDet.queJiao_RD_Open = value_f["form"]["Jiao_Config"]["RD_Jiao"].asBool();
}
if (value_f["form"]["Jiao_Config"]["Jiao_Width"])
{ {
_config.edgeDet.queJiao_width = value_f["form"]["Jiao_Config"]["Jiao_Width"].asInt();
}
if (value_f["form"]["Jiao_Config"]["Jiao_Height"]) if (value_f["form"]["Det_Config"]["pin_x_offset"])
{ {
_config.edgeDet.queJiao_height = value_f["form"]["Jiao_Config"]["Jiao_Height"].asInt(); _config.pinDet.pin_x_offset = value_f["form"]["Det_Config"]["pin_x_offset"].asFloat();
}
if (value_f["form"]["Draw_Config"]["Open"])
{
_config.edgeDet.bDrawRoi = value_f["form"]["Draw_Config"]["Open"].asBool();
}
// 2、读取区域点
{
auto value_region = value_f["form"]["Draw_Config"]["Edge_ROI"];
if (value_region.isArray())
{
for (int idx = 0; idx < value_region.size(); idx++)
{
cv::Point p;
p.x = value_region[idx][0].asInt();
p.y = value_region[idx][1].asInt();
_config.edgeDet.region.emplace_back(p);
} }
if (_config.edgeDet.region.size() > 0) if (value_f["form"]["Det_Config"]["pin_y_offset"])
{ {
_config.edgeDet.draw_ROI = boundingRect(_config.edgeDet.region); _config.pinDet.pin_y_offset = value_f["form"]["Det_Config"]["pin_y_offset"].asFloat();
}
}
} }
if (value_f["form"]["otherConfig"]["bDrawResult"]) if (value_f["form"]["otherConfig"]["bDrawResult"])
{ {
_config.edgeDet.bDrawResult = value_f["form"]["otherConfig"]["bDrawResult"].asBool(); _config.pinDet.bDrawResult = value_f["form"]["otherConfig"]["bDrawResult"].asBool();
} }
} }
else else
{ {
_config.edgeDet.Init(); _config.pinDet.Init();
} }
// _config.edgeDet.print("edgeDet"); // _config.pinDet.print("pinDet");
// getchar(); // getchar();
} }
if ("Det_Image_Save" == strCode) if ("Det_Image_Save" == strCode)
@ -984,7 +851,7 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
{ {
_config.saveImg.Init(); _config.saveImg.Init();
} }
// _config.edgeDet.print("edgeDet"); // _config.pinDet.print("pinDet");
// getchar(); // getchar();
} }
if ("Big_NG" == strCode) if ("Big_NG" == strCode)
@ -995,131 +862,91 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
_config.bigNG.bOpen = value_f["isOpen"].asBool(); _config.bigNG.bOpen = value_f["isOpen"].asBool();
if (_config.bigNG.bOpen) if (_config.bigNG.bOpen)
{ {
if (value_f["form"]["aotudian"]["open"]) if (value_f["form"]["PIN_PoSun"]["open"])
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_aotudian].bOpen = value_f["form"]["aotudian"]["open"].asBool();
}
if (value_f["form"]["aotudian"]["Area"])
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_aotudian].fArea = value_f["form"]["aotudian"]["Area"].asFloat();
}
_config.bigNG.qx[CONFIG_QX_NAME_cell_aotudian].strname = "aotudian";
if (value_f["form"]["other"]["open"])
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_other].bOpen = value_f["form"]["other"]["open"].asBool();
}
if (value_f["form"]["other"]["Area"])
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_other].fArea = value_f["form"]["other"]["Area"].asFloat();
}
_config.bigNG.qx[CONFIG_QX_NAME_cell_other].strname = "other";
if (value_f["form"]["line"]["open"])
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_line].bOpen = value_f["form"]["line"]["open"].asBool();
}
if (value_f["form"]["line"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_line].fArea = value_f["form"]["line"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_PIN_PoSun].bOpen = value_f["form"]["PIN_PoSun"]["open"].asBool();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_line].strname = "line"; if (value_f["form"]["PIN_PoSun"]["Area"])
if (value_f["form"]["zangwu"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_zangwu].bOpen = value_f["form"]["zangwu"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_PIN_PoSun].fArea = value_f["form"]["PIN_PoSun"]["Area"].asFloat();
} }
if (value_f["form"]["zangwu"]["Area"]) _config.bigNG.qx[CONFIG_QX_NAME_PIN_PoSun].strname = "PIN_PoSun";
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_zangwu].fArea = value_f["form"]["zangwu"]["Area"].asFloat();
}
_config.bigNG.qx[CONFIG_QX_NAME_cell_zangwu].strname = "zangwu";
if (value_f["form"]["edge"]["open"]) if (value_f["form"]["PIN_QueShi"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_edge].bOpen = value_f["form"]["edge"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_PIN_QueShi].bOpen = value_f["form"]["PIN_QueShi"]["open"].asBool();
} }
if (value_f["form"]["edge"]["Area"]) if (value_f["form"]["PIN_QueShi"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_edge].fArea = value_f["form"]["edge"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_PIN_QueShi].fArea = value_f["form"]["PIN_QueShi"]["Area"].asFloat();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_edge].strname = "edge"; _config.bigNG.qx[CONFIG_QX_NAME_PIN_QueShi].strname = "PIN_QueShi";
if (value_f["form"]["ymhs"]["open"]) if (value_f["form"]["BTB_DuanLie"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_ymhs].bOpen = value_f["form"]["ymhs"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_BTB_DuanLie].bOpen = value_f["form"]["BTB_DuanLie"]["open"].asBool();
} }
if (value_f["form"]["ymhs"]["Area"]) if (value_f["form"]["BTB_DuanLie"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_ymhs].fArea = value_f["form"]["ymhs"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_BTB_DuanLie].fArea = value_f["form"]["BTB_DuanLie"]["Area"].asFloat();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_ymhs].strname = "ymhs"; _config.bigNG.qx[CONFIG_QX_NAME_BTB_DuanLie].strname = "BTB_DuanLie";
if (value_f["form"]["dianzhuang"]["open"]) if (value_f["form"]["LianXi"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_dianzhuang].bOpen = value_f["form"]["dianzhuang"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_LianXi].bOpen = value_f["form"]["LianXi"]["open"].asBool();
} }
if (value_f["form"]["dianzhuang"]["Area"]) if (value_f["form"]["LianXi"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_dianzhuang].fArea = value_f["form"]["dianzhuang"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_LianXi].fArea = value_f["form"]["LianXi"]["Area"].asFloat();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_dianzhuang].strname = "dianzhuang"; _config.bigNG.qx[CONFIG_QX_NAME_LianXi].strname = "LianXi";
if (value_f["form"]["posun"]["open"]) if (value_f["form"]["QueXi"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_posun].bOpen = value_f["form"]["posun"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_QueXi].bOpen = value_f["form"]["QueXi"]["open"].asBool();
} }
if (value_f["form"]["posun"]["Area"]) if (value_f["form"]["QueXi"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_posun].fArea = value_f["form"]["posun"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_QueXi].fArea = value_f["form"]["QueXi"]["Area"].asFloat();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_posun].strname = "posun"; _config.bigNG.qx[CONFIG_QX_NAME_QueXi].strname = "QueXi";
if (value_f["form"]["xianwei"]["open"]) if (value_f["form"]["YiWu"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_xianwei].bOpen = value_f["form"]["xianwei"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_YiWu].bOpen = value_f["form"]["YiWu"]["open"].asBool();
} }
if (value_f["form"]["xianwei"]["Area"]) if (value_f["form"]["YiWu"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_xianwei].fArea = value_f["form"]["xianwei"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_YiWu].fArea = value_f["form"]["YiWu"]["Area"].asFloat();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_xianwei].strname = "xianwei"; _config.bigNG.qx[CONFIG_QX_NAME_YiWu].strname = "YiWu";
if (value_f["form"]["shuizi"]["open"]) if (value_f["form"]["C_BianXing"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_shuizi].bOpen = value_f["form"]["shuizi"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_C_BianXing].bOpen = value_f["form"]["C_BianXing"]["open"].asBool();
} }
if (value_f["form"]["shuizi"]["Area"]) if (value_f["form"]["C_BianXing"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_shuizi].fArea = value_f["form"]["shuizi"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_C_BianXing].fArea = value_f["form"]["C_BianXing"]["Area"].asFloat();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_shuizi].strname = "shuizi"; _config.bigNG.qx[CONFIG_QX_NAME_C_BianXing].strname = "C_BianXing";
if (value_f["form"]["danban"]["open"]) if (value_f["form"]["other"]["open"])
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_danban].bOpen = value_f["form"]["danban"]["open"].asBool();
}
if (value_f["form"]["danban"]["Area"])
{
_config.bigNG.qx[CONFIG_QX_NAME_cell_danban].fArea = value_f["form"]["danban"]["Area"].asFloat();
}
_config.bigNG.qx[CONFIG_QX_NAME_cell_danban].strname = "danban";
if (value_f["form"]["fuchen"]["open"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_fuchen].bOpen = value_f["form"]["fuchen"]["open"].asBool(); _config.bigNG.qx[CONFIG_QX_NAME_other].bOpen = value_f["form"]["other"]["open"].asBool();
} }
if (value_f["form"]["fuchen"]["Area"]) if (value_f["form"]["other"]["Area"])
{ {
_config.bigNG.qx[CONFIG_QX_NAME_cell_fuchen].fArea = value_f["form"]["fuchen"]["Area"].asFloat(); _config.bigNG.qx[CONFIG_QX_NAME_other].fArea = value_f["form"]["other"]["Area"].asFloat();
} }
_config.bigNG.qx[CONFIG_QX_NAME_cell_fuchen].strname = "fuchen"; _config.bigNG.qx[CONFIG_QX_NAME_other].strname = "other";
} }
else else
{ {
_config.bigNG.Init(); _config.bigNG.Init();
} }
// _config.edgeDet.print("edgeDet"); // _config.pinDet.print("pinDet");
// getchar(); // getchar();
} }
return 0; return 0;

@ -423,6 +423,7 @@ int deal::preCheck()
{ {
continue; continue;
} }
pushImgNum++;
} }
SetStatus_List(ThreadIdx, Thread_Status_READY); SetStatus_List(ThreadIdx, Thread_Status_READY);
GetImgNum++; GetImgNum++;
@ -458,7 +459,7 @@ int deal::preCheck()
std::shared_ptr<CheckResult> checkResult; std::shared_ptr<CheckResult> checkResult;
int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult); int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult);
saveImg("/home/aidlux/BOE/CELL_AOI/testresult/", checkResult); saveImg("/home/aidlux/BOE/ZB_SOCKET/testresult/", checkResult);
getresultNum++; getresultNum++;
if (getresultNum == pushImgNum) if (getresultNum == pushImgNum)
{ {
@ -804,14 +805,14 @@ void deal::ResultThread(int id)
// 存图 // 存图
// std::string savepath = "/home/aidlux/BOE/Detsave/" + runConfig.filePath + "/"; // std::string savepath = "/home/aidlux/BOE/Detsave/" + runConfig.filePath + "/";
// saveImg(savepath, dealResult); // saveImg(savepath, dealResult);
saveImg("/home/aidlux/BOE/CELL_AOI/Detsave/", dealResult); saveImg("/home/aidlux/BOE/ZB_SOCKET/Detsave/", dealResult);
} }
{ {
// 存 检测统计 日志 // 存 检测统计 日志
mutex_DetResult_.lock(); mutex_DetResult_.lock();
m_DetResult.print(false); m_DetResult.print(false);
std::string strlog = "/home/aidlux/BOE/CELL_AOI/ResultImg/"; std::string strlog = "/home/aidlux/BOE/ZB_SOCKET/ResultImg/";
if (m_strCurDate != "") if (m_strCurDate != "")
{ {
strlog += m_strCurDate; strlog += m_strCurDate;
@ -1167,7 +1168,12 @@ int deal::DetImg()
{ {
m_nReadThread_type = READ_THREAD_TYPE_READIMG; m_nReadThread_type = READ_THREAD_TYPE_READIMG;
StartThread(THREAD_RUN_Only_ReadImg); StartThread(THREAD_RUN_Only_ReadImg);
// -8 循环执行:像 -f 批量一样,线程只启动一次,内部重复跑同一套图
do
{
preCheck(); preCheck();
usleep(10 * 1000);
} while (runConfig.bLoop);
return 0; return 0;
} }
@ -1597,6 +1603,11 @@ int deal::LoadProductID(std::string strImgPath)
} }
int deal::DelImg_Cell_ET() int deal::DelImg_Cell_ET()
{ {
// -8 循环执行:每次重新加载产品列表,重复跑同一批产品
if (runConfig.bLoop && runConfig.filePath != "")
{
LoadProductID(runConfig.filePath);
}
size_t totalSize = m_product_ID_List.size(); size_t totalSize = m_product_ID_List.size();
if (totalSize > 0) if (totalSize > 0)

@ -499,6 +499,7 @@ struct DealRunConfig
RUNTYPE_ det_Type = RUNTYPE_RUN_Pre; // 处理 RUNTYPE_ det_Type = RUNTYPE_RUN_Pre; // 处理
std::string filePath = ""; // 处理文件路径 如果为空 处理当前的单张图片 std::string filePath = ""; // 处理文件路径 如果为空 处理当前的单张图片
bool bSaveProcessImg = false; // 是否中间图片图片 bool bSaveProcessImg = false; // 是否中间图片图片
bool bLoop = false; // -8 循环执行(常驻)
void print(std::string str) void print(std::string str)
{ {
printf(">>>>>>>>>>>>>>> %s <<<<<<<<<<<<\n", str.c_str()); printf(">>>>>>>>>>>>>>> %s <<<<<<<<<<<<\n", str.c_str());

@ -85,6 +85,7 @@ int main(int argc, char *argv[])
cout << "*** 5、./test_JBL_Check -falign filepath num : 批量测试定位算法num 至多处理张数,结果:/home/aidlux/BOE/Align" << endl; cout << "*** 5、./test_JBL_Check -falign filepath num : 批量测试定位算法num 至多处理张数,结果:/home/aidlux/BOE/Align" << endl;
cout << "*** 6、./test_JBL_Check -rjson filepath: 单张复测filepath xx/xx/3A3K380001B1DK_20240408_152157_Main_0_2_L255" << endl; 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 << "*** 6、./test_JBL_Check -rjsonall filepath: 一套图复测filepath xx/xx/" << endl;
cout << "*** 7、./test_SOCKET -8: 循环执行程序(常驻),不加 -8 只执行一次" << endl;
cout << "******************************************************" << endl; cout << "******************************************************" << endl;
return 0; return 0;
@ -145,12 +146,21 @@ int main(int argc, char *argv[])
test.runConfig.print("config"); test.runConfig.print("config");
// getchar(); // getchar();
signal(SIGINT, handler); signal(SIGINT, handler);
test.start();
while (true) // -8: 循环执行程序(常驻);默认:执行一次后退出
bool bLoop = false;
for (int i = 1; i < argc; i++)
{ {
usleep(10 * 1000); if (string(argv[i]) == "-8")
{
bLoop = true;
break;
}
} }
test.runConfig.bLoop = bLoop;
test.start();
return 0; return 0;
} }

Loading…
Cancel
Save