Redrawing a line from two points gives slightly inaccurate results - c++

Recently I started working on a project with OpenCV and C++.
I graph a curved line on desmos, and feed it into the program. The objective of the program is to measure how curved the line is, and how much to straighten it.
The red line you see in the image below (with the green and red dots on it) is the graphed line from desmos. The purple line with hollow circles on it is the model line that needs to be met. I have written some basic functions to calculate what each x value of a given y value would be on the straight line. I did this in order to align the points from the curved line with points on the straight line.
The code for calculating the values is:
double slopeOf(Point first, Point second) {
return (second.y - first.y) / (second.x - first.x);
}
double f(Point first, Point second, int y) {
// return x of point with y value, on given line
return ((y - first.y) / slopeOf(first, second)) + first.x;
}
As you can see, the hollow points at the bottom of the line are centered with the straight line, and they are accurate. But the higher up you go in the line, the points begin to stray away from the line.
Why is this happening?
Also: I tired using the LineIterator in OpenCV but couldn't get the flexible results I would if I used my own functions.
Thanks in advance, any help is appreciated.

Related

Draw line through, instead of between two points in Python

I want to draw a line trough two given points in an image using OpenCV in Python. The definition of a line states as "The shortest distance between two points." But I don't want the line to stop at the points, I want it to go all the way to the borders of my image. Currently I am obviously just using the cv2.line function, with 1 being the thickness of the line.
cv2.line(img,(x1,y1),(x2,y2),blue,1)
The algorithm I'm writing doesn't really matter, I just can't find any function in cv2 or numpy that draws a "line" through two points instead of between them.
Thanks in advance
EDIT: solved it myself
a = (1.0*(y2-y1))/(1.0*(x2-x1))
b = -a*x1+y1
y1_ = (int)(0)
y2_ = (int)(np.shape(img)[1])
x1_ = (int)((y1_-b)/a)
x2_ = (int)((y2_-b)/a)
cv2.line(img,(x1_,y1_),(x2_,y2_),(colors[i][0],colors[i][1],colors[i][2]),5)

why hough transform detects two lines while there is only one line

I would like to detect a line and extract its two ended points. The common approach is using the hough transform. Luckily there is a sample in OpenCV regarding is matter, therefore I've drawn a line whose two ended points p1(100,200), p2(400,200). I thought the aforementioned method will provid me with only these points. My sample image is
the hough transform provides me with two images which are
For Canny filter,
In the code, it seems that there are two lines are detected. This explains why the red line is thicker which indicates the fact that there are two lines rather than one. When I print out the number of lines, it shows me two as follows
lines.size(): 2
p1:<99,201> p2:<401,201>
lines.size(): 2
p1:<102,198> p2:<398,198>
Why I'm getting two lines?
It might be due to the width of the bins in your HoughSpace.
You probably choose one of the default OpenCv functio, i.e.
HoughLines(X, X, 1, CV_PI/180, X, X, X );
The arguments that are not X define the width of the bins see.
There it says:
rho : The resolution of the parameter r in pixels. We use 1 pixel.
For the first argument and for the second:
theta: The resolution of the parameter \theta in radians. We use 1 degree (CV_PI/180)
I don't now the values you chose, but you might want to choose larger ones.

Connecting Circles in C++/Excel

