update 同步云平台边损更新

dev_lsy
liusiyang 1 month ago
parent c2f9d93b2f
commit b663c7f676

@ -134,8 +134,9 @@ public:
// 检测小区域的信息
struct Det_ROI_Config
{
cv::Rect roi;
std::vector<cv::Point> plist;
cv::Rect roi; // 轴对齐包围盒(由 rrect.boundingRect() 计算,保持兼容)
cv::RotatedRect rrect; // 旋转矩形,贴合倾斜产品的边缘方向,避免过检
std::vector<cv::Point> plist; // 检测区域的多边形顶点
};
struct Algin_Result
{
@ -215,10 +216,15 @@ private:
// 检测缺陷
int Det_qx(const cv::Mat &img, std::vector<Det_ROI_Config> roilist, Det_ROI_Type type, DetConfigResult *pDetConfig);
// 多边形边缘缺陷检测(无方向/角点过滤每个ROI独立处理避免巨型mask
int Det_qx_polygon(const cv::Mat &img, const std::vector<Det_ROI_Config> &roilist, 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);
// 使用定位区域巡边检测
int Draw_Det_Align(const cv::Mat &img, DetConfigResult *pDetConfig);
private:
/// @brief

@ -287,8 +287,8 @@ private:
// AI mask 在这一列是否有 缺陷残点,用以 加速 blob 分析。
unsigned char *m_ImgBlobHFlagData;
// 原始区域数据
Rect m_old_productROI = Rect(0, 0, 0, 0);
// 原始区域数据(使用 RotatedRect 以保留 region 的旋转角度信息)
cv::RotatedRect m_old_productROI;
std::vector<cv::Point> m_old_cur_edgeDet_region;
std::vector<cv::Point> m_old_cur_markLine_region;
std::vector<cv::Point> m_old_cur_traditional_region;

@ -210,9 +210,15 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
{
return 0;
}
if(pDetConfig->pBaseCheckFunction->edgeDet.bUseAlignRoi)
{
int re = Draw_Det_Align(img, pDetConfig);
return re;
}
if (pDetConfig->pBaseCheckFunction->edgeDet.bDrawRoi)
{
return Draw_Det(img, pDetConfig);
int re = Draw_Det(img, pDetConfig);
return re;
}
// if (pDetConfig->strChannel == "TA")
@ -313,59 +319,6 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
}
// printf("DirectSign_Right::111111111111111111 re123 %d\n", re123);
// 求交点
std::vector<cv::Point2f> cornerPoints;
cv::Point2f pt;
// 左上角Up_line[0] 与 Left_line[0]
if (GetSegmentIntersection(Up_line[0], left_line[0], pt))
{
pt.x += 10;
pt.y += 10;
cornerPoints.push_back(pt);
Up_line[0].p1 = pt;
left_line[0].p1 = pt;
}
else
return 1;
// 右上角Up_line.back() 与 Right_line[0]
if (GetSegmentIntersection(Up_line.back(), right_line[0], pt))
{
pt.x -= 10;
pt.y += 10;
cornerPoints.push_back(pt);
Up_line.back().p2 = pt;
right_line[0].p1 = pt;
}
else
return 1;
// 右下角Down_line.back() 与 Right_line.back()
if (GetSegmentIntersection(down_line.back(), right_line.back(), pt))
{
pt.x -= 10;
pt.y -= 10;
cornerPoints.push_back(pt);
down_line.back().p2 = pt;
right_line.back().p2 = pt;
}
else
return 1;
// 左下角Down_line[0] 与 Left_line.back()
if (GetSegmentIntersection(down_line[0], left_line.back(), pt))
{
pt.x += 10;
pt.y -= 10;
cornerPoints.push_back(pt);
down_line[0].p1 = pt;
left_line.back().p2 = pt;
}
else
return 1;
// 用RANSAC剔除崩边凹陷的异常点后拟合二次曲线使ROI贴合产品边缘的自然弧度
// 水平边缘(上下): 拟合 y = a*x² + b*x + c
// 垂直边缘(左右): 拟合 x = a*y² + b*y + c
@ -487,8 +440,62 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
}
}
// 曲线拟合后重新计算角点,使角点与拟合后的线段端点对齐
std::vector<cv::Point2f> cornerPoints;
cv::Point2f pt;
cornerPoints.clear();
// 左上角Up_line[0] 与 left_line[0]
if (GetSegmentIntersection(Up_line[0], left_line[0], pt))
{
pt.x += 10;
pt.y += 10;
cornerPoints.push_back(pt);
Up_line[0].p1 = pt;
left_line[0].p1 = pt;
}
else
return 1;
// 右上角Up_line.back() 与 right_line[0]
if (GetSegmentIntersection(Up_line.back(), right_line[0], pt))
{
pt.x -= 10;
pt.y += 10;
cornerPoints.push_back(pt);
Up_line.back().p2 = pt;
right_line[0].p1 = pt;
}
else
return 1;
// 右下角down_line.back() 与 right_line.back()
if (GetSegmentIntersection(down_line.back(), right_line.back(), pt))
{
pt.x -= 10;
pt.y -= 10;
cornerPoints.push_back(pt);
down_line.back().p2 = pt;
right_line.back().p2 = pt;
}
else
return 1;
// 左下角down_line[0] 与 left_line.back()
if (GetSegmentIntersection(down_line[0], left_line.back(), pt))
{
pt.x += 10;
pt.y -= 10;
cornerPoints.push_back(pt);
down_line[0].p1 = pt;
left_line.back().p2 = pt;
}
else
return 1;
// 生成 检测的 roi。
int roi_wh = pDetConfig->pBaseCheckFunction->edgeDet.Det_Range;
int range_offset = pDetConfig->pBaseCheckFunction->edgeDet.Det_Range_Offset;
cv::Rect imgBounds(0, 0, img.cols, img.rows); // 图像边界,用于裁剪越界 ROI
std::vector<Det_ROI_Config> up_det_roi;
@ -498,52 +505,56 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
for (const auto &line : Up_line)
{
Det_ROI_Config tem;
tem.plist.push_back(line.p1);
tem.plist.push_back(line.p2);
tem.plist.push_back(cv::Point(line.p2.x, line.p2.y + roi_wh));
tem.plist.push_back(cv::Point(line.p1.x, line.p1.y + roi_wh));
tem.roi = cv::boundingRect(tem.plist) & imgBounds;
if (tem.roi.width <= 0 || tem.roi.height <= 0) continue;
tem.plist.push_back(cv::Point(line.p1.x, line.p1.y + range_offset));
tem.plist.push_back(cv::Point(line.p2.x, line.p2.y + range_offset));
tem.plist.push_back(cv::Point(line.p2.x, line.p2.y + range_offset + roi_wh));
tem.plist.push_back(cv::Point(line.p1.x, line.p1.y + range_offset + roi_wh));
tem.rrect = cv::minAreaRect(tem.plist);
tem.roi = tem.rrect.boundingRect() & imgBounds;
if (tem.rrect.size.width <= 0 || tem.rrect.size.height <= 0) continue;
pDetConfig->edge_det_roi.push_back(tem);
up_det_roi.push_back(tem);
}
for (const auto &line : down_line)
{
Det_ROI_Config tem;
tem.plist.push_back(line.p1);
tem.plist.push_back(line.p2);
tem.plist.push_back(cv::Point(line.p2.x, line.p2.y - roi_wh));
tem.plist.push_back(cv::Point(line.p1.x, line.p1.y - roi_wh));
tem.roi = cv::boundingRect(tem.plist) & imgBounds;
if (tem.roi.width <= 0 || tem.roi.height <= 0) continue;
tem.plist.push_back(cv::Point(line.p1.x, line.p1.y - range_offset));
tem.plist.push_back(cv::Point(line.p2.x, line.p2.y - range_offset));
tem.plist.push_back(cv::Point(line.p2.x, line.p2.y - range_offset - roi_wh));
tem.plist.push_back(cv::Point(line.p1.x, line.p1.y - range_offset - roi_wh));
tem.rrect = cv::minAreaRect(tem.plist);
tem.roi = tem.rrect.boundingRect() & imgBounds;
if (tem.rrect.size.width <= 0 || tem.rrect.size.height <= 0) continue;
pDetConfig->edge_det_roi.push_back(tem);
down_det_roi.push_back(tem);
}
for (const auto &line : left_line)
{
Det_ROI_Config tem;
tem.plist.push_back(line.p1);
tem.plist.push_back(line.p2);
tem.plist.push_back(cv::Point(line.p2.x + roi_wh, line.p2.y));
tem.plist.push_back(cv::Point(line.p1.x + roi_wh, line.p1.y));
tem.roi = cv::boundingRect(tem.plist) & imgBounds;
if (tem.roi.width <= 0 || tem.roi.height <= 0) continue;
tem.plist.push_back(cv::Point(line.p1.x + range_offset, line.p1.y));
tem.plist.push_back(cv::Point(line.p2.x + range_offset, line.p2.y));
tem.plist.push_back(cv::Point(line.p2.x + range_offset + roi_wh, line.p2.y));
tem.plist.push_back(cv::Point(line.p1.x + range_offset + roi_wh, line.p1.y));
tem.rrect = cv::minAreaRect(tem.plist);
tem.roi = tem.rrect.boundingRect() & imgBounds;
if (tem.rrect.size.width <= 0 || tem.rrect.size.height <= 0) continue;
pDetConfig->edge_det_roi.push_back(tem);
left_det_roi.push_back(tem);
}
for (const auto &line : right_line)
{
Det_ROI_Config tem;
tem.plist.push_back(line.p1);
tem.plist.push_back(line.p2);
tem.plist.push_back(cv::Point(line.p2.x - roi_wh, line.p2.y));
tem.plist.push_back(cv::Point(line.p1.x - roi_wh, line.p1.y));
tem.roi = cv::boundingRect(tem.plist) & imgBounds;
if (tem.roi.width <= 0 || tem.roi.height <= 0) continue;
tem.plist.push_back(cv::Point(line.p1.x - range_offset, line.p1.y));
tem.plist.push_back(cv::Point(line.p2.x - range_offset, line.p2.y));
tem.plist.push_back(cv::Point(line.p2.x - range_offset - roi_wh, line.p2.y));
tem.plist.push_back(cv::Point(line.p1.x - range_offset - roi_wh, line.p1.y));
tem.rrect = cv::minAreaRect(tem.plist);
tem.roi = tem.rrect.boundingRect() & imgBounds;
if (tem.rrect.size.width <= 0 || tem.rrect.size.height <= 0) continue;
pDetConfig->edge_det_roi.push_back(tem);
right_det_roi.push_back(tem);
}
@ -602,7 +613,10 @@ int Edge_QX_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig)
}
for (const auto &r : pDetConfig->edge_det_roi)
{
cv::rectangle(showimg, r.roi, cv::Scalar(255, 0, 255), 3); // 黄色角点
cv::Point2f vertices[4];
r.rrect.points(vertices);
for (int j = 0; j < 4; j++)
cv::line(showimg, vertices[j], vertices[(j+1)%4], cv::Scalar(255, 0, 255), 3);
}
for (const auto r : pDetConfig->qx_result)
{
@ -1072,29 +1086,38 @@ int Edge_QX_Det::Det_qx(const cv::Mat &img, std::vector<Det_ROI_Config> roilist,
return -12;
}
Base_Function_Edge_Det *pedgeDet = &pDetConfig->pBaseCheckFunction->edgeDet;
vector<cv::Point> allPoints;
if (roilist.empty())
{
return 1;
}
cv::Rect DetRoi;
for (const auto &ROI : roilist)
{
allPoints.insert(allPoints.end(), ROI.plist.begin(), ROI.plist.end());
DetRoi = DetRoi | ROI.roi;
}
if (allPoints.size() <= 0)
if (DetRoi.width <= 0 || DetRoi.height <= 0)
{
return 1;
}
cv::Rect DetRoi = cv::boundingRect(allPoints);
cv::Mat roiMask = cv::Mat::zeros(DetRoi.height, DetRoi.width, CV_8UC1);
for (const auto &ROI : roilist)
{
cv::Mat mask;
applyMaskInROI(img, ROI, mask, pedgeDet->Det_threshold);
if (mask.empty())
continue;
cv::Rect detimg_roi;
detimg_roi.x = ROI.roi.x - DetRoi.x;
detimg_roi.y = ROI.roi.y - DetRoi.y;
detimg_roi.width = ROI.roi.width;
detimg_roi.height = ROI.roi.height;
mask.copyTo(roiMask(detimg_roi), mask);
detimg_roi.width = mask.cols; // 使用 mask 实际尺寸,而非 ROI.roi 尺寸,避免裁剪后不一致
detimg_roi.height = mask.rows;
// 安全检查:确保 detimg_roi 在 roiMask 范围内
cv::Rect safeDetRoi = detimg_roi & cv::Rect(0, 0, roiMask.cols, roiMask.rows);
if (safeDetRoi.width <= 0 || safeDetRoi.height <= 0)
continue;
mask.copyTo(roiMask(safeDetRoi), mask);
}
int erx = pedgeDet->QX_Widht_min;
int ery = pedgeDet->QX_Height_min;
@ -1257,6 +1280,66 @@ int Edge_QX_Det::Det_qx(const cv::Mat &img, std::vector<Det_ROI_Config> roilist,
return 0;
}
// ===== 多边形模式缺陷检测:无方向/角点过滤逐ROI独立处理避免巨型mask =====
int Edge_QX_Det::Det_qx_polygon(const cv::Mat &img, const std::vector<Det_ROI_Config> &roilist, DetConfigResult *pDetConfig)
{
if (img.empty()) return -11;
if (img.channels() != 1) return -12;
Base_Function_Edge_Det *pedgeDet = &pDetConfig->pBaseCheckFunction->edgeDet;
if (roilist.empty()) return 1;
int erx = std::max(pedgeDet->QX_Widht_min, 3);
int ery = std::max(pedgeDet->QX_Height_min, 3);
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(erx, ery));
for (const auto &ROI : roilist)
{
cv::Rect safeRoi = ROI.roi & cv::Rect(0, 0, img.cols, img.rows);
if (safeRoi.width <= 0 || safeRoi.height <= 0) continue;
// 二值化:暗区(产品)=255
cv::Mat binary;
cv::compare(img(safeRoi), pedgeDet->Det_threshold, binary, cv::CMP_LT);
// 多边形 mask局部坐标
std::vector<cv::Point> localPts;
localPts.reserve(ROI.plist.size());
for (const auto &pt : ROI.plist)
localPts.emplace_back(pt.x - safeRoi.x, pt.y - safeRoi.y);
cv::Mat polyMask = cv::Mat::zeros(safeRoi.size(), CV_8UC1);
cv::fillPoly(polyMask, std::vector<std::vector<cv::Point>>{localPts}, 255);
// 应用 mask
cv::Mat result = cv::Mat::zeros(safeRoi.size(), CV_8UC1);
binary.copyTo(result, polyMask);
// 形态学开操作
cv::morphologyEx(result, result, cv::MORPH_OPEN, kernel);
// 找轮廓 → 尺寸过滤
std::vector<std::vector<cv::Point>> contours;
cv::findContours(result, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
for (size_t i = 0; i < contours.size(); ++i)
{
cv::Rect rect = cv::boundingRect(contours[i]);
if (rect.width >= pedgeDet->QX_Widht_min && rect.width <= pedgeDet->QX_Widht_max &&
rect.height >= pedgeDet->QX_Height_min && rect.height <= pedgeDet->QX_Height_max)
{
QX_Result tem;
tem.roi_src.x = rect.x + safeRoi.x;
tem.roi_src.y = rect.y + safeRoi.y;
tem.roi_src.width = rect.width;
tem.roi_src.height = rect.height;
tem.area_pixel = cv::contourArea(contours[i]);
pDetConfig->qx_result.push_back(tem);
}
}
}
return 0;
}
int Edge_QX_Det::applyMaskInROI(const cv::Mat &grayImg, const Det_ROI_Config &config, cv::Mat &result, int threshold)
{
// 0. 裁剪 ROI防止 RANSAC 投影后越界
@ -1268,11 +1351,9 @@ int Edge_QX_Det::applyMaskInROI(const cv::Mat &grayImg, const Det_ROI_Config &co
}
// 1. 获取 ROI 区域图像(不 clone只引用
cv::Mat roiGray = grayImg(safeRoi);
// cv::imwrite("roiGray.png", roiGray);
// 2. 二值化(用 compare 更快)
cv::Mat binary;
cv::compare(roiGray, threshold, binary, cv::CMP_LT); // binary = roiGray > 128 ? 255 : 0
// cv::imwrite("binary.png", binary);
cv::compare(roiGray, threshold, binary, cv::CMP_LT); // binary = gray < threshold ? 255 : 0
// 3. 构建局部坐标的多边形(相对于裁剪后的 safeRoi
std::vector<cv::Point> localPts;
localPts.reserve(config.plist.size());
@ -1282,11 +1363,9 @@ int Edge_QX_Det::applyMaskInROI(const cv::Mat &grayImg, const Det_ROI_Config &co
// 4. 快速创建 mask 并填充
cv::Mat mask = cv::Mat::zeros(roiGray.size(), CV_8UC1);
cv::fillPoly(mask, std::vector<std::vector<cv::Point>>{localPts}, 255);
// cv::imwrite("mask.png", mask);
// 5. 应用 mask
result = cv::Mat::zeros(roiGray.size(), CV_8UC1);
binary.copyTo(result, mask);
// cv::imwrite("result.png", result);
return 0;
}
@ -1313,8 +1392,8 @@ int Edge_QX_Det::Draw_Det(const cv::Mat &img, DetConfigResult *pDetConfig)
cv::Point pc;
if (pDetConfig->alginResult.H.empty())
{
pc.x = p.x - pDetConfig->alginResult.corpRoi.x + pDetConfig->alginResult.offtx;
pc.y = p.y - pDetConfig->alginResult.corpRoi.y + pDetConfig->alginResult.offty;
pc.x = p.x - pDetConfig->alginResult.corpRoi.x;
pc.y = p.y - pDetConfig->alginResult.corpRoi.y;
}
else
{
@ -1397,6 +1476,190 @@ int Edge_QX_Det::Draw_Det(const cv::Mat &img, DetConfigResult *pDetConfig)
return 0;
}
int Edge_QX_Det::Draw_Det_Align(const cv::Mat &img, DetConfigResult *pDetConfig)
{
Base_Function_Edge_Det *pedgeDet = &pDetConfig->pBaseCheckFunction->edgeDet;
if (pedgeDet->Align_region.size() <= 2)
{
return 1;
}
// ===== 第1步精细化边缘点 =====
// 在每个Align_region点周围100x100区域内用二值化+轮廓找最接近中心的实际边缘点
std::vector<cv::Point> Det_region;
for(auto p : pedgeDet->Align_region)
{
cv::Rect orig_roi(p.x - 50, p.y - 50, 100, 100);
cv::Rect c_roi_100 = orig_roi & cv::Rect(0, 0, img.cols, img.rows);
if (c_roi_100.width <= 0 || c_roi_100.height <= 0)
{
Det_region.push_back(p);
continue;
}
cv::Mat c_img = img(c_roi_100);
// 二值化产品区域为暗低灰度背景为亮高灰度THRESH_BINARY_INV 使暗区变白
cv::Mat binary;
cv::threshold(c_img, binary, pedgeDet->Det_threshold, 255, cv::THRESH_BINARY_INV);
// 找轮廓
std::vector<std::vector<cv::Point>> contours;
cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
// 找最接近中心的边缘点
// 中心在原始100x100区域中为(50,50),裁剪后需要偏移
cv::Point center_in_roi(50 - (orig_roi.x - c_roi_100.x), 50 - (orig_roi.y - c_roi_100.y));
cv::Point best_pt;
double best_dist = 1e10;
bool found = false;
for (const auto& contour : contours)
{
for (const auto& pt : contour)
{
double dist = (pt.x - center_in_roi.x) * (pt.x - center_in_roi.x) +
(pt.y - center_in_roi.y) * (pt.y - center_in_roi.y);
if (dist < best_dist)
{
best_dist = dist;
best_pt = pt;
found = true;
}
}
}
if (found)
Det_region.push_back(cv::Point(best_pt.x + c_roi_100.x, best_pt.y + c_roi_100.y));
else
Det_region.push_back(p); // 未找到边缘点则回退使用原始点
}
if (Det_region.size() <= 2)
{
return 1;
}
// ===== 第2步计算向内偏移的多边形 =====
// 使用多边形有向面积判断顶点顺序,确保向内法向量方向正确
int inward_offset = pedgeDet->Det_Range; // 使用配置的检测范围作为内缩距离
int range_offset = pedgeDet->Det_Range_Offset; // 可选的额外偏移量
if (inward_offset <= 0) inward_offset = 50;
size_t n = Det_region.size();
// 计算有向面积判断多边形方向CCW为正
float signed_area = 0;
for (size_t i = 0; i < n; i++)
{
size_t j = (i + 1) % n;
signed_area += (float)Det_region[i].x * Det_region[j].y -
(float)Det_region[j].x * Det_region[i].y;
}
bool isCCW = (signed_area > 0); // 逆时针: 左法线指向内部
std::vector<cv::Point2f> inner_pts(n);
std::vector<cv::Point2f> outer_pts(n);
for (size_t i = 0; i < n; i++)
{
cv::Point2f prev = Det_region[(i + n - 1) % n];
cv::Point2f curr = Det_region[i];
cv::Point2f next = Det_region[(i + 1) % n];
// 入边方向
cv::Point2f dir1 = curr - prev;
float len1 = cv::norm(dir1);
if (len1 > 1e-6f) dir1 = dir1 / len1;
// 出边方向
cv::Point2f dir2 = next - curr;
float len2 = cv::norm(dir2);
if (len2 > 1e-6f) dir2 = dir2 / len2;
// 向内法向量
cv::Point2f normal1, normal2;
if (isCCW)
{
normal1 = cv::Point2f(-dir1.y, dir1.x); // 左法线 = 向内CCW
normal2 = cv::Point2f(-dir2.y, dir2.x);
}
else
{
normal1 = cv::Point2f(dir1.y, -dir1.x); // 右法线 = 向内CW
normal2 = cv::Point2f(dir2.y, -dir2.x);
}
// 角平分线方向
cv::Point2f bisector = normal1 + normal2;
float bis_len = cv::norm(bisector);
if (bis_len < 1e-6f)
{
bisector = normal1; // 两边共线退化情况
bis_len = cv::norm(bisector);
}
if (bis_len > 1e-6f)
bisector = bisector / bis_len;
// 内边界 = range_offset + inward_offsetROI高度仍为 inward_offset
inner_pts[i] = curr + (range_offset + inward_offset) * bisector;
// 外边界 = range_offset整个ROI向产品内部平移 range_offset
outer_pts[i] = curr + range_offset * bisector;
}
// ===== 第3步生成检测ROI =====
cv::Rect imgBounds(0, 0, img.cols, img.rows);
for (size_t i = 0; i < n; i++)
{
size_t j = (i + 1) % n;
Det_ROI_Config tem;
tem.plist.push_back(cv::Point(cvRound(outer_pts[i].x), cvRound(outer_pts[i].y)));
tem.plist.push_back(cv::Point(cvRound(outer_pts[j].x), cvRound(outer_pts[j].y)));
tem.plist.push_back(cv::Point(cvRound(inner_pts[j].x), cvRound(inner_pts[j].y)));
tem.plist.push_back(cv::Point(cvRound(inner_pts[i].x), cvRound(inner_pts[i].y)));
tem.rrect = cv::minAreaRect(tem.plist);
tem.roi = tem.rrect.boundingRect() & imgBounds;
if (tem.rrect.size.width <= 0 || tem.rrect.size.height <= 0) continue;
pDetConfig->edge_det_roi.push_back(tem);
}
// ===== 第4步缺陷检测多边形模式逐ROI独立处理 =====
Det_qx_polygon(img, pDetConfig->edge_det_roi, pDetConfig);
if (bshowimg)
{
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
// 绘制外多边形(边缘点连线)
for (size_t i = 0; i < n; i++)
{
size_t j = (i + 1) % n;
cv::line(showimg, Det_region[i], Det_region[j], cv::Scalar(0, 255, 0), 2);
cv::circle(showimg, Det_region[i], 4, cv::Scalar(0, 255, 255), -1);
}
// 绘制内缩多边形
for (size_t i = 0; i < n; i++)
{
size_t j = (i + 1) % n;
cv::Point pi(cvRound(inner_pts[i].x), cvRound(inner_pts[i].y));
cv::Point pj(cvRound(inner_pts[j].x), cvRound(inner_pts[j].y));
cv::line(showimg, pi, pj, cv::Scalar(255, 0, 0), 2);
}
// 绘制检测ROI
for (const auto &r : pDetConfig->edge_det_roi)
{
cv::Point2f vertices[4];
r.rrect.points(vertices);
for (int j = 0; j < 4; j++)
cv::line(showimg, vertices[j], vertices[(j+1)%4], cv::Scalar(255, 0, 255), 2);
}
// 绘制检测到的缺陷
for (const auto &r : pDetConfig->qx_result)
{
cv::rectangle(showimg, r.roi_src, cv::Scalar(255, 22, 100), 3);
}
cv::imwrite(pDetConfig->strChannel + "_edge_align_show.png", showimg);
}
return 0;
}
int Edge_QX_Det::UDNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit)
{
if (img.empty())

@ -451,12 +451,12 @@ Point2f GetCoorPoint(Point2f point, Mat img_mat)
return new_point;
}
int GetEdgeRoi(Mat img, Rect &new_roi, float scale_x, float scale_y){
int GetEdgeRoi(Mat img, Rect &new_roi, cv::RotatedRect &rotated_roi, float scale_x, float scale_y){
if (img.empty())
{
return 1;
}
// 缩小,减少耗时
// ============ Stage 1: 粗定位(大尺度缩小,速度快)============
Mat r_img;
int resize_width = static_cast<int>(img.cols / scale_x);
@ -489,22 +489,116 @@ int GetEdgeRoi(Mat img, Rect &new_roi, float scale_x, float scale_y){
return 3;
}
cv::Rect small_roi = cv::boundingRect(contours[maxAreaIdx]);
Rect roi;
roi.x = static_cast<int>(small_roi.x * scale_x);
roi.y = static_cast<int>(small_roi.y * scale_y);
roi.width = static_cast<int>(small_roi.width * scale_x);
roi.height = static_cast<int>(small_roi.height * scale_y);
roi.x = std::max(0, roi.x);
roi.y = std::max(0, roi.y);
roi.width = std::min(roi.width, img.cols - roi.x);
roi.height = std::min(roi.height, img.rows - roi.y);
// 使用minAreaRect获取带旋转角度的最小外接矩形
cv::RotatedRect coarse_rotated_tmp = cv::minAreaRect(contours[maxAreaIdx]);
cv::RotatedRect coarse_rotated;
coarse_rotated.center.x = coarse_rotated_tmp.center.x * scale_x;
coarse_rotated.center.y = coarse_rotated_tmp.center.y * scale_y;
coarse_rotated.size.width = coarse_rotated_tmp.size.width * scale_x;
coarse_rotated.size.height = coarse_rotated_tmp.size.height * scale_y;
coarse_rotated.angle = coarse_rotated_tmp.angle;
cv::Rect coarse_roi = coarse_rotated.boundingRect();
coarse_roi.x = std::max(0, coarse_roi.x);
coarse_roi.y = std::max(0, coarse_roi.y);
coarse_roi.width = std::min(coarse_roi.width, img.cols - coarse_roi.x);
coarse_roi.height = std::min(coarse_roi.height, img.rows - coarse_roi.y);
// ============ Stage 2: 精修(小尺度,只处理裁剪后的局部区域)============
// 粗定位精度损失约 scale_x/scale_y 个像素,扩展 margin 确保包含真实边界
const float fine_scale = 4.0f; // 精修阶段缩放倍率,越小越精确
int margin_x = static_cast<int>(scale_x * 2); // 补偿粗定位误差
int margin_y = static_cast<int>(scale_y * 2);
Rect fine_roi;
fine_roi.x = std::max(0, coarse_roi.x - margin_x);
fine_roi.y = std::max(0, coarse_roi.y - margin_y);
fine_roi.width = std::min(coarse_roi.width + 2 * margin_x, img.cols - fine_roi.x);
fine_roi.height = std::min(coarse_roi.height + 2 * margin_y, img.rows - fine_roi.y);
Mat fine_region = img(fine_roi);
int fine_w = static_cast<int>(fine_region.cols / fine_scale);
int fine_h = static_cast<int>(fine_region.rows / fine_scale);
// 精修区域足够大时才做细化
if (fine_w > 50 && fine_h > 50)
{
Mat fine_resized;
resize(fine_region, fine_resized, Size(fine_w, fine_h), 0, 0, INTER_LINEAR);
Mat fine_bin;
threshold(fine_resized, fine_bin, 15, 255, THRESH_BINARY);
std::vector<std::vector<cv::Point>> fine_contours;
cv::findContours(fine_bin, fine_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
if (!fine_contours.empty())
{
double fine_maxArea = 0;
int fine_maxIdx = -1;
for (size_t i = 0; i < fine_contours.size(); ++i)
{
double area = cv::contourArea(fine_contours[i]);
if (area > fine_maxArea)
{
fine_maxArea = area;
fine_maxIdx = i;
}
}
new_roi = roi;
if (fine_maxIdx >= 0)
{
// 使用minAreaRect获取带旋转角度的最小外接矩形保留旋转信息
cv::RotatedRect fine_rotated = cv::minAreaRect(fine_contours[fine_maxIdx]);
// 映射回原图坐标center缩放+平移size按比例缩放角度不变
rotated_roi.center.x = fine_rotated.center.x * fine_scale + fine_roi.x;
rotated_roi.center.y = fine_rotated.center.y * fine_scale + fine_roi.y;
rotated_roi.size.width = fine_rotated.size.width * fine_scale;
rotated_roi.size.height = fine_rotated.size.height * fine_scale;
rotated_roi.angle = fine_rotated.angle;
// 取旋转矩形的轴对齐外接框作为new_roi用于ROI裁剪等场景
cv::Rect fine_small = rotated_roi.boundingRect();
Rect refined_roi;
refined_roi.x = fine_small.x;
refined_roi.y = fine_small.y;
refined_roi.width = fine_small.width;
refined_roi.height = fine_small.height;
refined_roi.x = std::max(0, refined_roi.x);
refined_roi.y = std::max(0, refined_roi.y);
refined_roi.width = std::min(refined_roi.width, img.cols - refined_roi.x);
refined_roi.height = std::min(refined_roi.height, img.rows - refined_roi.y);
new_roi = refined_roi;
return 0;
}
}
}
// 精修失败则回退到粗定位结果
new_roi = coarse_roi;
rotated_roi = coarse_rotated;
return 0;
}
std::vector<cv::Point2f> sort_vertices(cv::RotatedRect rrect) {
cv::Point2f pts[4];
rrect.points(pts);
std::vector<cv::Point2f> vertices(pts, pts + 4);
// 按 y 坐标升序排序
std::sort(vertices.begin(), vertices.end(),
[](const cv::Point2f& a, const cv::Point2f& b) {
return a.y < b.y;
});
if (vertices[0].x > vertices[1].x)
std::swap(vertices[0], vertices[1]);
if (vertices[2].x > vertices[3].x)
std::swap(vertices[2], vertices[3]);
return vertices;
}
int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update){
if (img.empty()) {
std::cerr << "Error: Input image 'img' is empty!" << std::endl;
@ -513,16 +607,17 @@ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update){
if(!b_update){
return 1;
}
int get_edge_roi = GetEdgeRoi(img, cur_roi, 20, 20);
cv::RotatedRect rot_cur_roi;
int get_edge_roi = GetEdgeRoi(img, cur_roi, rot_cur_roi, 20, 20);
if(get_edge_roi != 0){
return 2;
}
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "-------------------start--------------");
/*计算xy偏移缩放比例*/
// 拷贝原始数据
if(m_old_productROI.width == 0 || m_old_productROI.height == 0){
m_old_productROI = m_AnalysisyConfig.baseFunction.markLine.productROI;
// 拷贝原始数据old_productROI 使用 markLine.region 的 minAreaRect保留旋转角度
if(m_old_productROI.size.width == 0 || m_old_productROI.size.height == 0){
m_old_productROI = cv::minAreaRect(m_AnalysisyConfig.baseFunction.markLine.region);
m_old_cur_edgeDet_region = m_AnalysisyConfig.baseFunction.edgeDet.region;
m_old_cur_markLine_region = m_AnalysisyConfig.baseFunction.markLine.region;
m_old_cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1;
@ -530,23 +625,35 @@ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update){
m_old_cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr;
m_old_cur_traditional_region = m_pbaseCheckFunction->traditionDet.detArea;
}
Rect old_roi = m_old_productROI;
Point old_center(old_roi.x + old_roi.width / 2, old_roi.y + old_roi.height / 2);
Point new_center(cur_roi.x + cur_roi.width / 2, cur_roi.y + cur_roi.height / 2);
int x_offset = new_center.x - old_center.x;
int y_offset = new_center.y - old_center.y;
float scale_x = (float)cur_roi.width / (float)old_roi.width;
float scale_y = (float)cur_roi.height / (float)old_roi.height;
/*计算old_roi到new_roi的完整仿射变换矩阵(平移+缩放+旋转)*/
// old使用 minAreaRect(region) 的顶点new使用 GetEdgeRoi 检测到的旋转矩形顶点
vector<cv::Point2f> old_vertices = sort_vertices(m_old_productROI);
vector<cv::Point2f> new_vertices = sort_vertices(rot_cur_roi);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "old_roi = %d %d %d %d", old_roi.x, old_roi.y, old_roi.width, old_roi.height);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "cur_roi = %d %d %d %d", cur_roi.x, cur_roi.y, cur_roi.width, cur_roi.height);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "x_offset = %d y_offset = %d", x_offset, y_offset);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "scale_x = %f scale_y = %f", scale_x, scale_y);
if(abs(x_offset) < 50 && abs(y_offset) < 50 && abs(scale_x - 1) < 0.0001 && abs(scale_y - 1) < 0.0001 ){
return 3;
}
cv::Point2f src_pts[3] = {
old_vertices[0], // 左上
old_vertices[1], // 右上
old_vertices[2] // 左下
};
cv::Point2f dst_pts[3] = {
new_vertices[0], // 对应左上
new_vertices[1], // 对应右上
new_vertices[2] // 对应左下
};
cv::Mat affine_mat = cv::getAffineTransform(src_pts, dst_pts);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "affine_mat = [%f %f %f; %f %f %f]",
affine_mat.at<double>(0,0), affine_mat.at<double>(0,1), affine_mat.at<double>(0,2),
affine_mat.at<double>(1,0), affine_mat.at<double>(1,1), affine_mat.at<double>(1,2));
// 单点仿射变换的lambda (直接使用矩阵,涵盖平移+缩放+旋转)
auto affinePoint = [&](const cv::Point& p) -> cv::Point {
return cv::Point(
cvRound(affine_mat.at<double>(0,0) * p.x + affine_mat.at<double>(0,1) * p.y + affine_mat.at<double>(0,2)),
cvRound(affine_mat.at<double>(1,0) * p.x + affine_mat.at<double>(1,1) * p.y + affine_mat.at<double>(1,2))
);
};
/*获取待修改的region引用*/
std::vector<cv::Point>& cur_edgeDet_region = m_AnalysisyConfig.baseFunction.edgeDet.region;
@ -557,57 +664,100 @@ int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update){
cv::Rect& cur_traditional_rect = m_pbaseCheckFunction->traditionDet.detArea_ROI;
std::vector<cv::Point>& cur_traditional_region = m_pbaseCheckFunction->traditionDet.detArea;
/*进行修改*/
// if (img.empty())
// {
// return 0;
// }
// Mat show_img = img.clone();
// cvtColor(show_img, show_img, COLOR_GRAY2BGR);
// // 确保 productROI 在图像范围内
// cv::Rect safe_roi = m_AnalysisyConfig.baseFunction.markLine.productROI;
// safe_roi &= cv::Rect(0, 0, show_img.cols, show_img.rows);
// if (safe_roi.width > 0 && safe_roi.height > 0)
// {
// cv::rectangle(show_img, safe_roi, Scalar(255,255,255), 5);
// }
// if (cur_edgeDet_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_edgeDet_region.size() - 1; i++){
// cv::line(show_img, cur_edgeDet_region[i], cur_edgeDet_region[i+1], Scalar(0,255,0), 20);
// }
// cv::line(show_img, cur_edgeDet_region.back(), cur_edgeDet_region.front(), Scalar(0,255,0), 20);
// }
// if (cur_markLine_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_markLine_region.size() - 1; i++){
// cv::line(show_img, cur_markLine_region[i], cur_markLine_region[i+1], Scalar(0,0,255), 20);
// }
// cv::line(show_img, cur_markLine_region.back(), cur_markLine_region.front(), Scalar(0,0,255), 20);
// }
// for(size_t i = 0 ; i < cur_regionConfigArr.size(); i++){
// if (cur_regionConfigArr[i].basicInfo.pointArry.size() >= 2)
// {
// for(size_t j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size() - 1; j++){
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry[j], cur_regionConfigArr[i].basicInfo.pointArry[j+1], Scalar(255,0,0), 10);
// }
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry.back(), cur_regionConfigArr[i].basicInfo.pointArry.front(), Scalar(255,0,0), 10);
// }
// }
// imwrite(m_AnalysisyConfig.commonCheckConfig.baseConfig.strCamearName +"_org_img.tiff", show_img);
/*使用仿射矩阵进行修改*/
// rect
m_AnalysisyConfig.baseFunction.markLine.productROI = cur_roi;
// point
cur_markLine_mark1.x = m_old_cur_markLine_mark1.x + x_offset;
cur_markLine_mark1.y = m_old_cur_markLine_mark1.y + y_offset;
cur_markLine_mark1 = Point((cur_markLine_mark1.x - new_center.x) * scale_x + new_center.x, (cur_markLine_mark1.y - new_center.y) * scale_y + new_center.y);
cur_markLine_mark2.x = m_old_cur_markLine_mark2.x + x_offset;
cur_markLine_mark2.y = m_old_cur_markLine_mark2.y + y_offset;
cur_markLine_mark2 = Point((cur_markLine_mark2.x - new_center.x) * scale_x + new_center.x, (cur_markLine_mark2.y - new_center.y) * scale_y + new_center.y);
cur_markLine_mark1 = affinePoint(m_old_cur_markLine_mark1);
cur_markLine_mark2 = affinePoint(m_old_cur_markLine_mark2);
// region
for(int i = 0; i < cur_edgeDet_region.size(); i++){
cur_edgeDet_region[i].x = m_old_cur_edgeDet_region[i].x + x_offset;
cur_edgeDet_region[i].y = m_old_cur_edgeDet_region[i].y + y_offset;
cur_edgeDet_region[i] = Point((cur_edgeDet_region[i].x - new_center.x) * scale_x + new_center.x, (cur_edgeDet_region[i].y - new_center.y) * scale_y + new_center.y);
cur_edgeDet_region[i] = affinePoint(m_old_cur_edgeDet_region[i]);
}
for(int i = 0; i < cur_markLine_region.size(); i++){
cur_markLine_region[i].x = m_old_cur_markLine_region[i].x + x_offset;
cur_markLine_region[i].y = m_old_cur_markLine_region[i].y + y_offset;
cur_markLine_region[i] = Point((cur_markLine_region[i].x - new_center.x) * scale_x + new_center.x, (cur_markLine_region[i].y - new_center.y) * scale_y + new_center.y);
cur_markLine_region[i] = affinePoint(m_old_cur_markLine_region[i]);
}
for(int i = 0 ; i < cur_regionConfigArr.size(); i++){
for(int j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size(); j++){
cur_regionConfigArr[i].basicInfo.pointArry[j].x = m_old_cur_regionConfigArr[i].basicInfo.pointArry[j].x + x_offset;
cur_regionConfigArr[i].basicInfo.pointArry[j].y = m_old_cur_regionConfigArr[i].basicInfo.pointArry[j].y + y_offset;
cur_regionConfigArr[i].basicInfo.pointArry[j] = Point((cur_regionConfigArr[i].basicInfo.pointArry[j].x - new_center.x) * scale_x + new_center.x, (cur_regionConfigArr[i].basicInfo.pointArry[j].y - new_center.y) * scale_y + new_center.y);
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].x = m_old_cur_traditional_region[i].x + x_offset;
cur_traditional_region[i].y = m_old_cur_traditional_region[i].y + y_offset;
cur_traditional_region[i] = Point((cur_traditional_region[i].x - new_center.x) * scale_x + new_center.x, (cur_traditional_region[i].y - new_center.y) * scale_y + new_center.y);
cur_traditional_region[i] = affinePoint(m_old_cur_traditional_region[i]);
}
/*show*/
// Mat show_img = img.clone();
// cv::rectangle(show_img, m_AnalysisyConfig.baseFunction.markLine.productROI, Scalar(255), 5);
// if(cur_edgeDet_region.size() >=2){
// for(int i = 0 ; i < cur_edgeDet_region.size() - 1; i++){
// cv::line(show_img, cur_edgeDet_region[i], cur_edgeDet_region[i+1], Scalar(255), 20);
// if (img.empty())
// {
// return 0;
// }
// show_img = img.clone();
// cvtColor(show_img, show_img, COLOR_GRAY2BGR);
// // 确保 productROI 在图像范围内
// safe_roi = m_AnalysisyConfig.baseFunction.markLine.productROI;
// safe_roi &= cv::Rect(0, 0, show_img.cols, show_img.rows);
// if (safe_roi.width > 0 && safe_roi.height > 0)
// {
// cv::rectangle(show_img, safe_roi, Scalar(255,255,255), 5);
// }
// if (cur_edgeDet_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_edgeDet_region.size() - 1; i++){
// cv::line(show_img, cur_edgeDet_region[i], cur_edgeDet_region[i+1], Scalar(0,255,0), 20);
// }
// cv::line(show_img, cur_edgeDet_region.back(), cur_edgeDet_region.front(), Scalar(0,255,0), 20);
// }
// if(cur_markLine_region.size() >=2){
// for(int i = 0 ; i < cur_markLine_region.size() - 1; i++){
// cv::line(show_img, cur_markLine_region[i], cur_markLine_region[i+1], Scalar(255), 20);
// if (cur_markLine_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_markLine_region.size() - 1; i++){
// cv::line(show_img, cur_markLine_region[i], cur_markLine_region[i+1], Scalar(0,0,255), 20);
// }
// cv::line(show_img, cur_markLine_region.back(), cur_markLine_region.front(), Scalar(0,0,255), 20);
// }
// if(cur_regionConfigArr.size() >=2){
// for(int i = 0 ; i < cur_regionConfigArr.size(); i++){
// for(int j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size()-1; j++){
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry[j], cur_regionConfigArr[i].basicInfo.pointArry[j+1], Scalar(255), 20);
// for(size_t i = 0 ; i < cur_regionConfigArr.size(); i++){
// if (cur_regionConfigArr[i].basicInfo.pointArry.size() >= 2)
// {
// for(size_t j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size() - 1; j++){
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry[j], cur_regionConfigArr[i].basicInfo.pointArry[j+1], Scalar(255,0,0), 10);
// }
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry.back(), cur_regionConfigArr[i].basicInfo.pointArry.front(), Scalar(255,0,0), 10);
// }
// }
// imwrite(m_AnalysisyConfig.commonCheckConfig.baseConfig.strCamearName +"_show_img.tiff", show_img);
@ -766,7 +916,7 @@ int ImgCheckAnalysisy::SetNewConfig()
{
m_bupdateconfig = true;
// printf("************** ImgCheckAnalysisy::SetNewConfig m_nConfigIdx %d\n", m_nConfigIdx);
m_old_productROI = cv::Rect(0, 0, 0, 0);
m_old_productROI = cv::RotatedRect();
m_pConfig->GetConfig(ConfigType_Analysisy_Common_XL, &m_AnalysisyConfig);
if (m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.size() > 0)
{
@ -2226,7 +2376,13 @@ int ImgCheckAnalysisy::Edge_Qx_Det(const cv::Mat &img)
m_Edge_DetConfig.strChannel = m_strCurDetChannel;
m_Edge_DetConfig.pBaseCheckFunction = m_pbaseCheckFunction;
m_Edge_DetConfig.alginResult.corpRoi = m_Crop_Roi_paramImg;
m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region = m_AnalysisyConfig.baseFunction.markLine.region;
for(int i = 0; i < m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region.size(); i++)
{
m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region[i].x -= m_Crop_Roi_paramImg.x;
m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region[i].y -= m_Crop_Roi_paramImg.y;
}
if (m_pEdge_Align_Result && m_pEdge_Align_Result->buseOfft)
{
m_Edge_DetConfig.alginResult.offtx = m_pEdge_Align_Result->offt_x;

@ -408,6 +408,7 @@ struct BasicConfig
float fImage_Scale_x; // 成像精度
float fImage_Scale_y; // 成像精度
std::string strCamName; //
std::string strConfigVersion; // 配置版本
float density_R_mm; // 密度计算半径 像素
BasicConfig()
@ -429,6 +430,7 @@ struct BasicConfig
fImage_Scale_y = 0.03;
density_R_mm = 5;
strCamName = "";
strConfigVersion = "1.0";
strCamearName = EMPTY_CONFIG_NAME;
}
void copy(BasicConfig tem)
@ -452,6 +454,8 @@ struct BasicConfig
this->fImage_Scale_y = tem.fImage_Scale_y;
this->density_R_mm = tem.density_R_mm;
this->strCamearName = tem.strCamearName;
this->strConfigVersion = tem.strConfigVersion;
}
void print(std::string str = "")
{
@ -955,7 +959,7 @@ struct Function_ShieldRegion
{
return;
}
shieldMask = cv::Mat(img_H, img_W, CV_8U, cv::Scalar(0));
shieldMask = cv::Mat::zeros(img_H, img_W, CV_8U);
if (pointArry1.size() > 0)
{
cv::fillPoly(shieldMask, pointArry1, cv::Scalar(255));
@ -1082,7 +1086,7 @@ struct Function_EdgeROI
// {
// return;
// }
EdgeMask = cv::Mat(img_H, img_W, CV_8U, cv::Scalar(0));
EdgeMask = cv::Mat::zeros(img_H, img_W, CV_8U);
if (pointArry1.size() > 0)
{
@ -1191,7 +1195,7 @@ struct Function_Image_Align
// pointArry1[i].y -= boundingRect.y;
// }
cv::Mat tem_feature_Mask = cv::Mat(img_H, img_W, CV_8U, cv::Scalar(0));
cv::Mat tem_feature_Mask = cv::Mat::zeros(img_H, img_W, CV_8U);
if (pointArry1.size() > 0)
{
@ -1940,6 +1944,7 @@ struct Base_Function_Edge_Det
int Search_threshold; // 搜索边缘阈值
int Det_threshold; // 缺陷检测阈值
int Det_Range; // 检测范围
int Det_Range_Offset; // 检测范围偏移
int QX_Widht_min; // 缺陷宽度-最小
int QX_Widht_max;
int QX_Height_min;
@ -1953,8 +1958,10 @@ struct Base_Function_Edge_Det
int queJiao_height;
bool bDrawRoi;
bool bUseAlignRoi;
cv::Rect draw_ROI;
std::vector<cv::Point> region;
std::vector<cv::Point> Align_region;
bool bDrawResult; // 是否绘制结果
Base_Function_Edge_Det()
@ -1967,6 +1974,7 @@ struct Base_Function_Edge_Det
Search_threshold = 30;
Det_threshold = 30;
Det_Range = 100;
Det_Range_Offset = 0;
QX_Widht_min = 10;
QX_Widht_max = 100;
QX_Height_min = 10;
@ -1979,6 +1987,7 @@ struct Base_Function_Edge_Det
queJiao_width = 50;
queJiao_height = 50;
bDrawRoi = false;
bUseAlignRoi = false;
draw_ROI = cv::Rect(0, 0, 0, 0);
region.clear();
region.erase(region.begin(), region.end());
@ -1991,6 +2000,7 @@ struct Base_Function_Edge_Det
this->Search_threshold = tem.Search_threshold;
this->Det_threshold = tem.Det_threshold;
this->Det_Range = tem.Det_Range;
this->Det_Range_Offset = tem.Det_Range_Offset;
this->QX_Widht_min = tem.QX_Widht_min;
this->QX_Widht_max = tem.QX_Widht_max;
this->QX_Height_min = tem.QX_Height_min;
@ -2006,18 +2016,19 @@ struct Base_Function_Edge_Det
this->region.assign(tem.region.begin(), tem.region.end());
this->draw_ROI = tem.draw_ROI;
this->bDrawRoi = tem.bDrawRoi;
this->bUseAlignRoi = tem.bUseAlignRoi;
this->bDrawResult = tem.bDrawResult;
}
void print(std::string str)
{
printf("%s>>bOpen %d Search_threshold %d Det_threshold %d Det_Range %d QX_Widht [%d %d] QX_Height [%d %d]\n", str.c_str(),
bOpen, Search_threshold, Det_threshold, Det_Range, QX_Widht_min, QX_Widht_max, QX_Height_min, QX_Height_max);
printf("%s>>bOpen %d Search_threshold %d Det_threshold %d Det_Range %d Det_Range_Offset %d QX_Widht [%d %d] QX_Height [%d %d]\n", str.c_str(),
bOpen, Search_threshold, Det_threshold, Det_Range, Det_Range_Offset, QX_Widht_min, QX_Widht_max, QX_Height_min, QX_Height_max);
}
std::string GetInfo(std::string str)
{
char buffer[256];
sprintf(buffer, "%s>>bOpen %d Search_threshold %d Det_threshold %d Det_Range %d QX_Widht [%d %d] QX_Height [%d %d]\n", str.c_str(),
bOpen, Search_threshold, Det_threshold, Det_Range, QX_Widht_min, QX_Widht_max, QX_Height_min, QX_Height_max);
sprintf(buffer, "%s>>bOpen %d Search_threshold %d Det_threshold %d Det_Range %d Det_Range_Offset %d QX_Widht [%d %d] QX_Height [%d %d]\n", str.c_str(),
bOpen, Search_threshold, Det_threshold, Det_Range, Det_Range_Offset, QX_Widht_min, QX_Widht_max, QX_Height_min, QX_Height_max);
std::string str123 = buffer;
return str123;
}

@ -32,7 +32,7 @@ void CommonParamToCheckConfigJson::toObjectFromValue(Json::Value root)
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::Value rootvalue;
std::string err;
// std::cout << strJson << std::endl;
std::cout << strJson << std::endl;
auto nSize = strJson.size();
if (reader->parse(strJson.c_str(), strJson.c_str() + nSize, &rootvalue, &err))
{
@ -44,6 +44,11 @@ void CommonParamToCheckConfigJson::toObjectFromValue(Json::Value root)
// getchar();
if (value.isObject())
{
_config.baseConfig.strConfigVersion = value["version"].asString();
if ( _config.baseConfig.strConfigVersion == "")
{
_config.baseConfig.strConfigVersion = "NULL";
}
_config.baseConfig.image_widht = value["image_widht"].asInt();
_config.baseConfig.Image_height = value["Image_height"].asInt();
_config.baseConfig.bDrawShieldRoi = value["bDrawShieldRoi"].asBool();
@ -1248,6 +1253,11 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
_config.edgeDet.bDrawRoi = value_f["form"]["Draw_Config"]["Open"].asBool();
}
if (value_f["form"]["Draw_Config"]["bUse_Align"])
{
_config.edgeDet.bUseAlignRoi = value_f["form"]["Draw_Config"]["bUse_Align"].asBool();
}
// 2、读取区域点
{
auto value_region = value_f["form"]["Draw_Config"]["Edge_ROI"];

Loading…
Cancel
Save