设置首页收藏本站
开启左侧

求助焊缝特征点识别图像处理算法

[复制链接]
1250990324 发表于 2024-6-18 17:19:15 | 显示全部楼层 |阅读模式
       目前我基于opencv用c++写了一个代码,但是总感觉笨笨的,因为刚接触图像处理,自己一个人实在是有太多不懂的,所以来请教各位大佬,看看有没有更好更简洁的办法。

线结构光扫描的焊缝图像

线结构光扫描的焊缝图像

       我需要将图中焊缝的顶点,也就是那个尖尖给检测到,还要尽可能的准确,由于这个图像在实际应用中不一定是朝上的,所以不能直接遍历所有点直接检测最高点。最好是通过拟合直线求交点的方式,把那个顶点计算出来。所以算法的关键是通过直线的拟合来找交点。我自己写的代码直线拟合的不是很好,经常丢直线,或者有重复直线,导致求交点经常出现一些奇怪的点。

我的检测结果如下图,最左边的直线检测不到拟合不上不知道为啥,改阈值也不行,不是最左边拟合不上就是最右边拟合不上,挺头疼的。而且求交点我写的也不好,我是让相邻两直线求交点,然后对交点进行筛选,保留最高点,这样在实际应用中是不行的,因为如果焊缝是歪的那这个检测的就不对了,我不清楚该怎么改筛选条件能确保把这个尖尖处的点给保留下来。

结果

结果

