update 优化支架边缘和绘制

dev_lsy
liusiyang 3 weeks ago
parent b36ffffda6
commit ec5933dba1

@ -77,11 +77,17 @@ struct Support_Draw_Info_
float fDist; // 实测距离(原图像素) float fDist; // 实测距离(原图像素)
float fStandard; // 标准距离(原图像素) float fStandard; // 标准距离(原图像素)
bool bExceed; // |fDist-fStandard| 超限差(x_offset) -> 红色 bool bExceed; // |fDist-fStandard| 超限差(x_offset) -> 红色
cv::Point2f ptEdge; // 连线端点:所计算边缘上、支架中心行/列处的点(原图坐标)
cv::Point2f ptEdgeA; // 所计算边缘线段端点A(原图坐标)
cv::Point2f ptEdgeB; // 所计算边缘线段端点B(原图坐标)
Edge_Draw_() Edge_Draw_()
{ {
fDist = 0.0f; fDist = 0.0f;
fStandard = 0.0f; fStandard = 0.0f;
bExceed = false; bExceed = false;
ptEdge = cv::Point2f(0.0f, 0.0f);
ptEdgeA = cv::Point2f(0.0f, 0.0f);
ptEdgeB = cv::Point2f(0.0f, 0.0f);
} }
}; };
bool bValid; // 本次是否有效计算出支架偏移几何 bool bValid; // 本次是否有效计算出支架偏移几何
@ -377,6 +383,7 @@ private:
// 把手检测结果(从 outer 定位 mask 分离的凸起区域 + 各把手区域判定结果) // 把手检测结果(从 outer 定位 mask 分离的凸起区域 + 各把手区域判定结果)
std::vector<Mask_Protrusion_> m_HandleProtrusionList; // 分离出的凸起区域(把手候选:roi/质心/深度/就近角等) std::vector<Mask_Protrusion_> m_HandleProtrusionList; // 分离出的凸起区域(把手候选:roi/质心/深度/就近角等)
std::vector<Handle_Region_Result_> m_HandleRegionResultList; // 各把手区域(最多4个)的判定结果 std::vector<Handle_Region_Result_> m_HandleRegionResultList; // 各把手区域(最多4个)的判定结果
std::vector<cv::Point2f> m_HandleBodyQuad; // 拟合出的主体四边形(TL/TR/BR/BL,原图坐标;支架偏移检测复用其四边抗凸起)
bool m_bHandleDetSucc; // 本次是否完成把手检测 bool m_bHandleDetSucc; // 本次是否完成把手检测
bool m_bHandleFound; // 所有非空把手区域是否都找到了把手 bool m_bHandleFound; // 所有非空把手区域是否都找到了把手
bool m_bHandleExpect; // 是否开启了把手缺失检测(且有非空把手区域) bool m_bHandleExpect; // 是否开启了把手缺失检测(且有非空把手区域)

