|
|
|
@ -25,7 +25,7 @@
|
|
|
|
#define HANDLE_SIZE_MAX_RATIO 1.2f
|
|
|
|
#define HANDLE_SIZE_MAX_RATIO 1.2f
|
|
|
|
// "附近"的搜索范围:把手区域外接矩形在宽/高方向各外扩该比例
|
|
|
|
// "附近"的搜索范围:把手区域外接矩形在宽/高方向各外扩该比例
|
|
|
|
#define HANDLE_NEAR_EXPAND_RATIO 5
|
|
|
|
#define HANDLE_NEAR_EXPAND_RATIO 5
|
|
|
|
// 把手缺失检测开关见 Base层 Function_Support_Det::bDetHandle(CheckConfigDefine.h)
|
|
|
|
// 把手缺失检测开关见 Function_Support_Det::bDetHandle(CheckConfigDefine.h)
|
|
|
|
|
|
|
|
|
|
|
|
// 用于排序轮廓的比较函数
|
|
|
|
// 用于排序轮廓的比较函数
|
|
|
|
static bool compareContourAreas(const vector<Point> &contour1, const vector<Point> &contour2)
|
|
|
|
static bool compareContourAreas(const vector<Point> &contour1, const vector<Point> &contour2)
|
|
|
|
@ -723,6 +723,7 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
long time_edge_s = CheckUtil::getcurTime();
|
|
|
|
long time_edge_s = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
|
|
|
|
m_pFuntion = GetChannelFuntion(m_strCurDetChannel);
|
|
|
|
m_pFuntion = GetChannelFuntion(m_strCurDetChannel);
|
|
|
|
|
|
|
|
int nfunction = 0;
|
|
|
|
if (m_pFuntion != NULL)
|
|
|
|
if (m_pFuntion != NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Detect function", "%s",
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Detect function", "%s",
|
|
|
|
@ -730,8 +731,12 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 通道层允许为空(仅打印,不再按错误处理)
|
|
|
|
nfunction = 1;
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Detect function", "no channel config, use base function only");
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Error", "m_pFuntion is NULL");
|
|
|
|
|
|
|
|
PublishAlignShare(false); // 本图不会产出定位结果,通知可能的等待方(暗场复用)
|
|
|
|
|
|
|
|
m_nErrorCode = 22;
|
|
|
|
|
|
|
|
m_nCheckResultErrorCode = m_nErrorCode;
|
|
|
|
|
|
|
|
return m_nErrorCode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*AI 边缘定位(内外边缘)*/
|
|
|
|
/*AI 边缘定位(内外边缘)*/
|
|
|
|
@ -759,7 +764,7 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 标签检测(独立步骤):暗场图像 + 明场 bigmask(不再沿用明场检出的标签);bDetTag 关闭时跳过
|
|
|
|
// 标签检测(独立步骤):暗场图像 + 明场 bigmask(不再沿用明场检出的标签);bDetTag 关闭时跳过
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (m_pbaseCheckFunction->supportDet.bDetTag)
|
|
|
|
if (m_pFuntion->function.f_supportDet.bDetTag)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
long tag_s = CheckUtil::getcurTime();
|
|
|
|
long tag_s = CheckUtil::getcurTime();
|
|
|
|
int reTag = CheckTagByBigMask(m_CheckResult_shareP->in_shareImage->img, m_pEdge_Align_Result->bigmask);
|
|
|
|
int reTag = CheckTagByBigMask(m_CheckResult_shareP->in_shareImage->img, m_pEdge_Align_Result->bigmask);
|
|
|
|
@ -890,9 +895,8 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
3、按 edge_select 指定方向(left/right/up/down)计算 rs 中心到 rp 对应边缘的距离
|
|
|
|
3、按 edge_select 指定方向(left/right/up/down)计算 rs 中心到 rp 对应边缘的距离
|
|
|
|
4、计算值与标准值(x_standard/y_standard)做差取平均,平均差超过 offset(x_offset) → 偏移 */
|
|
|
|
4、计算值与标准值(x_standard/y_standard)做差取平均,平均差超过 offset(x_offset) → 偏移 */
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Function_Support_Det &supportDet = m_pbaseCheckFunction->supportDet;
|
|
|
|
Function_Support_Det &supportDet = m_pFuntion->function.f_supportDet;
|
|
|
|
m_SupportDrawInfo.Reset(); // 清空本帧绘制信息(未开启/计算无效时不绘制)
|
|
|
|
if (supportDet.bOpen && supportDet.bDetSupport)
|
|
|
|
if (supportDet.bDetSupport)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const cv::Mat &bigmask = m_pEdge_Align_Result->bigmask;
|
|
|
|
const cv::Mat &bigmask = m_pEdge_Align_Result->bigmask;
|
|
|
|
const cv::Mat &smallmask = m_pEdge_Align_Result->smallmask;
|
|
|
|
const cv::Mat &smallmask = m_pEdge_Align_Result->smallmask;
|
|
|
|
@ -1009,15 +1013,6 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
float fDiff = fabs(fDist - fStandard);
|
|
|
|
float fDiff = fabs(fDist - fStandard);
|
|
|
|
fSumDiff += fDiff;
|
|
|
|
fSumDiff += fDiff;
|
|
|
|
nDiffNum++;
|
|
|
|
nDiffNum++;
|
|
|
|
// 记录该方向绘制信息:|实测-标准|超限差(x_offset)则绘制为红色
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Support_Draw_Info_::Edge_Draw_ edgeDraw;
|
|
|
|
|
|
|
|
edgeDraw.strEdge = strEdge;
|
|
|
|
|
|
|
|
edgeDraw.fDist = fDist;
|
|
|
|
|
|
|
|
edgeDraw.fStandard = fStandard;
|
|
|
|
|
|
|
|
edgeDraw.bExceed = (fDiff > supportDet.x_offset);
|
|
|
|
|
|
|
|
m_SupportDrawInfo.edgeList.push_back(edgeDraw);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(strTmp, "%s(%.1f/%.1f) ", strEdge.c_str(), fDist, fStandard);
|
|
|
|
sprintf(strTmp, "%s(%.1f/%.1f) ", strEdge.c_str(), fDist, fStandard);
|
|
|
|
strSelect += strTmp;
|
|
|
|
strSelect += strTmp;
|
|
|
|
sprintf(strTmp, "%.1f ", fDiff);
|
|
|
|
sprintf(strTmp, "%.1f ", fDiff);
|
|
|
|
@ -1027,13 +1022,6 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
float fAvgDiff = (nDiffNum > 0) ? (fSumDiff / nDiffNum) : 0.0f;
|
|
|
|
float fAvgDiff = (nDiffNum > 0) ? (fSumDiff / nDiffNum) : 0.0f;
|
|
|
|
bool bOffset = (nDiffNum > 0) && (fAvgDiff > supportDet.x_offset);
|
|
|
|
bool bOffset = (nDiffNum > 0) && (fAvgDiff > supportDet.x_offset);
|
|
|
|
|
|
|
|
|
|
|
|
// 记录绘制信息(DrawResult_Step_1 用):支架中心十字 + 各方向距离
|
|
|
|
|
|
|
|
m_SupportDrawInfo.bValid = true;
|
|
|
|
|
|
|
|
m_SupportDrawInfo.bOffset = bOffset;
|
|
|
|
|
|
|
|
m_SupportDrawInfo.rpRect = rpRect;
|
|
|
|
|
|
|
|
m_SupportDrawInfo.rsRect = rsRect;
|
|
|
|
|
|
|
|
m_SupportDrawInfo.ptCenter = cv::Point2f(fCx, fCy);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "支架检测",
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "支架检测",
|
|
|
|
"rp [%d %d %d %d] rs [%d %d %d %d] scale (%.4f %.4f) center (%.1f %.1f) dL %.1f dR %.1f dT %.1f dB %.1f | select %s diff %s avgDiff %.1f limit %.1f ng %d",
|
|
|
|
"rp [%d %d %d %d] rs [%d %d %d %d] scale (%.4f %.4f) center (%.1f %.1f) dL %.1f dR %.1f dT %.1f dB %.1f | select %s diff %s avgDiff %.1f limit %.1f ng %d",
|
|
|
|
rpRect.x, rpRect.y, rpRect.width, rpRect.height,
|
|
|
|
rpRect.x, rpRect.y, rpRect.width, rpRect.height,
|
|
|
|
@ -1150,7 +1138,7 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
|
|
|
|
|
|
|
|
/* Tag检测(bDetTag 关闭时不上报标签 NG) */
|
|
|
|
/* Tag检测(bDetTag 关闭时不上报标签 NG) */
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!m_pbaseCheckFunction->supportDet.bDetTag)
|
|
|
|
if (!m_pFuntion->function.f_supportDet.bDetTag)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_tag_roiList.clear();
|
|
|
|
m_tag_roiList.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -2057,16 +2045,6 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
|
|
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
|
|
if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg && !ResultImg.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string strSaveDir = "/home/aidlux/BOE/AI_Detect/KK/" + DetImgInfo_shareP->strImgProductID + "/";
|
|
|
|
|
|
|
|
CheckUtil::CreateDir(strSaveDir);
|
|
|
|
|
|
|
|
std::string strSavePath_in = strSaveDir + m_strCurDetChannel + "_in.png";
|
|
|
|
|
|
|
|
std::string strSavePath_out = strSaveDir + m_strCurDetChannel + "_out.png";
|
|
|
|
|
|
|
|
cv::imwrite(strSavePath_in, inputImg);
|
|
|
|
|
|
|
|
cv::imwrite(strSavePath_out, ResultImg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 临时存图
|
|
|
|
// 临时存图
|
|
|
|
if (DetImgInfo_shareP->bsaveProcessImg)
|
|
|
|
if (DetImgInfo_shareP->bsaveProcessImg)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -2360,7 +2338,21 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 注:不再绘制 inner 定位蓝色框(m_inner_rroi 为大轮廓裁剪子图局部坐标,直接映射会缺裁剪原点偏移)
|
|
|
|
// 绘制m_inner_rroi(蓝色),原图坐标 -> 检测图(裁剪) -> 结果图
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
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::Point2f detPt = MatAffinePoint(m_matSrc2Det, vertices[i]);
|
|
|
|
|
|
|
|
draw_pts.emplace_back(cvRound(detPt.x * fs_resize_x),
|
|
|
|
|
|
|
|
cvRound(detPt.y * fs_resize_y));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::polylines(m_CheckResult_shareP->resultimg, draw_pts, true,
|
|
|
|
|
|
|
|
CheckUtil::GetDrawColor(m_CheckResult_shareP->resultimg, cv::Scalar(255, 0, 0)), 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_pbaseCheckFunction && m_pbaseCheckFunction->markLine.region.size() > 1)
|
|
|
|
if (m_pbaseCheckFunction && m_pbaseCheckFunction->markLine.region.size() > 1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -2403,63 +2395,6 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 支架偏移检测绘制:支架中心十字(绿=正常/红=偏移NG)+ 支架到边缘的距离(绿=正常/红=超标准)
|
|
|
|
|
|
|
|
if (m_SupportDrawInfo.bValid && !m_CheckResult_shareP->resultimg.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 支架中心:原图坐标 -> 检测图(裁剪) -> 结果图
|
|
|
|
|
|
|
|
cv::Point2f detPt = MatAffinePoint(m_matSrc2Det, m_SupportDrawInfo.ptCenter);
|
|
|
|
|
|
|
|
cv::Point pCenter(cvRound(detPt.x * fs_resize_x), cvRound(detPt.y * fs_resize_y));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 支架中心十字:NG 红色 / 正常绿色
|
|
|
|
|
|
|
|
cv::Scalar colorCross = m_SupportDrawInfo.bOffset ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0);
|
|
|
|
|
|
|
|
colorCross = CheckUtil::GetDrawColor(m_CheckResult_shareP->resultimg, colorCross);
|
|
|
|
|
|
|
|
const int nCrossLen = 40; // 结果图上十字半长(px)
|
|
|
|
|
|
|
|
cv::line(m_CheckResult_shareP->resultimg, cv::Point(pCenter.x - nCrossLen, pCenter.y), cv::Point(pCenter.x + nCrossLen, pCenter.y), colorCross, 2);
|
|
|
|
|
|
|
|
cv::line(m_CheckResult_shareP->resultimg, cv::Point(pCenter.x, pCenter.y - nCrossLen), cv::Point(pCenter.x, pCenter.y + nCrossLen), colorCross, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 支架到边缘的距离:中心 -> 产品区域对应边缘连线 + 实测/标准(像素)文字
|
|
|
|
|
|
|
|
char strTxt[64];
|
|
|
|
|
|
|
|
for (size_t i = 0; i < m_SupportDrawInfo.edgeList.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const Support_Draw_Info_::Edge_Draw_ &edgeDraw = m_SupportDrawInfo.edgeList[i];
|
|
|
|
|
|
|
|
cv::Point2f ptEdge = m_SupportDrawInfo.ptCenter;
|
|
|
|
|
|
|
|
if (edgeDraw.strEdge == "left")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ptEdge.x = (float)m_SupportDrawInfo.rpRect.x;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (edgeDraw.strEdge == "right")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ptEdge.x = (float)(m_SupportDrawInfo.rpRect.x + m_SupportDrawInfo.rpRect.width);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (edgeDraw.strEdge == "up")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ptEdge.y = (float)m_SupportDrawInfo.rpRect.y;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (edgeDraw.strEdge == "down")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ptEdge.y = (float)(m_SupportDrawInfo.rpRect.y + m_SupportDrawInfo.rpRect.height);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Point2f detEdge = MatAffinePoint(m_matSrc2Det, ptEdge);
|
|
|
|
|
|
|
|
cv::Point pEdge(cvRound(detEdge.x * fs_resize_x), cvRound(detEdge.y * fs_resize_y));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 超标准红色 / 正常绿色
|
|
|
|
|
|
|
|
cv::Scalar colorEdge = edgeDraw.bExceed ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0);
|
|
|
|
|
|
|
|
colorEdge = CheckUtil::GetDrawColor(m_CheckResult_shareP->resultimg, colorEdge);
|
|
|
|
|
|
|
|
cv::line(m_CheckResult_shareP->resultimg, pCenter, pEdge, colorEdge, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 距离文字:实测/标准(原图像素)
|
|
|
|
|
|
|
|
snprintf(strTxt, sizeof(strTxt), "%s %.0f/%.0f", edgeDraw.strEdge.c_str(), edgeDraw.fDist, edgeDraw.fStandard);
|
|
|
|
|
|
|
|
cv::putText(m_CheckResult_shareP->resultimg, strTxt,
|
|
|
|
|
|
|
|
cv::Point((pCenter.x + pEdge.x) / 2 + 6, (pCenter.y + pEdge.y) / 2 - 6),
|
|
|
|
|
|
|
|
cv::FONT_HERSHEY_SIMPLEX, 0.8, colorEdge, 2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// cv::imwrite("sss.png", m_CheckResult_shareP->resultimg);
|
|
|
|
// cv::imwrite("sss.png", m_CheckResult_shareP->resultimg);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -2601,8 +2536,7 @@ int ImgCheckAnalysisy::AI_Edge(const cv::Mat &img, cv::RotatedRect &outerRoi, cv
|
|
|
|
}
|
|
|
|
}
|
|
|
|
config.strChannel = DetImgInfo_shareP->strChannel;
|
|
|
|
config.strChannel = DetImgInfo_shareP->strChannel;
|
|
|
|
config.pBaseCheckFunction = m_pbaseCheckFunction;
|
|
|
|
config.pBaseCheckFunction = m_pbaseCheckFunction;
|
|
|
|
config.bDetTag = m_pbaseCheckFunction->supportDet.bDetTag; // 标签检测开关:关闭时不跑 Tag_Loc
|
|
|
|
config.bDetTag = m_pFuntion->function.f_supportDet.bDetTag; // 标签检测开关:关闭时不跑 Tag_Loc
|
|
|
|
config.strProductID = DetImgInfo_shareP->strImgProductID; // 定位存图文件名首位使用产品ID
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 定位获取三个roi */
|
|
|
|
/* 定位获取三个roi */
|
|
|
|
int re = m_pAI_Edge_Algin.Detect(img, &config, m_pEdge_Align_Result);
|
|
|
|
int re = m_pAI_Edge_Algin.Detect(img, &config, m_pEdge_Align_Result);
|
|
|
|
@ -2664,9 +2598,9 @@ int ImgCheckAnalysisy::CheckHandleByBigMask(const cv::Mat &bigmask)
|
|
|
|
// 2、把手检测开关 + 把手区域(最多4个,非空区域表示该处应该有一个把手)
|
|
|
|
// 2、把手检测开关 + 把手区域(最多4个,非空区域表示该处应该有一个把手)
|
|
|
|
bool bDetHandle = false;
|
|
|
|
bool bDetHandle = false;
|
|
|
|
std::vector<cv::Rect> regionBoxList;
|
|
|
|
std::vector<cv::Rect> regionBoxList;
|
|
|
|
if (m_pbaseCheckFunction != NULL)
|
|
|
|
if (m_pFuntion != NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const Function_Support_Det &supportDet = m_pbaseCheckFunction->supportDet;
|
|
|
|
const Function_Support_Det &supportDet = m_pFuntion->function.f_supportDet;
|
|
|
|
bDetHandle = supportDet.bDetHandle;
|
|
|
|
bDetHandle = supportDet.bDetHandle;
|
|
|
|
for (size_t i = 0; i < supportDet.handleBoxes.size() && i < HANDLE_REGION_MAX_NUM; i++)
|
|
|
|
for (size_t i = 0; i < supportDet.handleBoxes.size() && i < HANDLE_REGION_MAX_NUM; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|