代码如下:
  1. Mat image, grayImg, binaryImg;
  2.     image = imread("C:\\Users\\86150\\Desktop\\tiliang.jpg");
  3.     //灰度二值化
  4.     cvtColor(image, grayImg, COLOR_BGR2GRAY);
  5.     threshold(grayImg, binaryImg, 50, 255, THRESH_BINARY);//阈值调节

  6.     // 霍夫直线检测
  7.     vector<Vec4i> lines; // 注意这里使用了 Vec4i,它包含了两个点的坐标 (x1, y1) 和 (x2, y2),表示直线的两个端点
  8.     HoughLinesP(binaryImg, lines, 1, CV_PI / 180, 10, 30, 30); // 参数可根据具体情况调整(后三个,阈值、最小直线长度、最大线段间隙)

  9.     // 创建彩色直线图像
  10.     Mat colorLinesImage = Mat::zeros(binaryImg.size(), CV_8UC3);

  11.     // 存储代表性直线和对应的斜率
  12.     vector<pair<Vec4i, double>> uniqueLinesWithSlope;

  13.     // 绘制直线并记录斜率
  14.     for (size_t i = 0; i < lines.size(); i++) {
  15.         Vec4i l = lines[/color][i][color=#2e8b57]; //l的存储大概是x,y。l[0]是第一个点的横坐标,l[1]是纵坐标
  16.         bool unique = true;

  17.         // 检查直线是否有效,避免起点和终点重合导致的问题
  18.         if (l[0] == l[2] && l[1] == l[3]) {
  19.             continue; // 起点和终点重合,跳过这条直线
  20.         }

  21.         // 计算当前直线的斜率
  22.         double dx = static_cast<double>(double(l[2]) - double(l[0]));
  23.         if (dx == 0.0) {
  24.             continue; // 避免除数为零的情况
  25.         }
  26.         double slope_current = static_cast<double>(double(l[3]) - double(l[1]) )/ dx;

  27.         // 遍历已有的代表性直线,判断是否与当前直线相似
  28.         for (size_t j = 0; j < uniqueLinesWithSlope.size(); j++) {
  29.             Vec4i ul = uniqueLinesWithSlope[j].first;
  30.             double slope_unique = uniqueLinesWithSlope[j].second;

  31.             // 判断当前直线与已有直线是否相似,小于的是阈值
  32.             if (abs(slope_current - slope_unique) < 0.07) {
  33.                 unique = false;
  34.                 break;
  35.             }
  36.         }

  37.         // 如果当前直线是独特的,则加入到代表性直线集合中
  38.         if (unique) {
  39.             uniqueLinesWithSlope.push_back(make_pair(l, slope_current));
  40.             // line(colorLinesImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, LINE_AA);//在colorLinesImage中显示图像
  41.             line(image, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, LINE_AA);//在image中显示图像
  42.         }
  43.     }


  44. // 对检测到的直线按照左端点的横坐标排序
  45.     sort(uniqueLinesWithSlope.begin(), uniqueLinesWithSlope.end(), [](const pair<Vec4i, double>& a, const pair<Vec4i, double>& b) {
  46.         return a.first[0] < b.first[0];
  47.         });

  48.     // 存储直线交点及其对应的直线索引
  49.     vector<pair<Point2f, pair<int, int>>> intersections;

  50.     // 对相邻直线进行遍历,找到斜率突变的直线并求交点
  51.     for (size_t i = 0; i < uniqueLinesWithSlope.size() - 1; i++) {
  52.         Vec4i line1 = uniqueLinesWithSlope[/color][i][color=#2e8b57].first;
  53.         double slope1 = uniqueLinesWithSlope[/color][i][color=#2e8b57].second;

  54.         Vec4i line2 = uniqueLinesWithSlope[i + 1].first;
  55.         double slope2 = uniqueLinesWithSlope[i + 1].second;

  56.         // 计算直线1的参数
  57.         double x1 = line1[0], y1 = line1[1], x2 = line1[2], y2 = line1[3];
  58.         double A1 = y2 - y1;
  59.         double B1 = x1 - x2;
  60.         double C1 = A1 * x1 + B1 * y1;

  61.         // 计算直线2的参数
  62.         double x3 = line2[0], y3 = line2[1], x4 = line2[2], y4 = line2[3];
  63.         double A2 = y4 - y3;
  64.         double B2 = x3 - x4;
  65.         double C2 = A2 * x3 + B2 * y3;

  66.         // 计算交点坐标
  67.         double det = A1 * B2 - A2 * B1;
  68.         if (det != 0) { // 确保直线不平行
  69.             double intersection_x = (B2 * C1 - B1 * C2) / det;
  70.             double intersection_y = (A1 * C2 - A2 * C1) / det;

  71.             // 将交点坐标及对应的直线索引添加到交点向量中
  72.             intersections.push_back(make_pair(Point2f(intersection_x, intersection_y), make_pair(i, i + 1)));
  73.         }
  74.     }

  75.     // 在彩色直线图像上绘制交点及其来源直线
  76.     for (const auto& intersection : intersections) {
  77.         Point2f point = intersection.first;
  78.         int line1_index = intersection.second.first;
  79.         int line2_index = intersection.second.second;

  80.         // 标注交点
  81.         circle(image, point, 5, Scalar(255, 0, 0), -1); // 以蓝色绘制交点
  82.          // 在交点附近标注直线索引
  83.         putText(image, "Line " + to_string(line1_index) + " & Line " + to_string(line2_index),
  84.             point + Point2f(10, -10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);
  85.     }

  86.     // 找到位置最高的交点,,要修改,最高点不准确
  87.     Point2f highestPoint;
  88.     bool foundHighestPoint = false;

  89.     for (const auto& intersection : intersections) {
  90.         Point2f point = intersection.first;
  91.         if (!foundHighestPoint || point.y < highestPoint.y) {
  92.             highestPoint = point;
  93.             foundHighestPoint = true;
  94.         }
  95.     }

  96.     // 在图像上绘制位置最高的交点及其坐标
  97.     if (foundHighestPoint) {
  98.         // 标注交点
  99.         circle(image, highestPoint, 5, Scalar(0, 255, 0), -1); // 以绿色绘制最高点

  100.         // 在交点附近标注坐标
  101.         putText(image, "(" + to_string(static_cast<int>(highestPoint.x)) + ", " + to_string(static_cast<int>(highestPoint.y)) + ")",
  102.             highestPoint + Point2f(10, -10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1);
  103.     }

  104.     //// 显示彩色直线图像
  105.     imshow("Detected Lines", image);
复制代码

奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| 1250990324 发表于 2024-6-18 17:20:10 | 显示全部楼层
恳请各位大佬救救孩子
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
8034zhang 发表于 2024-6-19 16:57:10 | 显示全部楼层
本帖最后由 8034zhang 于 2024-6-19 17:02 编辑

左边直线干扰区域较多
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| 1250990324 发表于 2024-6-19 18:05:42 | 显示全部楼层
8034zhang 发表于 2024-6-19 16:57
左边直线干扰区域较多

大佬请细说,那怎么才能拟合上呢
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
vc9181 发表于 2024-12-21 08:52:06 | 显示全部楼层
这是再做线激光相机引导机器人焊接呀
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表