Reputation: 189
I have tried to draw a straight line using two reference points and I got some problems on vertical orientation.
That's the current source code:
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);
What am I doing wrong?
Upvotes: 0
Views: 3890
Reputation: 41765
This is a known bug, now fixed.
So update to the latest version of OpenCV (version 3.2) or use cv::clipLine(img.size(), p, q);
before drawing line.
All credits to @sturkmen
Upvotes: 1
Reputation: 81
I had the same problem of you running on the 2.4.9 version. Given the Miki anwser it might have been fixed on newer versions.
The problem seems to happen when the line slope is too high and therefore the intersection with the y axis it is far away from the origin.
I tested the cited point,as well many others and the following function handled that problem. It basically computes the intersection of the computed line with the image borders and return collinear points in the image borders.
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];
}
Upvotes: 3
Reputation: 41765
I'm not able to reproduce the error with your code. This code (copied & pasted from yours) works well:
#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;
}
Upvotes: 1