11

这个问题说明了一切,

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

我需要画线而不是线段,也使用线段的两个点。


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

我使用了您的解决方案,它在水平线中表现良好,但在垂直线中仍然存在问题。

例如,下面的示例使用点 [306,411] 和 [304,8](紫色)以及绘制线(红色),在 600x600 像素的图像上。你有什么诀窍吗?

在此处输入图像描述

4

4 回答 4

10

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

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 之外,这是一种令人讨厌的技巧,但解决方法很简单。

于 2014-04-20T19:27:27.850 回答
6

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

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

此外,如果您对点之间的距离有所了解,您也可以在每个方向上沿线选择非常远的点,我认为交给 Line() 的点不需要在图像上。

于 2012-10-31T15:41:33.753 回答
5

我遇到了同样的问题,发现它是2.4.X OpenCV 上的一个已知错误,已针对较新版本进行了修复。

对于 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);
}
于 2017-03-30T14:14:27.527 回答
2

这个答案是从 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);
}
于 2015-01-19T17:38:15.687 回答