update 优化返回的物理坐标和宽高

dev_lsy
liusiyang 1 week ago
parent 76edbade98
commit 718d12b26b

@ -70,6 +70,9 @@ public:
float fscale_detToresult_x = 0; float fscale_detToresult_x = 0;
float fscale_detToresult_y = 0; float fscale_detToresult_y = 0;
// 产品左上角rot_cur_roi.boundingRect在检测图 detImg 中的偏移,缺陷坐标转换到产品坐标系时需减去该间隙
cv::Point ptRoiOffsetInDet = cv::Point(0, 0);
int NG_num = 0; int NG_num = 0;
int YS_num = 0; int YS_num = 0;
int Ok_num = 0; int Ok_num = 0;

@ -241,6 +241,8 @@ private:
cv::Rect m_CutRoi; cv::Rect m_CutRoi;
cv::Rect m_Crop_Roi_paramImg; // 裁切在参数模板图上的 位置。 cv::Rect m_Crop_Roi_paramImg; // 裁切在参数模板图上的 位置。
cv::RotatedRect m_rot_cur_roi; // 产品旋转外接矩形(原图坐标)
bool m_bRotCurRoiValid = false; // m_rot_cur_roi 是否有效
std::string m_strCurDetChannel; // 当前处理的图片通道 std::string m_strCurDetChannel; // 当前处理的图片通道