@ -1070,9 +1070,11 @@ int ImgCheckAnalysisy::CheckRun()
/* 检测支架偏移(bDetSupport 开关关闭时不做支架判定) /* 检测支架偏移(bDetSupport 开关关闭时不做支架判定)
不使用参数绘制区域,结合两次定位的 mask 计算: 不使用参数绘制区域,结合两次定位的 mask 计算:
1、bigmask 最大连通域 = 产品区域 rp(近似矩形,四周可能有凸起) 1、产品边缘:优先复用把手提取对 bigmask 做的"四边抗凸起拟合"主体四边形
(CheckHandleByBigMask -> GetMaskProtrusions;边缘上的凸起(把手等)不会把边缘带偏),
拟合不可用/无效时回退 bigmask 最大连通域外接矩形 rp(近似矩形,四周可能有凸起)
2、smallmask 最大连通域 = 支架区域 rs(按定位裁剪区 m_outer_rroi 外接矩形映射回原图坐标) 2、smallmask 最大连通域 = 支架区域 rs(按定位裁剪区 m_outer_rroi 外接矩形映射回原图坐标)
3、按 edge_select 指定方向(left/right/up/down)计算 rs 中心到 rp 对应边缘的距离 3、按 edge_select 指定方向(left/right/up/down)计算 rs 中心到产品对应边缘的距离
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_pbaseCheckFunction->supportDet;
@ -1132,7 +1134,7 @@ int ImgCheckAnalysisy::CheckRun()
} }
else else
{ {
// rp 边缘:产品最大连通域的外接矩形(含凸起) // rp 边缘(拟合不可用时的回退):产品最大连通域的外接矩形(含凸起)
cv::Rect rpRect = cv::boundingRect(rpContour); cv::Rect rpRect = cv::boundingRect(rpContour);
// rs 映射回原图坐标:smallmask 对应定位时裁剪的大轮廓区域(m_outer_rroi 外接矩形),按比例映射 // rs 映射回原图坐标:smallmask 对应定位时裁剪的大轮廓区域(m_outer_rroi 外接矩形),按比例映射
@ -1146,18 +1148,87 @@ int ImgCheckAnalysisy::CheckRun()
cvRound(rsSmallRect.width * fx), cvRound(rsSmallRect.width * fx),
cvRound(rsSmallRect.height * fy)); cvRound(rsSmallRect.height * fy));
// 3、rs 中心到 rp 上下左右边缘的距离 // 3、产品边缘:优先复用把手提取对 bigmask 做的"四边抗凸起拟合"主体四边形
// (CheckHandleByBigMask -> GetMaskProtrusions 输出):边缘上的凸起(把手等)不会把边缘带偏;
// 拟合不可用/无效时回退到产品最大连通域外接矩形 rpRect(含凸起)
bool bFitQuad = false; // 是否用上了拟合主体四边形
float fDL = 0, fDR = 0, fDT = 0, fDB = 0; // 支架中心到产品左/右/上/下边缘的距离(原图像素,后乘缩放系数)
cv::Point2f ptEdgeArr[4]; // 连线端点(边缘线上):0 left 1 right 2 up 3 down
cv::Point2f ptSegAArr[4]; // 边缘线段端点A
cv::Point2f ptSegBArr[4]; // 边缘线段端点B
float fCx = rsRect.x + rsRect.width * 0.5f; float fCx = rsRect.x + rsRect.width * 0.5f;
float fCy = rsRect.y + rsRect.height * 0.5f; float fCy = rsRect.y + rsRect.height * 0.5f;
float fDL = fCx - rpRect.x; // 到左边缘 if (m_HandleBodyQuad.size() == 4)
float fDR = (rpRect.x + rpRect.width) - fCx; // 到右边缘 {
float fDT = fCy - rpRect.y; // 到上边缘 // 四边形角点顺序:左上/右上/右下/左下;左/右边 x=k*y+b、上/下边 y=k*x+b(与 GetMaskProtrusions 约定一致);
float fDB = (rpRect.y + rpRect.height) - fCy; // 到下边缘 // 边长过小说明拟合退化,不用
const cv::Point2f &ptTL = m_HandleBodyQuad[0];
const cv::Point2f &ptTR = m_HandleBodyQuad[1];
const cv::Point2f &ptBR = m_HandleBodyQuad[2];
const cv::Point2f &ptBL = m_HandleBodyQuad[3];
if (fabs(ptBL.y - ptTL.y) > 2.0f && fabs(ptBR.y - ptTR.y) > 2.0f &&
fabs(ptTR.x - ptTL.x) > 2.0f && fabs(ptBR.x - ptBL.x) > 2.0f)
{
float fKL = (ptBL.x - ptTL.x) / (ptBL.y - ptTL.y); // 左边 x = k*y + b
float fBL = ptTL.x - fKL * ptTL.y;
float fKR = (ptBR.x - ptTR.x) / (ptBR.y - ptTR.y); // 右边 x = k*y + b
float fBR = ptTR.x - fKR * ptTR.y;
float fKT = (ptTR.y - ptTL.y) / (ptTR.x - ptTL.x); // 上边 y = k*x + b
float fBT = ptTL.y - fKT * ptTL.x;
float fKB = (ptBR.y - ptBL.y) / (ptBR.x - ptBL.x); // 下边 y = k*x + b
float fBB = ptBL.y - fKB * ptBL.x;
// 连线端点:取边缘线在支架中心行/列上的点;长度即中心到边缘的水平/垂直距离
float fXEdgeL = fKL * fCy + fBL;
float fXEdgeR = fKR * fCy + fBR;
float fYEdgeT = fKT * fCx + fBT;
float fYEdgeB = fKB * fCx + fBB;
fDL = fCx - fXEdgeL;
fDR = fXEdgeR - fCx;
fDT = fCy - fYEdgeT;
fDB = fYEdgeB - fCy;
// 拟合有效性:支架中心应位于四条拟合边内侧(四个方向距离均为正),否则放弃拟合
if (fDL > 0 && fDR > 0 && fDT > 0 && fDB > 0)
{
ptEdgeArr[0] = cv::Point2f(fXEdgeL, fCy);
ptEdgeArr[1] = cv::Point2f(fXEdgeR, fCy);
ptEdgeArr[2] = cv::Point2f(fCx, fYEdgeT);
ptEdgeArr[3] = cv::Point2f(fCx, fYEdgeB);
ptSegAArr[0] = ptTL; ptSegBArr[0] = ptBL; // left:整条拟合左边
ptSegAArr[1] = ptTR; ptSegBArr[1] = ptBR; // right:整条拟合右边
ptSegAArr[2] = ptTL; ptSegBArr[2] = ptTR; // up:整条拟合上边
ptSegAArr[3] = ptBL; ptSegBArr[3] = ptBR; // down:整条拟合下边
bFitQuad = true;
}
}
}
if (!bFitQuad)
{
// 回退:产品区域外接矩形(含凸起)的四条边
fDL = fCx - rpRect.x;
fDR = (rpRect.x + rpRect.width) - fCx;
fDT = fCy - rpRect.y;
fDB = (rpRect.y + rpRect.height) - fCy;
ptEdgeArr[0] = cv::Point2f((float)rpRect.x, fCy);
ptEdgeArr[1] = cv::Point2f((float)(rpRect.x + rpRect.width), fCy);
ptEdgeArr[2] = cv::Point2f(fCx, (float)rpRect.y);
ptEdgeArr[3] = cv::Point2f(fCx, (float)(rpRect.y + rpRect.height));
ptSegAArr[0] = cv::Point2f((float)rpRect.x, (float)rpRect.y);
ptSegBArr[0] = cv::Point2f((float)rpRect.x, (float)(rpRect.y + rpRect.height));
ptSegAArr[1] = cv::Point2f((float)(rpRect.x + rpRect.width), (float)rpRect.y);
ptSegBArr[1] = cv::Point2f((float)(rpRect.x + rpRect.width), (float)(rpRect.y + rpRect.height));
ptSegAArr[2] = cv::Point2f((float)rpRect.x, (float)rpRect.y);
ptSegBArr[2] = cv::Point2f((float)(rpRect.x + rpRect.width), (float)rpRect.y);
ptSegAArr[3] = cv::Point2f((float)rpRect.x, (float)(rpRect.y + rpRect.height));
ptSegBArr[3] = cv::Point2f((float)(rpRect.x + rpRect.width), (float)(rpRect.y + rpRect.height));
}
// 像素 -> mm
fDL *= m_fImgage_Scale_X; fDL *= m_fImgage_Scale_X;
fDR *= m_fImgage_Scale_X; fDR *= m_fImgage_Scale_X;
fDT *= m_fImgage_Scale_Y; fDT *= m_fImgage_Scale_Y;
fDB *= m_fImgage_Scale_Y; fDB *= m_fImgage_Scale_Y;
float fDistArr[4] = {fDL, fDR, fDT, fDB}; // 顺序固定:0 left 1 right 2 up 3 down
// 4、按 edge_select 指定方向(left/right/up/down)取计算值,与标准值做差取平均,平均差超过 offset → 偏移 // 4、按 edge_select 指定方向(left/right/up/down)取计算值,与标准值做差取平均,平均差超过 offset → 偏移
// left/right 用 x_standard,up/down 用 y_standard;offset 用 x_offset // left/right 用 x_standard,up/down 用 y_standard;offset 用 x_offset
@ -1169,26 +1240,26 @@ int ImgCheckAnalysisy::CheckRun()
for (size_t iselect = 0; iselect < supportDet.edge_select.size(); iselect++) for (size_t iselect = 0; iselect < supportDet.edge_select.size(); iselect++)
{ {
const std::string &strEdge = supportDet.edge_select[iselect]; const std::string &strEdge = supportDet.edge_select[iselect];
float fDist = 0; int gi = -1; // 方向索引:0 left 1 right 2 up 3 down
float fStandard = 0; float fStandard = 0;
if (strEdge == "left") if (strEdge == "left")
{ {
fDist = fDL; gi = 0;
fStandard = supportDet.x_standard; fStandard = supportDet.x_standard;
} }
else if (strEdge == "right") else if (strEdge == "right")
{ {
fDist = fDR; gi = 1;
fStandard = supportDet.x_standard; fStandard = supportDet.x_standard;
} }
else if (strEdge == "up") else if (strEdge == "up")
{ {
fDist = fDT; gi = 2;
fStandard = supportDet.y_standard; fStandard = supportDet.y_standard;
} }
else if (strEdge == "down") else if (strEdge == "down")
{ {
fDist = fDB; gi = 3;
fStandard = supportDet.y_standard; fStandard = supportDet.y_standard;
} }
else else
@ -1196,6 +1267,7 @@ int ImgCheckAnalysisy::CheckRun()
continue; continue;
} }
float fDist = fDistArr[gi];
float fDiff = fabs(fDist - fStandard); float fDiff = fabs(fDist - fStandard);
fSumDiff += fDiff; fSumDiff += fDiff;
nDiffNum++; nDiffNum++;
@ -1206,6 +1278,9 @@ int ImgCheckAnalysisy::CheckRun()
edgeDraw.fDist = fDist; edgeDraw.fDist = fDist;
edgeDraw.fStandard = fStandard; edgeDraw.fStandard = fStandard;
edgeDraw.bExceed = (fDiff > supportDet.x_offset); edgeDraw.bExceed = (fDiff > supportDet.x_offset);
edgeDraw.ptEdge = ptEdgeArr[gi];
edgeDraw.ptEdgeA = ptSegAArr[gi];
edgeDraw.ptEdgeB = ptSegBArr[gi];
m_SupportDrawInfo.edgeList.push_back(edgeDraw); 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);
@ -1225,10 +1300,10 @@ int ImgCheckAnalysisy::CheckRun()
m_SupportDrawInfo.ptCenter = cv::Point2f(fCx, fCy); 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) edge %s quad %ld 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,
rsRect.x, rsRect.y, rsRect.width, rsRect.height, rsRect.x, rsRect.y, rsRect.width, rsRect.height,
fx, fy, fCx, fCy, fDL, fDR, fDT, fDB, fx, fy, fCx, fCy, bFitQuad ? "fitquad" : "rpbox", (long)m_HandleBodyQuad.size(), fDL, fDR, fDT, fDB,
strSelect.c_str(), strDiff.c_str(), fAvgDiff, supportDet.x_offset, bOffset); strSelect.c_str(), strDiff.c_str(), fAvgDiff, supportDet.x_offset, bOffset);
if (bOffset) if (bOffset)
@ -2618,56 +2693,47 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
} }
} }
// 支架偏移检测绘制(受参数 bDrawSupport 控制,默认关闭):支架中心十字(绿=正常/红=偏移NG)+ 支架到边缘的距离(绿=正常/红=超标准) // 支架偏移检测绘制(受参数 bDrawSupport 控制,默认关闭):
// 支架中心十字(绿=正常/红=偏移NG)+ 各方向"所计算的产品边缘"线段(抗凸起拟合直边,见 CheckRun 支架块)
// + 支架中心到该边缘的连线(连线长度=支架中心到所计算边缘的距离;绿=正常/红=超标准)+ 实测/标准(mm)文字
if (m_SupportDrawInfo.bValid && m_pbaseCheckFunction->supportDet.bDrawSupport && !m_CheckResult_shareP->resultimg.empty()) if (m_SupportDrawInfo.bValid && m_pbaseCheckFunction->supportDet.bDrawSupport && !m_CheckResult_shareP->resultimg.empty())
{ {
// 支架中心:原图坐标 -> 检测图(裁剪) -> 结果图 // 原图坐标 -> 检测图(裁剪) -> 结果图
cv::Point2f detPt = MatAffinePoint(m_matSrc2Det, m_SupportDrawInfo.ptCenter); auto srcToResult = [&](const cv::Point2f &pt) -> cv::Point {
cv::Point pCenter(cvRound(detPt.x * fs_resize_x), cvRound(detPt.y * fs_resize_y)); cv::Point2f detPt = MatAffinePoint(m_matSrc2Det, pt);
return cv::Point(cvRound(detPt.x * fs_resize_x), cvRound(detPt.y * fs_resize_y));
};
// 支架中心十字:NG 红色 / 正常绿色 // 支架中心十字:NG 红色 / 正常绿色
cv::Point pCenter = srcToResult(m_SupportDrawInfo.ptCenter);
cv::Scalar colorCross = m_SupportDrawInfo.bOffset ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0); cv::Scalar colorCross = m_SupportDrawInfo.bOffset ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0);
colorCross = CheckUtil::GetDrawColor(m_CheckResult_shareP->resultimg, colorCross); colorCross = CheckUtil::GetDrawColor(m_CheckResult_shareP->resultimg, colorCross);
const int nCrossLen = 40; // 结果图上十字半长(px) 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 - 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); cv::line(m_CheckResult_shareP->resultimg, cv::Point(pCenter.x, pCenter.y - nCrossLen), cv::Point(pCenter.x, pCenter.y + nCrossLen), colorCross, 2);
// 支架到边缘的距离:中心 -> 产品区域对应边缘连线 + 实测/标准(像素)文字 // 各方向:所计算边缘线段(抗凸起拟合直边/回退外接矩形边) + 中心到边缘点的连线(长度=点到所计算边缘) + 实测/标准文字
// 几何(边缘点/线段两端点)由 CheckRun 支架块算好存入 edgeDraw,此处只做坐标映射与绘制
char strTxt[64]; char strTxt[64];
for (size_t i = 0; i < m_SupportDrawInfo.edgeList.size(); i++) for (size_t i = 0; i < m_SupportDrawInfo.edgeList.size(); i++)
{ {
const Support_Draw_Info_::Edge_Draw_ &edgeDraw = m_SupportDrawInfo.edgeList[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 = srcToResult(edgeDraw.ptEdge);
cv::Point pEdge(cvRound(detEdge.x * fs_resize_x), cvRound(detEdge.y * fs_resize_y)); cv::Point pEdgeA = srcToResult(edgeDraw.ptEdgeA);
cv::Point pEdgeB = srcToResult(edgeDraw.ptEdgeB);
// 超标准红色 / 正常绿色 // 超标准红色 / 正常绿色
cv::Scalar colorEdge = edgeDraw.bExceed ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0); cv::Scalar colorEdge = edgeDraw.bExceed ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0);
colorEdge = CheckUtil::GetDrawColor(m_CheckResult_shareP->resultimg, colorEdge); colorEdge = CheckUtil::GetDrawColor(m_CheckResult_shareP->resultimg, colorEdge);
// 1、所计算边缘线段:标出参与计算的产品边缘(细线;抗凸起拟合直边/回退边)
cv::line(m_CheckResult_shareP->resultimg, pEdgeA, pEdgeB, colorEdge, 1);
// 2、中心 -> 边缘点连线:长度即支架中心到所计算边缘的距离
cv::line(m_CheckResult_shareP->resultimg, pCenter, pEdge, colorEdge, 2); cv::line(m_CheckResult_shareP->resultimg, pCenter, pEdge, colorEdge, 2);
// 距离文字:实测/标准(原图像素) // 3、距离文字:实测/标准(mm)
snprintf(strTxt, sizeof(strTxt), "%s %.0f/%.0f", edgeDraw.strEdge.c_str(), edgeDraw.fDist, edgeDraw.fStandard); snprintf(strTxt, sizeof(strTxt), "%s %.0f/%.0f", edgeDraw.strEdge.c_str(), edgeDraw.fDist, edgeDraw.fStandard);
cv::putText(m_CheckResult_shareP->resultimg, strTxt, cv::putText(m_CheckResult_shareP->resultimg, strTxt,
cv::Point((pCenter.x + pEdge.x) / 2 + 6, (pCenter.y + pEdge.y) / 2 - 6), cv::Point((pCenter.x + pEdge.x) / 2 + 6, (pCenter.y + pEdge.y) / 2 - 6),
@ -2864,6 +2930,7 @@ int ImgCheckAnalysisy::AI_Edge(const cv::Mat &img, cv::RotatedRect &outerRoi, cv
// 3、凸起本身不算 NG,只有"某个把手区域附近找不到匹配的凸起"才算把手缺失(NG 由 CheckRun 上报) // 3、凸起本身不算 NG,只有"某个把手区域附近找不到匹配的凸起"才算把手缺失(NG 由 CheckRun 上报)
// 4、-s(存过程图)时输出 {通道}_handle_det.jpg:绿色四边形=拟合主体、红框=凸起(带编号/角/深度)、 // 4、-s(存过程图)时输出 {通道}_handle_det.jpg:绿色四边形=拟合主体、红框=凸起(带编号/角/深度)、
// 蓝框=参数把手区域、绿框=匹配到的把手,便于从图像观察问题 // 蓝框=参数把手区域、绿框=匹配到的把手,便于从图像观察问题
// 5、拟合出的主体四边形存 m_HandleBodyQuad:支架偏移检测复用其四边(抗凸起)做测距与绘制
int ImgCheckAnalysisy::CheckHandleByBigMask(const cv::Mat &bigmask) int ImgCheckAnalysisy::CheckHandleByBigMask(const cv::Mat &bigmask)
{ {
m_bHandleDetSucc = false; m_bHandleDetSucc = false;
@ -2871,6 +2938,7 @@ int ImgCheckAnalysisy::CheckHandleByBigMask(const cv::Mat &bigmask)
m_bHandleExpect = false; m_bHandleExpect = false;
m_HandleProtrusionList.clear(); m_HandleProtrusionList.clear();
m_HandleRegionResultList.clear(); m_HandleRegionResultList.clear();
m_HandleBodyQuad.clear();
if (bigmask.empty()) if (bigmask.empty())
{ {
@ -2910,8 +2978,8 @@ int ImgCheckAnalysisy::CheckHandleByBigMask(const cv::Mat &bigmask)
nEdgeMargin = (int)(fEdgeMarginCoef * nStep + 0.5f); nEdgeMargin = (int)(fEdgeMarginCoef * nStep + 0.5f);
} }
} }
std::vector<cv::Point2f> vecBodyQuad; // 拟合出的主体四边形(仅 -s 存图观察用) // m_HandleBodyQuad:拟合出的主体四边形(左上/右上/右下/左下);-s 存图观察用,支架偏移检测复用其四边做抗凸起测距/绘制
int re = CheckUtil::GetMaskProtrusions(bigmask, m_HandleProtrusionList, nMinDepth, nMinArea, &vecBodyQuad, nEdgeMargin); int re = CheckUtil::GetMaskProtrusions(bigmask, m_HandleProtrusionList, nMinDepth, nMinArea, &m_HandleBodyQuad, nEdgeMargin);
if (re != 0) if (re != 0)
{ {
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Handle", "GetMaskProtrusions error %d", re); m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Handle", "GetMaskProtrusions error %d", re);
@ -2992,12 +3060,12 @@ int ImgCheckAnalysisy::CheckHandleByBigMask(const cv::Mat &bigmask)
show = bigmask.clone(); show = bigmask.clone();
} }
// 主体四边形(拟合出的四条边缘) // 主体四边形(拟合出的四条边缘)
if (vecBodyQuad.size() == 4) if (m_HandleBodyQuad.size() == 4)
{ {
std::vector<cv::Point> vecQuad; std::vector<cv::Point> vecQuad;
for (size_t i = 0; i < vecBodyQuad.size(); i++) for (size_t i = 0; i < m_HandleBodyQuad.size(); i++)
{ {
vecQuad.push_back(cv::Point(cvRound(vecBodyQuad[i].x), cvRound(vecBodyQuad[i].y))); vecQuad.push_back(cv::Point(cvRound(m_HandleBodyQuad[i].x), cvRound(m_HandleBodyQuad[i].y)));
} }
cv::polylines(show, vecQuad, true, cv::Scalar(0, 255, 0), 8); cv::polylines(show, vecQuad, true, cv::Scalar(0, 255, 0), 8);
} }

Loading…
Cancel
Save