使用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++在垂直方向的两点之间绘制直线的主要内容,如果未能解决你的问题,请参考以下文章