使用Opencv和C++在垂直方向的两点之间绘制直线

Posted

技术标签:

【中文标题】使用Opencv和C++在垂直方向的两点之间绘制直线【英文标题】:Draw Straight line between two points in vertical orientation using Opencv and C++ 【发布时间】:2017-08-23 03:57:18 【问题描述】:

我尝试使用两个参考点绘制一条直线,但在垂直方向上遇到了一些问题。

这是当前的源代码:

cv::Mat img = cv::Mat::zeros(600,600,CV_8UC3);
cv::Point p1(306,41);
cv::Point p2(304,8);

cv::Point p(0,0), q(img.cols, img.rows);
if (p1.x != p2.x) 
    double m = (double) (p1.y - p2.y) / (double) (p1.x - p2.x);
    double 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::circle(img, p1, 4, cv::Scalar(255,0,255), -1);
cv::circle(img, p2, 4, cv::Scalar(255,0,255), -1);
cv::line(img, p, q, cv::Scalar(0,0,255), 2);

这是以下输出:

我做错了什么?

【问题讨论】:

我猜cv::line(img, p1, p2, cv::Scalar(0,0,255), 2); 不是你想要的,对吧? 嗨@Miki,我想要一条完整的线穿过图像并使用 p1 和 p2 点作为参考。 在这种情况下,点p和q应该是线的最终点。 你的代码很适合我...请仔细检查 @Miki,我通过了错误的分数。请看以下几点:p1 = (301,49) 和 p2 = (303,460)。 【参考方案1】:

我在 2.4.9 版本上运行时遇到了同样的问题。鉴于 Miki anwser,它可能已在较新版本上得到修复。

这个问题似乎发生在直线斜率太高,因此与 y 轴的交点远离原点时。

我测试了引用的点,以及许多其他点,下面的函数处理了这个问题。它主要计算计算线与图像边界的交点,并返回图像边界中的共线点。

void getLinePointinImageBorder(const cv::Point& p1_in, const cv::Point& p2_in,
                               cv::Point& p1_out, cv::Point& p2_out, 
                               int rows, int cols)

    double m = (double) (p1_in.y - p2_in.y) / (double) (p1_in.x - p2_in.x + std::numeric_limits<double>::epsilon());
    double b = p1_in.y - (m * p1_in.x);

    std::vector<cv::Point> border_point;
    double x,y;
    //test for the line y = 0
    y = 0;
    x = (y-b)/m;
    if(x > 0 && x < cols)
        border_point.push_back(cv::Point(x,y));

    //test for the line y = img.rows
    y = rows;
    x = (y-b)/m;
    if(x > 0 && x < cols)
        border_point.push_back(cv::Point(x,y));

    //check intersection with horizontal lines x = 0
    x = 0;
    y = m * x + b;
    if(y > 0 && y < rows)
        border_point.push_back(cv::Point(x,y));

    x = cols;
    y = m * x + b;
    if(y > 0 && y < rows)
        border_point.push_back(cv::Point(x,y));

    p1_out = border_point[0];
    p2_out = border_point[1];

【讨论】:

@Diego 的解决方案对我有用。我使用一组点进行了测试,它给出了正确的线点。谢谢!【参考方案2】:

我无法用您的代码重现错误。此代码(从您的复制和粘贴)运行良好:

#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int main() 

    cv::Mat img = cv::Mat::zeros(600,600,CV_8UC3);
    cv::Point p1(301,49);
    cv::Point p2(303,460);

    cv::Point p(0,0), q(img.cols, img.rows);
    if (p1.x != p2.x) 
        double m = (double) (p1.y - p2.y) / (double) (p1.x - p2.x);
        double 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::circle(img, p1, 4, cv::Scalar(255,0,255), -1);
    cv::circle(img, p2, 4, cv::Scalar(255,0,255), -1);
    cv::line(img, p, q, cv::Scalar(0,0,255), 2);

    imshow("Result", img);
    waitKey();

    return 0;

【讨论】:

我请一位朋友运行此代码,他得到的结果与我相同。 =S 你的opencv版本是多少?你是在linux/window/mac中执行的吗? Opencv 3.2 Visual Studio 2015 (vc14) 64bit, win10 我在 Ubuntu 16.04 64 位,Opencv 2.4.13 上进行过。 我并没有怀疑你的结果,但同样的源代码呈现两种不同的输出真的很有趣。如果我们遇到版本问题,您有什么建议吗?【参考方案3】:

这是known bug,现已修复。

所以更新到最新版本的OpenCV(3.2版)或者在画线之前使用cv::clipLine(img.size(), p, q);


所有致谢@sturkmen

【讨论】:

感谢三木和突击队员!

以上是关于使用Opencv和C++在垂直方向的两点之间绘制直线的主要内容,如果未能解决你的问题,请参考以下文章

GoogleMap API 为两点之间的方向提供了错误的坐标

Qt,C++ 在 2 个对象之间绘制连接线

在 OpenCV 中用渐变颜色绘制一条线

使用 OpenCV 查找图像中两点之间的角度

从二进制图像OpenCV C++中裁剪文本

OpenCV 例程200篇211. 绘制垂直矩形