@ -119,7 +119,11 @@ int ImageResultJudge::GetAIDetImg(std::shared_ptr<ImageAllResult> pImageResult,
QXImageResult ImageResultJudge::BuildDefectImage(std::shared_ptr<ImageAllResult> pImageResult, QX_ERROR_INFO_ *QX_info, QXImageResult ImageResultJudge::BuildDefectImage(std::shared_ptr<ImageAllResult> pImageResult, QX_ERROR_INFO_ *QX_info,
int qxidx, cv::Point pCenter, float fs_resize_x, float fs_resize_y) int qxidx, cv::Point pCenter, float fs_resize_x, float fs_resize_y)
{ {
cv::Rect roi = QX_info->roi; cv::Rect roi = QX_info->roi; // 缺陷坐标(产品坐标系,已减去裁剪框与产品左上角的间隙)
// 还原检测图(detImg)坐标,用于缺陷小图裁剪等内部用途
cv::Rect roi_det = roi;
roi_det.x += pImageResult->ptRoiOffsetInDet.x;
roi_det.y += pImageResult->ptRoiOffsetInDet.y;
float JudgArea = QX_info->JudgArea; float JudgArea = QX_info->JudgArea;
float flen = QX_info->flen; float flen = QX_info->flen;
float fbreadth = QX_info->fbreadth; float fbreadth = QX_info->fbreadth;
@ -130,7 +134,7 @@ QXImageResult ImageResultJudge::BuildDefectImage(std::shared_ptr<ImageAllResult>
QXImageResult tem; QXImageResult tem;
tem.idx = qxidx; tem.idx = qxidx;
cv::Rect CutRoi = GetCutRoi(roi, pImageResult->detImg); cv::Rect CutRoi = GetCutRoi(roi_det, pImageResult->detImg);
cv::Size sz = cv::Size(QX_SAMLLIMG_WIDTH, QX_SAMLLIMG_HEIGHT); cv::Size sz = cv::Size(QX_SAMLLIMG_WIDTH, QX_SAMLLIMG_HEIGHT);
if (pImageResult->detImg.channels() == 1) if (pImageResult->detImg.channels() == 1)
@ -151,25 +155,26 @@ QXImageResult ImageResultJudge::BuildDefectImage(std::shared_ptr<ImageAllResult>
tem.max_v = maxValue; tem.max_v = maxValue;
tem.strTypeName = QX_Result_Names[nqx_type]; tem.strTypeName = QX_Result_Names[nqx_type];
tem.qx_Code = QX_Result_Code[nqx_type]; tem.qx_Code = QX_Result_Code[nqx_type];
tem.srcImgroi = roi; tem.srcImgroi = roi_det;
tem.len = flen; tem.len = flen;
tem.breadth = fbreadth; tem.breadth = fbreadth;
tem.qx_type = 0; tem.qx_type = 0;
tem.fScore = 0; tem.fScore = 0;
tem.density = 0; tem.density = 0;
tem.resizeImgroi.x = roi.x * fs_resize_x; tem.resizeImgroi.x = roi_det.x * fs_resize_x;
tem.resizeImgroi.width = roi.width * fs_resize_x; tem.resizeImgroi.width = roi_det.width * fs_resize_x;
tem.resizeImgroi.y = roi.y * fs_resize_y; tem.resizeImgroi.y = roi_det.y * fs_resize_y;
tem.resizeImgroi.height = roi.height * fs_resize_y; tem.resizeImgroi.height = roi_det.height * fs_resize_y;
// 缺陷中心:产品坐标系(像素/物理),相对产品左上角
tem.x_pixel = roi.x + roi.width * 0.5; tem.x_pixel = roi.x + roi.width * 0.5;
tem.y_pixel = roi.y + roi.height * 0.5; tem.y_pixel = roi.y + roi.height * 0.5;
tem.x_mm = tem.x_pixel * m_fImgage_Scale_X; tem.x_mm = tem.x_pixel * m_fImgage_Scale_X;
tem.y_mm = tem.y_pixel * m_fImgage_Scale_Y; tem.y_mm = tem.y_pixel * m_fImgage_Scale_Y;
tem.CutImgroi = roi; tem.CutImgroi = roi_det;
tem.CutImgroi.x -= CutRoi.x; tem.CutImgroi.x -= CutRoi.x;
tem.CutImgroi.y -= CutRoi.y; tem.CutImgroi.y -= CutRoi.y;

@ -802,7 +802,16 @@ int ImgCheckAnalysisy::CheckRun()
/*自适应更新参数*/ /*自适应更新参数*/
long time_adapt_s = CheckUtil::getcurTime(); long time_adapt_s = CheckUtil::getcurTime();
cv::RotatedRect rot_cur_roi; cv::RotatedRect rot_cur_roi;
Adapt_Config(m_CheckResult_shareP->in_shareImage->img, m_CutRoi, rot_cur_roi, m_pbaseCheckFunction->markLine.badapt_region); int nAdaptRe = Adapt_Config(m_CheckResult_shareP->in_shareImage->img, m_CutRoi, rot_cur_roi, m_pbaseCheckFunction->markLine.badapt_region);
if (nAdaptRe == 0)
{
m_rot_cur_roi = rot_cur_roi;
m_bRotCurRoiValid = true;
}
else
{
m_bRotCurRoiValid = false;
}
long time_adapt_e = CheckUtil::getcurTime(); long time_adapt_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "time = %ld", time_adapt_e - time_adapt_s); m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "time = %ld", time_adapt_e - time_adapt_s);
@ -842,6 +851,18 @@ 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);
m_Crop_Roi_paramImg = m_CutRoi; m_Crop_Roi_paramImg = m_CutRoi;
// 计算产品左上角在检测图(detImg)中的偏移(间隙),用于缺陷坐标转换到产品坐标系
if (m_bRotCurRoiValid)
{
// 取旋转矩形实际的左上角顶点(非轴对齐外接框 boundingRect后者在带旋转角时会偏大
std::vector<cv::Point2f> rroi_vertices = sort_vertices(m_rot_cur_roi);
m_pImageAllResult->ptRoiOffsetInDet.x = cvRound(rroi_vertices[0].x) - m_CutRoi.x;
m_pImageAllResult->ptRoiOffsetInDet.y = cvRound(rroi_vertices[0].y) - m_CutRoi.y;
}
else
{
m_pImageAllResult->ptRoiOffsetInDet = cv::Point(0, 0);
}
m_pImageAllResult->pDetResult->CutRoi = m_CutRoi; m_pImageAllResult->pDetResult->CutRoi = m_CutRoi;
m_pImageAllResult->pDetResult->Param_CropRoi = m_Crop_Roi_paramImg; m_pImageAllResult->pDetResult->Param_CropRoi = m_Crop_Roi_paramImg;
@ -2532,6 +2553,12 @@ int ImgCheckAnalysisy::Edge_Qx_Det(const cv::Mat &img)
// } // }
// } // }
// 缺陷坐标转换到产品坐标系:减去裁剪框与产品左上角的间隙
if (m_bRotCurRoiValid)
{
temerror.roi.x -= m_pImageAllResult->ptRoiOffsetInDet.x;
temerror.roi.y -= m_pImageAllResult->ptRoiOffsetInDet.y;
}
m_pDetResult->pQx_ErrorList->push_back(temerror); m_pDetResult->pQx_ErrorList->push_back(temerror);
} }
@ -2604,6 +2631,12 @@ int ImgCheckAnalysisy::BLobToDetResult()
{ {
QX_ERROR_INFO_ temerror; QX_ERROR_INFO_ temerror;
temerror.roi = roi; temerror.roi = roi;
// 缺陷坐标转换到产品坐标系:减去裁剪框与产品左上角的间隙
if (m_bRotCurRoiValid)
{
temerror.roi.x -= m_pImageAllResult->ptRoiOffsetInDet.x;
temerror.roi.y -= m_pImageAllResult->ptRoiOffsetInDet.y;
}
temerror.Idx = m_pDetResult->pQx_ErrorList->size(); temerror.Idx = m_pDetResult->pQx_ErrorList->size();
temerror.area = blobs.blobTab[i].area; temerror.area = blobs.blobTab[i].area;
temerror.JudgArea = JudgArea; temerror.JudgArea = JudgArea;
@ -2695,8 +2728,25 @@ int ImgCheckAnalysisy::AI_Edge(const cv::Mat &img, cv::Rect &cutRoi)
int ImgCheckAnalysisy::CalProductSize() int ImgCheckAnalysisy::CalProductSize()
{ {
float fw = m_CutRoi.width * m_fImgage_Scale_X; float fw, fh;
float fh = m_CutRoi.height * m_fImgage_Scale_Y; if (m_bRotCurRoiValid)
{
// 产品存在旋转角:用旋转矩形四个顶点的实际边长换算物理尺寸
// 宽 = (左上-右上 + 左下-右下) / 2高 = (左上-左下 + 右上-右下) / 2
std::vector<cv::Point2f> v = sort_vertices(m_rot_cur_roi);
auto edgeLenPhys = [&](const cv::Point2f &a, const cv::Point2f &b) -> double {
double dx = (a.x - b.x) * m_fImgage_Scale_X;
double dy = (a.y - b.y) * m_fImgage_Scale_Y;
return std::sqrt(dx * dx + dy * dy);
};
fw = (float)((edgeLenPhys(v[0], v[1]) + edgeLenPhys(v[2], v[3])) * 0.5); // 上边+下边平均
fh = (float)((edgeLenPhys(v[0], v[2]) + edgeLenPhys(v[1], v[3])) * 0.5); // 左边+右边平均
}
else
{
fw = m_CutRoi.width * m_fImgage_Scale_X;
fh = m_CutRoi.height * m_fImgage_Scale_Y;
}
fw = std::ceil(fw * 10) / 10; fw = std::ceil(fw * 10) / 10;
fh = std::ceil(fh * 10) / 10; fh = std::ceil(fh * 10) / 10;
m_CheckResult_shareP->productWidht_mm = fw; m_CheckResult_shareP->productWidht_mm = fw;

Loading…
Cancel
Save