feat 初步添加Pin脚检测

main
xiewenji 1 month ago
parent 7864359af2
commit dad094bf0a

@ -1,252 +0,0 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-13 16:05:08
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Edge_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-04 21:29:05
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Edge_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef Edge_QX_Det_H_
#define Edge_QX_Det_H_
#include <opencv2/opencv.hpp>
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
using namespace std;
using namespace cv;
// 边缘缺陷检测
class Edge_QX_Det
{
public:
// 搜索方向
enum Edge_DirectSign
{
DirectSign_UP,
DirectSign_DOWN,
DirectSign_Left,
DirectSign_Right,
};
// 搜索边缘了下,黑还是白
enum Search_Value_Type
{
Search_Value_White,
Search_Value_Black,
};
// 边缘搜索参数
struct Edge_Search_Config
{
cv::Rect roi; // 边缘搜索区域
Search_Value_Type searchValueType; // 搜索边缘了下,黑还是白
Edge_DirectSign directSign; // 搜索方向
int nValueThreshold; // 灰度阈值
int nSearchCount; // 搜索点的个数 把roi 均分成多少个点。
int nSearchrange; // 搜索范围,一般为单数,如果 1表示 搜索当前点如果3表示 除了当前点,还有左右 点。5表示 从-2到2
int stepCount; // 每个搜索点的步数
int nLimit; // 连续搜索多个满足阈值的点后,停止搜索,当前搜索点 搜索成功。
std::string strchannel;
Edge_Search_Config()
{
roi = cv::Rect(0, 0, 0, 0);
directSign = DirectSign_UP;
searchValueType = Search_Value_White;
nValueThreshold = 40;
nSearchCount = 30;
nSearchrange = 1;
stepCount = 2;
nLimit = 3;
strchannel = "";
}
bool CheckConfigValid()
{
bool bRet = true;
if (roi.width <= 0 || roi.height <= 0)
{
printf("s1 \n");
return false;
}
if (searchValueType < Search_Value_White || searchValueType > Search_Value_Black)
{
printf("s2 \n");
return false;
}
if (directSign < 0 || directSign > 4)
{
printf("s3 \n");
return false;
}
if (nValueThreshold < 0 || nValueThreshold > 255)
{
printf("s4 \n");
return false;
}
if (nSearchCount < 0)
{
printf("s5 \n");
return false;
}
if (stepCount < 0)
{
printf("s6 \n");
return false;
}
if (nLimit < 0)
{
printf("s7 \n");
return false;
}
return true;
}
};
struct Line
{
cv::Point p1;
cv::Point p2;
Line()
{
p1 = cv::Point(0, 0);
p2 = cv::Point(0, 0);
}
};
struct QX_Result
{
cv::Rect roi_src;
int area_pixel;
QX_Result()
{
roi_src = cv::Rect(0, 0, 0, 0);
area_pixel = 0;
}
};
// 检测小区域的信息
struct Det_ROI_Config
{
cv::Rect roi;
std::vector<cv::Point> plist;
};
struct Algin_Result
{
cv::Rect corpRoi;
int offtx;
int offty;
cv::Mat H;
Algin_Result()
{
Init();
}
void Init()
{
corpRoi = cv::Rect(0, 0, 0, 0);
offtx = 0;
offty = 0;
if (!H.empty())
{
H.release();
}
}
/* data */
};
// 检测参数和结果
struct DetConfigResult
{
BaseCheckFunction *pBaseCheckFunction;
std::string strChannel;
std::vector<QX_Result> qx_result;
std::vector<Det_ROI_Config> edge_det_roi;
Algin_Result alginResult;
std::vector<cv::Point> Det_region;
bool bSaveResultImg;
DetConfigResult()
{
Init();
}
void Init()
{
pBaseCheckFunction = NULL;
strChannel = "";
qx_result.clear();
edge_det_roi.clear();
alginResult.Init();
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,
};
public:
bool GetSegmentIntersection(const Line &l1, const Line &l2, cv::Point2f &intersection);
Edge_QX_Det(/* args */);
~Edge_QX_Det();
int Detect(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
// 边缘点搜索函数
int GetEdgePoint(const cv::Mat &img, Edge_Search_Config *pEdge_Search_Config, std::vector<cv::Point> &pointList);
int GetLine(const cv::Mat &img, std::vector<cv::Point> &pointList, int lineNum, int xory, std::vector<Line> &lineList);
// 检测缺陷
int Det_qx(const cv::Mat &img, std::vector<Det_ROI_Config> roilist, Det_ROI_Type type, DetConfigResult *pDetConfig);
int applyMaskInROI(const cv::Mat &grayImg, const Det_ROI_Config &config, cv::Mat &result, int threshold);
// 通过手绘的方式来检测
int Draw_Det(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
/// @brief
/// @param img 搜到图片 单通道
/// @param DirectSign 搜索方向 >0 正向,< 0 反向
/// @param Gate 阈值
/// @param BorW 搜索黑点 = 0还是白点 = 1
/// @param roi 搜索范围
/// @param StepCount 搜索点数
/// @param Limit 最小满是阈值点个数算上搜索成功
/// @return <0 搜索错误, >=0表示 搜索位置
int UDNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit);
/// @brief
/// @param img 搜到图片 单通道
/// @param DirectSign 搜索方向 >0 正向,< 0 反向
/// @param Gate 阈值
/// @param BorW 搜索黑点 = 0还是白点 = 1
/// @param roi 搜索范围
/// @param StepCount 搜索点数
/// @param Limit 最小满是阈值点个数算上搜索成功
/// @return <0 搜索错误, >=0表示 搜索位置
int LRNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit);
// int LRNoiseEdgeDetect(cv::Mat img,int DirectSign, int Gate,int BorW, int StartSearchSite, int Step, int StepCount, int top, int bottom, int Limit, int Depth, int MaxLimit);
private:
cv::Mat showimg;
bool bshowimg;
private:
/* data */
};
#endif

@ -31,7 +31,7 @@
#include "ImageDetConfig.h"
#include "OtherDetect.h"
#include "Define_Error.h"
#include "Edge_QX_Det.h"
#include "Pin_QX_Det.h"
#include "AI_Edge_Algin.h"
#include "AI_Factory.h"
#include "ImageAllResult.h"
@ -189,7 +189,7 @@ private:
int UpdateImgageScale();
// 边缘缺陷检测
int Edge_Qx_Det(const cv::Mat &img);
int Pin_Qx_Det(const cv::Mat &img);
// 把blob 汇总成 检测结果。
int BLobToDetResult();
@ -256,8 +256,8 @@ private:
// 边缘定位结果
std::shared_ptr<AI_Edge_Algin::Edge_AI_Result> m_pEdge_Align_Result;
Edge_QX_Det m_Edge_QX_Det;
Edge_QX_Det::DetConfigResult m_Edge_DetConfig;
Pin_QX_Det m_Pin_QX_Det;
Pin_QX_Det::DetConfigResult m_Edge_DetConfig;
std::vector<QXImageResult> m_Draw_qxImageResult; // 缺陷小图结果
std::vector<cv::Rect> SmallRoiList;

@ -0,0 +1,213 @@
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-13 16:05:08
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Pin_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
* @Author: xiewenji 527774126@qq.com
* @Date: 2025-08-04 21:26:32
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-04 21:29:05
* @FilePath: /BOE_CELL_AOI/AlgorithmModule/include/Pin_QX_Det.h
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
//实现对部分缺陷 需要进行 数量 和距离上分析的
*/
#ifndef Pin_QX_Det_H_
#define Pin_QX_Det_H_
#include <opencv2/opencv.hpp>
#include <opencv2/opencv.hpp>
#include "CheckUtil.hpp"
#include "OtherDetBaseDefine.h"
#include "CheckErrorCodeDefine.hpp"
#include "ImageDetConfig.h"
#include "CheckConfigDefine.h"
#include "ImageStorage.h"
#include "AI_Factory.h"
#include "DetLog.h"
using namespace std;
using namespace cv;
// Pin脚缺陷检测
class Pin_QX_Det
{
public:
struct QX_Result
{
cv::Rect roi_src;
int area_pixel;
QX_Result()
{
roi_src = cv::Rect(0, 0, 0, 0);
area_pixel = 0;
}
};
struct Det_ROI_Config
{
cv::Rect roi;
std::vector<cv::Point> plist;
};
// 检测参数和结果
struct DetConfigResult
{
BaseCheckFunction *pBaseCheckFunction;
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;
DetConfigResult()
{
Init();
}
void Init()
{
pBaseCheckFunction = NULL;
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;
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;
}
};
public:
Pin_QX_Det(std::shared_ptr<DetLog>& log_ref);
~Pin_QX_Det();
int Detect(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
int InitModel_Pin();
int creatsavedir();
private:
bool m_bInitSucc; // 是否初始化成功
// 检测结果
std::shared_ptr<Pin_AI_Result> m_pCheckResult_Pin;
std::shared_ptr<DetLog>& m_pdetlog;
bool m_bInitialized;
bool m_bModelSucc;
bool m_bModel_Mark_Succ;
bool m_bshowimg;
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;
private:
/* data */
};
#endif

@ -332,22 +332,22 @@ int AI_Edge_Algin::InitModel_ALL()
int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDetConfig, std::string strChannel, cv::RotatedRect &Roi)
{
std::shared_ptr<AIModel_Base> pCELL_Align_Outer;
std::shared_ptr<AIModel_Base> pSocket_Align;
switch (AIModel_type)
{
case 0:
pCELL_Align_Outer = AI_Factory->Align_Outer;
pSocket_Align = AI_Factory->Align_Outer;
break;
case 1:
pCELL_Align_Outer = AI_Factory->Align_Inner;
pSocket_Align = AI_Factory->Align_Inner;
break;
default:
pCELL_Align_Outer = AI_Factory->Align_Outer;
pSocket_Align = AI_Factory->Align_Outer;
break;
}
cv::Size sz;
sz.width = pCELL_Align_Outer->input_0.width;
sz.height = pCELL_Align_Outer->input_0.height;
sz.width = pSocket_Align->input_0.width;
sz.height = pSocket_Align->input_0.height;
cv::Mat detImg;
cout<< pDetConfig->strChannel << ": " << "---Get_Edge-resize-" << to_string(AIModel_type) <<"-- ";
cout << "imgSize: " << img.size() << ", " << "detImgSize: " << detImg.size() << ", " << "szSize: " << sz << endl;
@ -360,7 +360,7 @@ int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDe
cv::cvtColor(detImg, detImg, cv::COLOR_RGB2GRAY);
}
re = pCELL_Align_Outer->AIDet(detImg, mask);
re = pSocket_Align->AIDet(detImg, mask);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge_%d----error %d ", AIModel_type, re);
@ -387,7 +387,7 @@ int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDe
}
}
// if (m_pDetConfig->bSaveResultImg)
if (m_pDetConfig->bSaveResultImg)
{
cv::imwrite(strChannel +"_edge_"+ to_string(AIModel_type) +"_in.png", detImg);
cv::imwrite(strChannel +"_edge_"+ to_string(AIModel_type) +"_out_mask.png", mask);

File diff suppressed because it is too large Load Diff

@ -20,6 +20,7 @@ static bool compareContourAreas(const vector<Point> &contour1, const vector<Poin
}
ImgCheckAnalysisy::ImgCheckAnalysisy()
: m_pAI_Edge_Algin(m_pdetlog)
, m_Pin_QX_Det(m_pdetlog)
{
m_nErrorCode = CHECK_OK;
@ -702,9 +703,9 @@ int ImgCheckAnalysisy::CheckRun()
/*实现PIN脚检测*/
{
long t41 = CheckUtil::getcurTime();
int reedge1111 = Edge_Qx_Det(m_pImageAllResult->detImg);
int reedge1111 = Pin_Qx_Det(m_pImageAllResult->detImg);
long t42 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "4、detect", "-------------------------1、Edge_Qx_Det--------%ld-------\n", t42 - t41);
m_pdetlog->AddCheckstr(PrintLevel_0, "4、detect", "-------------------------1、Pin_Qx_Det--------%ld-------\n", t42 - t41);
}
m_CheckResult_shareP->nresult = 0;
@ -1892,7 +1893,7 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
// 要绘制结果
if (m_pbaseCheckFunction && m_pbaseCheckFunction->edgeDet.bDrawResult)
{
for (const auto &r : m_Edge_DetConfig.edge_det_roi)
for (const auto &r : m_Edge_DetConfig.pin_det_roi)
{
cv::Rect droi;
droi.x = r.roi.x * fs_resize_x;
@ -2022,27 +2023,20 @@ int ImgCheckAnalysisy::UpdateImgageScale()
return 0;
}
int ImgCheckAnalysisy::Edge_Qx_Det(const cv::Mat &img)
int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
{
m_Edge_DetConfig.Init();
m_Edge_DetConfig.strChannel = m_strCurDetChannel;
m_Edge_DetConfig.pBaseCheckFunction = m_pbaseCheckFunction;
m_Edge_DetConfig.alginResult.corpRoi = m_Crop_Roi_paramImg;
if (m_pEdge_Align_Result && m_pEdge_Align_Result->buseOfft)
{
m_Edge_DetConfig.alginResult.offtx = m_pEdge_Align_Result->offt_x;
m_Edge_DetConfig.alginResult.offty = m_pEdge_Align_Result->offt_y;
m_Edge_DetConfig.alginResult.H = m_pEdge_Align_Result->H.clone();
}
m_Edge_DetConfig.bSaveResultImg = false;
if (DetImgInfo_shareP->bsaveProcessImg)
{
m_Edge_DetConfig.bSaveResultImg = true;
}
// m_pbaseCheckFunction->print("Edge_Qx_Det");
int re = m_Edge_QX_Det.Detect(img, &m_Edge_DetConfig);
// m_pbaseCheckFunction->print("Pin_Qx_Det");
int re = m_Pin_QX_Det.Detect(img, &m_Edge_DetConfig);
if (re == 0)
{
for (const auto r : m_Edge_DetConfig.qx_result)
@ -2106,12 +2100,12 @@ int ImgCheckAnalysisy::Edge_Qx_Det(const cv::Mat &img)
m_pDetResult->pQx_ErrorList->push_back(temerror);
}
m_pdetlog->AddCheckstr(PrintLevel_1, "Edge_Qx_Det", " succ qx num %ld", m_Edge_DetConfig.qx_result.size());
m_pdetlog->AddCheckstr(PrintLevel_1, "Pin_Qx_Det", " succ qx num %ld", m_Edge_DetConfig.qx_result.size());
// 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
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Edge_Qx_Det", " error %d", re);
m_pdetlog->AddCheckstr(PrintLevel_1, "Pin_Qx_Det", " error %d", re);
}
return 0;

@ -0,0 +1,97 @@
#include "Pin_QX_Det.h"
#include "CheckUtil.hpp"
#include <numeric>
#include <random>
#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)
: 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;
m_pImageStorage = ImageStorage::getInstance();
AI_Factory = AIFactory::GetInstance();
}
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;
}
std::shared_ptr<AIModel_Base> pSocket_Pin;
pSocket_Pin = AI_Factory->Pin_Loc;
cv::Size sz;
sz.width = pSocket_Pin->input_0.width;
sz.height = pSocket_Pin->input_0.height;
cv::Mat detImg;
cout<< pDetConfig->strChannel << ": " << "---Pin---";
cout << "imgSize: " << img.size() << ", " << "detImgSize: " << detImg.size() << ", " << "szSize: " << sz << endl;
cv::resize(img, detImg, sz);
int re = 0;
cv::Mat mask;
if (detImg.channels() != 1)
{
cv::cvtColor(detImg, detImg, cv::COLOR_RGB2GRAY);
}
re = pSocket_Pin->AIDet(detImg, mask);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge----error %d ", re);
int re123 = 100 + re;
return re123;
}
if (pDetConfig->pBaseCheckFunction->saveImg.bSaveAlginImg)
{
}
if (pDetConfig->bSaveResultImg)
{
cv::imwrite(pDetConfig->strChannel +"_pin_" +"in.png", detImg);
cv::imwrite(pDetConfig->strChannel +"_pin_" +"out_mask.png", mask);
}
if (m_bshowimg)
{
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
}
return 0;
}

@ -849,7 +849,7 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
_config.markLine.Init();
}
}
if ("Edge_QX_Detect" == strCode)
if ("Pin_QX_Detect" == strCode)
{
auto value_f = value;
// std::cout << value_f << std::endl;

Loading…
Cancel
Save