【问题标题】:How to draw line not line segment OpenCV 2.4.2如何画线而不是线段OpenCV 2.4.2
【发布时间】:2012-10-21 01:48:10
【问题描述】:

这个问题说明了一切,

我知道函数Line(),它在两点之间绘制线段。

我需要画线不是一条线段,同样使用线段的两个点。


[EN:编辑之前发布的问题答案]

我使用了你的解决方案,它在水平线上的效果很好,但在垂直线上我仍然遇到问题。

例如,下面是一个使用点 [306,411] 和 [304,8](紫色)和画线(红色)的示例,在 600x600 像素的图像上。你有什么建议吗?

【问题讨论】:

    标签: opencv


    【解决方案1】:

    我知道这是一个非常古老的问题。我遇到了完全相同的问题,我使用了这个简单的代码:

    double Slope(int x0, int y0, int x1, int y1){
         return (double)(y1-y0)/(x1-x0);
    }
    
    void fullLine(cv::Mat *img, cv::Point a, cv::Point b, cv::Scalar color){
         double slope = Slope(a.x, a.y, b.x, b.y);
    
         Point p(0,0), q(img->cols,img->rows);
    
         p.y = -(a.x - p.x) * slope + a.y;
         q.y = -(b.x - q.x) * slope + b.y;
    
         line(*img,p,q,color,1,8,0);
    }
    

    首先我计算线段的斜率,然后我将线段“延伸”到图像的边界。我计算位于 x = 0 和 x = image.width 的线的新点。点本身可以​​在Image之外,这是一种恶作剧,但解决方法很简单。

    【讨论】:

    • 这是openCV的正确答案。选择的答案是垃圾。我复制并粘贴了这个,这很有效。非常感谢。
    • 如果 x1-x0 = 0 会崩溃。
    • 伟大的概念。转换为 python 并回答了一个问题 stackoverflow.com/a/59579392/9605907 。非常感谢!!
    【解决方案2】:

    您需要自己编写一个函数来执行此操作。我建议你把你的线放在 ax+by+c=0 形式中,然后将它与图像的 4 个边缘相交。请记住,如果您有一条 [a b c] 形式的线,找到它与另一条线的交点只是两者的叉积。你的图像的边缘是

    top_horizontal =    [0 1 0];
    left_vertical   =   [1 0 0];
    bottom_horizontal = [0 1 -image.rows];
    right_vertical =    [1 0 -image.cols];
    

    另外,如果你知道你的点之间的距离,你也可以在每个方向上沿着直线选择非常远的点,我认为交给 Line() 的点不需要在图像上。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,发现在 2.4.X OpenCV 上有一个 known bug,已经为较新的版本修复了。

      对于 2.4.X 版本,解决方案是在使用 cv::clipLine() 绘制之前剪切线

      这里有一个我对自己做的函数,在 2.4.13 OpenCV 上运行良好

      void Detector::drawFullImageLine(cv::Mat& img, const std::pair<cv::Point, cv::Point>& points, cv::Scalar color)
      {
          //points of line segment
          cv::Point p1 = points.first;
          cv::Point p2 = points.second;
      
          //points of line segment which extend the segment P1-P2 to 
          //the image borders.
          cv::Point p,q;
      
          //test if line is vertical, otherwise computes line equation
          //y = ax + b
          if (p2.x == p1.x)
          {
              p = cv::Point(p1.x, 0); 
              q = cv::Point(p1.x, img.rows); 
          }
          else
          {
              double a = (double)(p2.y - p1.y) / (double) (p2.x - p1.x);
              double b =  p1.y - a*p1.x;
      
              p = cv::Point(0, b);
              q = cv::Point(img.rows, a*img.rows + b);
      
              //clipline to the image borders. It prevents a known bug on OpenCV
              //versions 2.4.X when drawing 
              cv::clipLine(cv::Size(img.rows, img.cols), p, q);
          }
      
          cv::line(img, p, q, color, 2);
      }
      

      【讨论】:

      • cv::clipLine() 是 OpenCV 的正确解决方案。这应该被接受的答案。非常感谢
      • 这是最完整可靠的答案。
      • 这个q = cv::Point(img.rows, a*img.rows + b);不应该编辑成q = cv::Point(img.cols, a*img.cols + b);吗?
      【解决方案4】:

      这个答案是从 pajus_cz 答案派生出来的,但有一点改进。

      我们有两个点,我们需要得到直线方程y = mx + b才能画出直线。

      我们需要得到两个变量

      1- 坡度(米)

      2- b 在计算斜率b = y - mx 后,可以使用我们已有的两个点中的任何给定点通过直线方程检索。

      void drawStraightLine(cv::Mat *img, cv::Point2f p1, cv::Point2f p2, cv::Scalar color)
      {
              Point2f p, q;
              // Check if the line is a vertical line because vertical lines don't have slope
              if (p1.x != p2.x)
              {
                      p.x = 0;
                      q.x = img->cols;
                      // Slope equation (y1 - y2) / (x1 - x2)
                      float m = (p1.y - p2.y) / (p1.x - p2.x);
                      // Line equation:  y = mx + b
                      float b = p1.y - (m * p1.x);
                      p.y = m * p.x + b;
                      q.y = m * q.x + b;
              }
              else
              {
                      p.x = q.x = p2.x;
                      p.y = 0;
                      q.y = img->rows;
              }
      
              cv::line(*img, p, q, color, 1);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多