This is quite complicated to explain, so I will do my best, sorry if there is anything I missed out, let me know and I will rectify it.
My question is, I have been tasked to draw this shape,
(source: learnersdictionary.com)
This is to be done using C++ to write code that will calculate the points on this shape.
Important details.
User Input - Centre Point (X, Y), number of points to be shown, Font Size (influences radius)
Output - List of co-ordinates on the shape.
The overall aim once I have the points is to put them into a graph on Excel and it will hopefully draw it for me, at the user inputted size!
I know that the maximum Radius is 165mm and the minimum is 35mm. I have decided that my base [Font Size][1] shall be 20. I then did some thinking and came up with the equation.
Radius = (Chosen Font Size/20)*130. This is just an estimation, I realise it probably not right, but I thought it could work at least as a template.
I then decided that I should create two different circles, with two different centre points, then link them together to create the shape. I thought that the INSIDE line will have to have a larger Radius and a centre point further along the X-Axis (Y staying constant), as then it could cut into the outside line.*
*(I know this is not what it looks like on the picture, just my chain of thought as it will still give the same shape)
So I defined 2nd Centre point as (X+4, Y). (Again, just estimation, thought it doesn't really matter how far apart they are).
I then decided Radius 2 = (Chosen Font Size/20)*165 (max radius)
So, I have my 2 Radii, and two centre points.
This is my code so far (it works, and everything is declared/inputted above)
for(int i=0; i<=n; i++) //output displayed to user
{
Xnew = -i*(Y+R1)/n; //calculate x coordinate
Ynew = pow((((Y+R1)*(Y+R1)) - (Xnew*Xnew)), 0.5); //calculate y coordinate
AND
for(int j=0; j<=n; j++)//calculation for angles and output displayed to user
{
Xnew2 = -j*(Y+R2)/((n)+((0.00001)*(n==0))); //calculate x coordinate
Ynew2 = Y*(pow(abs(1-(pow((Xnew2/X),2))),0.5));
if(abs(Ynew2) <= R1)
cout<<"\n("<<Xnew2<<", "<<Ynew2<<")"<<endl;
I am having the problem drawing the crescent moon that I cannot get the two circles to have the same starting point?
I have managed to get the results to Excel. Everything in that regard works. But when i plot the points on a graph on Excel, they do not have the same starting points. Its essentially just two half circles, one smaller than the other (Stops at the Y axis, giving the half doughnut shape).
If this makes sense, I am trying to get two parts of circles to draw the shape as such that they have the same start and end points.
If anyone has any suggestions on how to do this, it would be great, currently all I am getting more a 'half doughnut' shape, due to the circles not being connected.
So. Does anyone have any hints/tips/links they can share with me on how to fix this exactly?
Thanks again, any problems with the question, sorry will do my best to rectify if you let me know.
Cheers
Formular for points on a circle:
(x-h)^2+(y-k)^2=r^2
The center of the circle is at (h/k)
Solving for y
2y1 = k +/- sqrt( -x^2 + 2hx +r^2 - h^2)
So now if the inner circle has its center # h/k , the half-moon will begin # h and will stretch to h - r2
Now you need to solve the endpoint formular for the inner circle and the outter circle and plot it. Per x you should receive 4 points (solve the equation two times, each with two solutions)
I did not implement it, but this would be my train of thought...

Trigonometry across multiple planes

Please bear with me - I'm finding this very difficult to explain.
This is more of a trigonometry question but for what it matters, this is in JavaScript/KineticJS.
I have a series of 'group's which contain 'line's and 'handle's. The way this has to work, it works best for every group to have its own coordinate plane. The problem I'm asking for help on is the only instance where this solution is not ideal.
As these groups rotate, their coordinate plane also rotates. This allows the group object to be reused and its children can measure from the group's origin without any concern about the parent group's orientation. Up is always up... it doesn't matter which way my group is facing.
I'm a new poster, so I cant add an image. However, I think seeing it is vital. Please see http://i.imgur.com/WUVXE.png
The goal is to attach the unattached point of the red arc ('handle') to the black dot on the blue line ('line'). I've set it to always draw 90 degrees just for demonstration purposes.
Despite convention, the API I'm using rotates clockwise, giving the red line an angle of 0, the yellow line an angle of 116, green 180, and blue 296 - all relative to the same origin in the top left of the screen. These angles change, so I'm looking for the formula to calculate the new end point of the red handle.
The X-axis always travels straight down the middle of each line. The line is 20px wide, so there are 10px above or below it the line that are "dead space". The two correct points on the red handle are thus (10,10) and (30,10). Handles have a radius of 20px.
It is not possible to say red.arcEndX = blue.blackDotX, red.arcEndY = blue.blackDotY since the planes for the red and blue group are different. For instance, red's (0,0) is always equal to blue's (200,0). Think of each line as a chain that cannot be detached.
So, how do I calculate the red arc's remaining point? It should attach seamlessly to the edge of the blue line, exactly where the center point of the black dot on the blue line is except translated in to red's coordinate plane.
All of the measurements I may need are available, or can be calculated.
Handle.prototype.update = function() {
/* if we are the red group, this.parent is our group and
'prev' is the blue group. */
var prev = this.parent.getPrev();
// somehow get the new (x,y) for point2 below:
/* KineticJS SVG string. this.origin and this.point1 never
change. This (M)oves to 10,10, draws a (L)ine from
this.origin.x, this.origin.y to this.point1.x, this.point1.y
and (C)urves to this.point2.x, this.point2.y. this.centerXY
is the control point of that curve. */
this.data = "M" + this.origin + "L" + this.point1 + "C" + this.point1 + "," + this.centerXY + "," + this.point2 + "L" + this.origin + "z";
this.shape.setData(this.data);
}
In case anybody stumbles upon this - what I have is correct except I failed to accomodate the origin translation. If you move everything to (0,0) for each plane, do your sin/cos then you'll be OK

Vector line inside Rectangle

what i got is a vector line (normalized vector vx,vy some point x0,y0, form fitLine OpenCv) and a rectangle defined by four points (clockwise p1,p2,p3,p4). now i need to know, if the line is going through the rectangle.. which means there need to be two points above (or left from) the line and two points below (or right from) the line. how can i archive this in c++?
This question looks like a homework ;)
First, you will need to discribe your line as an equation (1) such as Ax+By=C. Any basic algebra book will tell you how to do that (or wikipedia).
Then, you will need to find the similar equations for each edge of your rectangle. Let's call those equations (2),(3),(4) and (5).
Then, you will need to find the intersection of (1) with each other equations. Let's call thoses points a , b ,c and d.
Afterward, you will need to figure out for each intersection points if it stands between the appropriate vertexes. If it's the case, they cross a rectangle edge!
If the your line cross at least one edge, you can say that your line cross your rectangle.
Here the challenge is to be able to deal with a line that is parralel to your rectangle or that is directly on one of a rectangle edge. Do not be shy to make yourself a nice drawing to be sure of what you are doing.
The equation of your vector is
y - y0 = (vy/vx) (x - x0)
To tell whether point (x1,y1) is above, on or below the line, solve the line for x1 and compare y to y1.
y > y1 - below
y == y1 - on
y < y1 - above
So compare the your vector to each corner of the rectangle.