update 同步云平台边损2

dev_lsy
liusiyang 2 weeks ago
parent d509bcbaa2
commit 444e57a52d

@ -200,7 +200,7 @@ private:
int BLobToDetResult(); int BLobToDetResult();
//自适应参数区域更新 //自适应参数区域更新
int Adapt_Config(Mat img, Rect roi, bool b_update, cv::RotatedRect &rot_cur_roi); int Adapt_Config(Mat img, Rect roi, bool b_update);
std::shared_ptr<AIFactory> AI_Factory; std::shared_ptr<AIFactory> AI_Factory;

@ -197,6 +197,63 @@ bool Edge_QX_Det::GetSegmentIntersection(const Line &l1, const Line &l2, cv::Poi
return false; return false;
} }
// Liang-Barsky 线段矩形裁剪:把线段截断到矩形范围内,返回是否仍有可见部分。
// 曲线拟合投影后端点可能越界(如右边缘 x>cols、左边缘 x<0必须先裁剪
// 否则角点处的水平/垂直相邻线段可能没有交点。
static bool ClipLineToRect(cv::Point2f &p1, cv::Point2f &p2, const cv::Rect &r)
{
float x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y;
float dx = x2 - x1, dy = y2 - y1;
float t0 = 0.f, t1 = 1.f;
auto clip = [&](float p, float q) -> bool {
if (std::abs(p) < 1e-9f)
{
return q >= 0; // 平行于边界q<0 表示整段在边界外
}
float t = q / p;
if (p < 0)
{
if (t > t1) return false;
if (t > t0) t0 = t;
}
else
{
if (t < t0) return false;
if (t < t1) t1 = t;
}
return true;
};
if (!clip(-dx, x1 - r.x)) return false; // 左边界
if (!clip( dx, (r.x + r.width) - x1)) return false; // 右边界
if (!clip(-dy, y1 - r.y)) return false; // 上边界
if (!clip( dy, (r.y + r.height) - y1)) return false; // 下边界
p1 = cv::Point2f(x1 + t0 * dx, y1 + t0 * dy);
p2 = cv::Point2f(x1 + t1 * dx, y1 + t1 * dy);
return true;
}
static void ClipLineToImg(cv::Point &p1, cv::Point &p2, const cv::Rect &bounds)
{
cv::Point2f f1((float)p1.x, (float)p1.y);
cv::Point2f f2((float)p2.x, (float)p2.y);
if (ClipLineToRect(f1, f2, bounds))
{
p1 = cv::Point(cvRound(f1.x), cvRound(f1.y));
p2 = cv::Point(cvRound(f2.x), cvRound(f2.y));
}
else
{
// 完全在图像外:收缩为图像内的最近边界点,避免零长度线段影响角点求交
cv::Point2f c((float)std::max(0, std::min(bounds.width, (int)((p1.x + p2.x) / 2))),
(float)std::max(0, std::min(bounds.height, (int)((p1.y + p2.y) / 2))));
p1 = cv::Point(cvRound(c.x), cvRound(c.y));
p2 = p1;
}
}
Edge_QX_Det::Edge_QX_Det() Edge_QX_Det::Edge_QX_Det()
{ {
bshowimg = false; bshowimg = false;
@ -444,8 +501,31 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
std::vector<cv::Point2f> cornerPoints; std::vector<cv::Point2f> cornerPoints;
cv::Point2f pt; cv::Point2f pt;
cornerPoints.clear(); cornerPoints.clear();
// 曲线投影后端点可能越界(产品部分区域在图像外时),先把所有线段裁剪到图像范围内,
// 否则相邻的水平/垂直线段可能没有交点,导致检测整体失败。
cv::Rect imgBound(0, 0, img.cols, img.rows);
for (auto &line : Up_line) ClipLineToImg(line.p1, line.p2, imgBound);
for (auto &line : down_line) ClipLineToImg(line.p1, line.p2, imgBound);
for (auto &line : left_line) ClipLineToImg(line.p1, line.p2, imgBound);
for (auto &line : right_line) ClipLineToImg(line.p1, line.p2, imgBound);
// 求角点:优先线段求交;线段不相交时(越界被裁剪后仍可能无交点)退化为直线求交,
// 并把交点限制在图像范围内。
auto getCorner = [&](Line &l1, Line &l2, cv::Point2f &out) -> bool {
if (GetSegmentIntersection(l1, l2, out))
return true;
cv::Vec4f v1((float)(l1.p2.x - l1.p1.x), (float)(l1.p2.y - l1.p1.y), (float)l1.p1.x, (float)l1.p1.y);
cv::Vec4f v2((float)(l2.p2.x - l2.p1.x), (float)(l2.p2.y - l2.p1.y), (float)l2.p1.x, (float)l2.p1.y);
if (!GetLineIntersection(v1, v2, out))
return false;
out.x = std::max(0.f, std::min((float)img.cols, out.x));
out.y = std::max(0.f, std::min((float)img.rows, out.y));
return true;
};
// 左上角Up_line[0] 与 left_line[0] // 左上角Up_line[0] 与 left_line[0]
if (GetSegmentIntersection(Up_line[0], left_line[0], pt)) if (getCorner(Up_line[0], left_line[0], pt))
{ {
pt.x += 10; pt.x += 10;
pt.y += 10; pt.y += 10;
@ -457,7 +537,7 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
return 1; return 1;
// 右上角Up_line.back() 与 right_line[0] // 右上角Up_line.back() 与 right_line[0]
if (GetSegmentIntersection(Up_line.back(), right_line[0], pt)) if (getCorner(Up_line.back(), right_line[0], pt))
{ {
pt.x -= 10; pt.x -= 10;
pt.y += 10; pt.y += 10;
@ -469,7 +549,7 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
return 1; return 1;
// 右下角down_line.back() 与 right_line.back() // 右下角down_line.back() 与 right_line.back()
if (GetSegmentIntersection(down_line.back(), right_line.back(), pt)) if (getCorner(down_line.back(), right_line.back(), pt))
{ {
pt.x -= 10; pt.x -= 10;
pt.y -= 10; pt.y -= 10;
@ -481,7 +561,7 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
return 1; return 1;
// 左下角down_line[0] 与 left_line.back() // 左下角down_line[0] 与 left_line.back()
if (GetSegmentIntersection(down_line[0], left_line.back(), pt)) if (getCorner(down_line[0], left_line.back(), pt))
{ {
pt.x += 10; pt.x += 10;
pt.y -= 10; pt.y -= 10;

@ -451,7 +451,7 @@ Point2f GetCoorPoint(Point2f point, Mat img_mat)
return new_point; return new_point;
} }
int GetEdgeRoi(Mat img, Rect &new_roi, cv::RotatedRect &rotated_roi, float scale_x, float scale_y, string cur_channel){ int GetEdgeRoi(Mat img, Rect &new_roi, cv::RotatedRect &rotated_roi, float scale_x, float scale_y){
if (img.empty()) if (img.empty())
{ {
return 1; return 1;
@ -465,22 +465,9 @@ int GetEdgeRoi(Mat img, Rect &new_roi, cv::RotatedRect &rotated_roi, float scale
// 二值化找最大连通域 // 二值化找最大连通域
Mat r_img_bin; Mat r_img_bin;
if(cur_channel == "BCA" || cur_channel == "BTA") threshold(r_img, r_img_bin, 15, 255, THRESH_BINARY);
{
threshold(r_img, r_img_bin, 35, 255, THRESH_BINARY);
}
else
{
threshold(r_img, r_img_bin, 35, 255, THRESH_BINARY);
}
// 做一步开运算
Mat r_img_bin_close;
morphologyEx(r_img_bin, r_img_bin_close, MORPH_CLOSE, Mat::ones(15, 15, CV_8U));
// imwrite("r_img_bin.tif", r_img_bin);
// imwrite("r_img_bin_close.tif", r_img_bin_close);
// imwrite("r_img.tif", r_img);
std::vector<std::vector<cv::Point>> contours; std::vector<std::vector<cv::Point>> contours;
cv::findContours(r_img_bin_close, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); cv::findContours(r_img_bin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
if (contours.empty()) if (contours.empty())
{ {
return 2; return 2;
@ -612,7 +599,7 @@ std::vector<cv::Point2f> sort_vertices(cv::RotatedRect rrect) {
return vertices; return vertices;
} }
int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update, cv::RotatedRect &rot_cur_roi){ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update){
if (img.empty()) { if (img.empty()) {
std::cerr << "Error: Input image 'img' is empty!" << std::endl; std::cerr << "Error: Input image 'img' is empty!" << std::endl;
return -1; return -1;
@ -620,8 +607,8 @@ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update, cv::Ro
if(!b_update){ if(!b_update){
return 1; return 1;
} }
// cv::RotatedRect rot_cur_roi; cv::RotatedRect rot_cur_roi;
int get_edge_roi = GetEdgeRoi(img, cur_roi, rot_cur_roi, 20, 20, m_CheckResult_shareP->basicResult.strChannel); int get_edge_roi = GetEdgeRoi(img, cur_roi, rot_cur_roi, 20, 20);
if(get_edge_roi != 0){ if(get_edge_roi != 0){
return 2; return 2;
} }
@ -636,7 +623,6 @@ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update, cv::Ro
m_old_cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1; 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_markLine_mark2 = m_AnalysisyConfig.baseFunction.markLine.mark_local_2;
m_old_cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr; m_old_cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr;
m_old_cur_traditional_region = m_pbaseCheckFunction->traditionDet.detArea;
} }
/*计算old_roi到new_roi的完整仿射变换矩阵(平移+缩放+旋转)*/ /*计算old_roi到new_roi的完整仿射变换矩阵(平移+缩放+旋转)*/
@ -674,8 +660,6 @@ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update, cv::Ro
cv::Point& cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1; cv::Point& cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1;
cv::Point& cur_markLine_mark2 = m_AnalysisyConfig.baseFunction.markLine.mark_local_2; cv::Point& cur_markLine_mark2 = m_AnalysisyConfig.baseFunction.markLine.mark_local_2;
std::vector<RegionConfigST>& cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr; std::vector<RegionConfigST>& cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr;
cv::Rect& cur_traditional_rect = m_pbaseCheckFunction->traditionDet.detArea_ROI;
std::vector<cv::Point>& cur_traditional_region = m_pbaseCheckFunction->traditionDet.detArea;
// if (img.empty()) // if (img.empty())
// { // {
@ -733,9 +717,7 @@ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update, cv::Ro
cur_regionConfigArr[i].basicInfo.pointArry[j] = affinePoint(m_old_cur_regionConfigArr[i].basicInfo.pointArry[j]); cur_regionConfigArr[i].basicInfo.pointArry[j] = affinePoint(m_old_cur_regionConfigArr[i].basicInfo.pointArry[j]);
} }
} }
for(int i = 0; i < cur_traditional_region.size(); i++){
cur_traditional_region[i] = affinePoint(m_old_cur_traditional_region[i]);
}
/*show*/ /*show*/
// if (img.empty()) // if (img.empty())
// { // {
@ -813,7 +795,7 @@ 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, m_pbaseCheckFunction->markLine.badapt_region, rot_cur_roi); Adapt_Config(m_CheckResult_shareP->in_shareImage->img, m_CutRoi, m_pbaseCheckFunction->markLine.badapt_region);
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);
@ -878,6 +860,7 @@ int ImgCheckAnalysisy::CheckRun()
else else
{ {
// 不推理:直接输出全黑残点图 // 不推理:直接输出全黑残点图
m_pdetlog->AddCheckstr(PrintLevel_0, "2.1、pre detect", "-------------------------NO AI_Edge--------------- \n");
m_pImageAllResult->AIMaskImg = cv::Mat::zeros(m_pImageAllResult->detImg.size(), CV_8UC1); m_pImageAllResult->AIMaskImg = cv::Mat::zeros(m_pImageAllResult->detImg.size(), CV_8UC1);
} }
@ -2232,34 +2215,11 @@ int ImgCheckAnalysisy::Update_DetRoiList()
float fx = m_pImageAllResult->fscale_detToresult_x; float fx = m_pImageAllResult->fscale_detToresult_x;
float fy = m_pImageAllResult->fscale_detToresult_y; float fy = m_pImageAllResult->fscale_detToresult_y;
int num = 0; // Adapt_Config 已通过仿射变换将配置区域适配到当前产品位置,
cv::Rect offsetroi = m_Crop_Roi_paramImg; // 此处仅做坐标映射减去裁剪ROI偏移 + 缩放),不再叠加边缘对齐的二次偏移
for (const auto &region : m_pCommonAnalysisyConfig->regionConfigArr)
if (m_pEdge_Align_Result && m_pEdge_Align_Result->buseOfft)
{ {
for (const auto &region : m_pCommonAnalysisyConfig->regionConfigArr) m_DetRoiList.Update(region.basicInfo.pointArry, m_Crop_Roi_paramImg, fx, fy);
{
if (m_pEdge_Align_Result->H.empty())
{
m_DetRoiList.Update_1(region.basicInfo.pointArry, offsetroi, m_pEdge_Align_Result->offt_x, m_pEdge_Align_Result->offt_y, fx, fy);
}
else
{
m_DetRoiList.Update_Marit(region.basicInfo.pointArry, offsetroi, m_pEdge_Align_Result->H, fx, fy);
}
// m_DetRoiList.Update_1(region.basicInfo.pointArry, offsetroi, m_pEdge_Align_Result->offt_x, m_pEdge_Align_Result->offt_y, fx, fy);
}
}
else
{
for (const auto &region : m_pCommonAnalysisyConfig->regionConfigArr)
{
m_DetRoiList.Update(region.basicInfo.pointArry, m_Crop_Roi_paramImg, fx, fy);
}
} }
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "info", "roiList_Src roi num %ld", m_DetRoiList.roiList_Src.size()); m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "info", "roiList_Src roi num %ld", m_DetRoiList.roiList_Src.size());
@ -2275,19 +2235,23 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
{ {
int n = 0; int n = 0;
// std::cout << m_DetRoiList.roiList_Show.size() << std::endl; // std::cout << m_DetRoiList.roiList_Show.size() << std::endl;
for (const auto &polygon : m_DetRoiList.roiList_Show) for(int i = 0; i < m_DetRoiList.roiList_Show.size(); i++)
{ {
// n++; cv::polylines(m_CheckResult_shareP->resultimg, m_DetRoiList.roiList_Show[i], true, cv::Scalar(32, 128, (i*64+64)%255), 1);
// if (n == 1) }
// { // for (const auto &polygon : m_DetRoiList.roiList_Show)
// continue; // {
// } // // n++;
// // if (n == 1)
// // {
// // continue;
// // }
// std::cout << polygon << std::endl; // // std::cout << polygon << std::endl;
// 绘制多边形的边界不填充使用绿色线条线宽为2 // // 绘制多边形的边界不填充使用绿色线条线宽为2
cv::polylines(m_CheckResult_shareP->resultimg, polygon, true, cv::Scalar(128, 128, 255), 1); // true表示闭合多边形 // cv::polylines(m_CheckResult_shareP->resultimg, polygon, true, cv::Scalar(128, 128, 255), 1); // true表示闭合多边形
} // }
// cv::imwrite(DetImgInfo_shareP->strChannel + "roi_src.png", m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc]); // cv::imwrite(DetImgInfo_shareP->strChannel + "roi_src.png", m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc]);
// cv::imwrite(DetImgInfo_shareP->strChannel + "roi_ss.png", m_pdetlog->temImgList[TEM_IMG_IDX_Result]); // cv::imwrite(DetImgInfo_shareP->strChannel + "roi_ss.png", m_pdetlog->temImgList[TEM_IMG_IDX_Result]);
@ -2302,13 +2266,17 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
{ {
for (const auto &r : m_Edge_DetConfig.edge_det_roi) for (const auto &r : m_Edge_DetConfig.edge_det_roi)
{ {
cv::Rect droi; cv::Point2f vertices[4];
droi.x = r.roi.x * fs_resize_x; r.rrect.points(vertices);
droi.y = r.roi.y * fs_resize_y; for (int j = 0; j < 4; j++)
droi.width = r.roi.width * fs_resize_x; {
droi.height = r.roi.height * fs_resize_y; cv::Point p1, p2;
p1.x = (int)(vertices[j].x * fs_resize_x);
cv::rectangle(m_CheckResult_shareP->resultimg, droi, cv::Scalar(255, 0, 255), 1); // 黄色角点 p1.y = (int)(vertices[j].y * fs_resize_y);
p2.x = (int)(vertices[(j+1)%4].x * fs_resize_x);
p2.y = (int)(vertices[(j+1)%4].y * fs_resize_y);
cv::line(m_CheckResult_shareP->resultimg, p1, p2, cv::Scalar(255, 0, 255), 1);
}
} }
if (m_Edge_DetConfig.Det_region.size() > 2) if (m_Edge_DetConfig.Det_region.size() > 2)
@ -2334,24 +2302,6 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
} }
} }
} }
if (m_pbaseCheckFunction && m_pbaseCheckFunction->markLine.region.size() > 1)
{
std::vector<cv::Point> product_roi_show;
for (const auto &pt : m_pbaseCheckFunction->markLine.region)
{
cv::Point draw_pt;
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,
product_roi_show,
true,
cv::Scalar(0, 255, 0),
1);
}
if (m_pEdge_Align_Result.get() != NULL) if (m_pEdge_Align_Result.get() != NULL)
{ {
@ -2434,6 +2384,7 @@ int ImgCheckAnalysisy::Edge_Qx_Det(const cv::Mat &img)
{ {
m_Edge_DetConfig.Init(); m_Edge_DetConfig.Init();
m_Edge_DetConfig.detlog = m_pdetlog;
m_Edge_DetConfig.strChannel = m_strCurDetChannel; m_Edge_DetConfig.strChannel = m_strCurDetChannel;
m_Edge_DetConfig.pBaseCheckFunction = m_pbaseCheckFunction; m_Edge_DetConfig.pBaseCheckFunction = m_pbaseCheckFunction;
m_Edge_DetConfig.alginResult.corpRoi = m_Crop_Roi_paramImg; m_Edge_DetConfig.alginResult.corpRoi = m_Crop_Roi_paramImg;
@ -2656,11 +2607,12 @@ int ImgCheckAnalysisy::CalProductSize()
m_CheckResult_shareP->productWidht_mm = fw; m_CheckResult_shareP->productWidht_mm = fw;
m_CheckResult_shareP->productHeight_mm = fh; m_CheckResult_shareP->productHeight_mm = fh;
m_pdetlog->AddCheckstr(PrintLevel_1, "Det ROI", " [w %d,h %d] (piexl) -> [w %f h %f](mm),scale %f %f", m_pdetlog->AddCheckstr(PrintLevel_1, "Det ROI", " [x%d, y%d, w %d,h %d] (piexl) -> [w %f h %f](mm),scale %f %f",
m_CutRoi.width, m_CutRoi.height, fw, fh, m_fImgage_Scale_X, m_fImgage_Scale_Y); m_CutRoi.x, m_CutRoi.y, m_CutRoi.width, m_CutRoi.height, fw, fh, m_fImgage_Scale_X, m_fImgage_Scale_Y);
return 0; return 0;
} }
int ImgCheckAnalysisy::ImgPreDet() int ImgCheckAnalysisy::ImgPreDet()
{ {

@ -1197,6 +1197,10 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
{ {
_config.edgeDet.Det_Range = value_f["form"]["Detect_Config"]["Det_Range"].asInt(); _config.edgeDet.Det_Range = value_f["form"]["Detect_Config"]["Det_Range"].asInt();
} }
if (value_f["form"]["Detect_Config"]["Det_Range_Offset"])
{
_config.edgeDet.Det_Range_Offset = value_f["form"]["Detect_Config"]["Det_Range_Offset"].asInt();
}
if (value_f["form"]["Detect_Config"]["QX_Widht_min"]) if (value_f["form"]["Detect_Config"]["QX_Widht_min"])
{ {

Loading…
Cancel
Save