EmguCV: Get coordinates of pixels in a line between two points - c#

So here's my goal: I want to stop at each pixel on a line and do some processing on those pixels. Currently i'm using EmguCV for my image processing library. In openCV there is a method called LineIterator which you can use to iterate through the pixel in a line. However, I haven't found a method similar to this in EmguCV which is where I am getting stuck.
Currently, I can get the pixel values of all the pixels on a line between two predefined points using the Image.Sample method. For a grayscale image Image this returns a n-by-1 matrix with n being the number of pixels on that line. However, I am not able to get the coordinates of each pixel on that particular line corresponding to the pixel values in the n-by-1 matrix mentioned above. Hence, I am not able to do image processing on these pixels, even though I have their pixel values. Is there a way to do this on EmguCV?
Thank you.

I implemented the bresenham line algoritm for my own project
(converted to C# from the wikipedia article)
public static List<Point> GetBresenhamLine(Point p0, Point p1)
{
int x0 = p0.X;
int y0 = p0.Y;
int x1 = p1.X;
int y1 = p1.Y;
int dx = Math.Abs(x1 - x0);
int dy = Math.Abs(y1 - y0);
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = dx - dy;
var points = new List<Point>();
while (true)
{
points.Add(new Point(x0, y0));
if (x0 == x1 && y0 == y1) break;
int e2 = 2 * err;
if (e2 > -dy)
{
err = err - dy;
x0 = x0 + sx;
}
if (e2 < dx)
{
err = err + dx;
y0 = y0 + sy;
}
}
return points;
}
I implemented my own "Point" struct, but think it matches Emgu's.
I think this should take care of any special cases.

If (x1, y1) and (x2, y2) are two end points.
(x1, y1) ___________________ (x2, y2)
then you can get intermediate points by
for (int i = x1, i < x2; i++)
{
int x = i;
int y = (y1 + (y2-y1)/(x2-x1) * (x - x1)))
cout << "Points : " << x << " " << y << endl;
}

Related

Euclidean distance between the coordinates in the array

I calculate euclidean distance in c#.
Point[] points = new Point[100];
I have the coordinates of the points I created in this array.I want to calculate the distance between all points.
for (int i = 1; i < k+1; i++)
{
X1 = points[i].X;
X2 = points[i + 1].X;
Y1 = points[i].Y;
Y2 = points[i + 1].Y;
result = Math.Sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2));
}
With this code I have calculated the distance between points (eg: distance between points a and b, distance between points c and d, etc.) but I couldn't calculate the distance between points a and c or the points b and b I want to calculate the distance between all points in this array. How do I do that?
You have to use 2 loops. The first loop assign values to X1 and the second loop assign values to X2.
This allows to calculate the Euclidean Distance between two points that aren't contiguous in the array.
You have to use 2 for loops to achieve that.
Also you would want to persist the euclidean distances between these points somewhere.
You probably want to go through the array twice.
Point[] points = new Point[100];
for(int i = 0; i < points.Length; i++)
for (int j = points.Length - 1; j >= i; j--)
{
float distance = 0;
if(i != j)
distance = CalculateDistance(points[i], points[j]);
// Do more stuff here
}
Obviously, you could simply run two for loops of equal lengths, but this will give you the same result twice. When i and j have the same value flipped (i = 10, j = 15 and later i = 15 and j = 10), you do the same calculation to get the same result. To prevent that I have my second loop only run about half the values to not redo calculations.
The CalculateDistance method does exactly the same as the code you have written before, in my case the following:
private static float CalculateDistance(Point point1, Point point2)
{
float X1 = point1.X;
float X2 = point1.Y;
float Y1 = point2.X;
float Y2 = point2.Y;
return (float)Math.Sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2));
}
This way I can reuse and reorder my calculations at any time, because I only have to move a single line. Note that you can always just use the floats as parameters instead of locals, but I felt like this way would make it more readable here in this example.
I also skipped the calculations when the distance was equal, because the same values were compared.
public void Euclidea()
{
double result;
int X1,X2,Y1,Y2;
for (int i = 1; i < k+1; i++)
{
X1 = points[i].X;
Y1 = points[i].Y;
for (int j = 0; j < k; j++)
{
X2 = points[j + 1].X;
Y2 = points[j + 1].Y;
result = Math.Sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2));
}
}
}
I solved the problem by typing this code
k=points.length()

Calculate the X -aixes Limmets of a arch from G-Code

I am trying to determine the limits of an arch for a couple of days now without much successes.I know this is more of a geometry type question than programming but here it goes.Let me first show this image to elaborate on what I am trying to achieve in C#.
In the image above you can see a Green Arc, I am trying to determine where the ‘Left Most’ point is on the X axis (and the 'right most' eventually, but for the sake of simplicity I will focus on the ‘left most’ point)
The answer of this image ‘left most’ in the X axis is 5,note: even if the arch has a greater sweep angle the answer is still 5, but if the sweep angle is less than the answer will be more than 5.
I am reading this information from a text based G-code file and here is a sample of the arc drawn in the G-code file.
G1 X10. Y15.
G3 X5. Y10. I10. J10.
The first line indicates the starting-point of the arch, witch is in this case X 10 and Y 15. The second line indicates the end-point, arch-center-point and rotation.
The G3 indicates a Counter-Clockwise rotation of the arch (G2 indicates a Clockwise Rotation).
The X & Y indicates the End-Point and the I & J is the (X & Y respectively) arch-center-point values.The first thing that I have tried is to see if I can detect the arch crosses the 180* red line without much successes mainly because I cannot seem to get angle calculations working correctly when I try to process different types of coordinates.Here is a sample of code I’m unable to finish:
else if (Gval == 3)
{
//Values read from G-Code File
double startX = Convert.ToDouble(oldXval);
double startY = Convert.ToDouble(oldYval);
double endX = Convert.ToDouble(Xval);
double endY = Convert.ToDouble(Yval);
double midX = Convert.ToDouble(Ival);
double midY = Convert.ToDouble(Jval);
//Get Start angle of Line
double startAngle = Math.Atan2(startY - midY, startX - midX);
startAngle = Math.Round(startAngle * (180.0 / Math.PI), 5);//Radiants to Degrees
startAngle = ((startAngle % 360) + 360) % 360;//Normalise
//Get End angle of line
double EndAngle = Math.Atan2(endY - midY, endX - midX);
EndAngle = Math.Round(EndAngle * (180.0 / Math.PI), 5);//Radiants to Degrees
EndAngle = ((EndAngle % 360) + 360) % 360;//Normalise
if (EndAngle == 0) EndAngle = 360;
//Get Raiduis
double raduis = Math.Round((Math.Sqrt(Math.Pow(Math.Abs(startX - midX), 2) + Math.Pow(Math.Abs(startY - midY), 2))),5);
double deltaY = (midY) - (startX);
double deltaX = (midX) - (startY);
double angleInDegrees = Math.Atan(deltaY / deltaX)*180/Math.PI;
if (startAngle <= 180 && EndAngle >= 180)
{
double LeftValue = midX - raduis;
}
}
The code above only works for some specific arcs.
I have Googled around and found mainly topics on Lines intersections and line and circle intersections but only one specifically about lines intersecting arcs, the answer is too vague to make out what is supposed to happen here is the Link
In addition to that there is also a type of arch that I think will have to be processed differently probably by some sort of Pathegorem, but I have not started on how I can do that one. But here is an image of it:
Here is the G-code :
G1 X30. Y15.
G3 X25.4 Y11.96 I30. J10.
And I think the ‘Left most’ X value is 25.4
I would like to know, if you know of a Method or a Library that can help out with this one .Thanks
This should calculate the X and Y bounds of an arc. There are many optimizations that could be made for better performance, but I think this is easier to understand.
class Bounds
{
public double MinX, MinY, MaxX, MaxY;
}
Bounds GetArcBounds(float cx, float cy, float x1, float y1, float x2, float y2)
{
var a1 = GetAngle(y1 - cy, x1 - cx);
var a2 = GetAngle(y2 - cy, x2 - cx);
var r = (float)Math.Sqrt(Math.Pow(y1 - cy, 2) + Math.Pow(x1 - cx, 2));
var bounds = new Bounds();
bounds.MinX = double.MaxValue;
bounds.MinY = double.MaxValue;
bounds.MaxX = double.MinValue;
bounds.MaxY = double.MinValue;
ExpandBounds(bounds, x1, y1);
ExpandBounds(bounds, x2, y2);
if (IsAngleInArc(a1, a2, 0))
ExpandBounds(bounds, cx + r, cy);
if (IsAngleInArc(a1, a2, (float)Math.PI * 0.5f))
ExpandBounds(bounds, cx, cy + r);
if (IsAngleInArc(a1, a2, (float)Math.PI))
ExpandBounds(bounds, cx - r, cy);
if (IsAngleInArc(a1, a2, (float)Math.PI * 1.5f))
ExpandBounds(bounds, cx, cy - r);
return bounds;
}
float GetAngle(float dy, float dx)
{
var a = (float)Math.Atan2(dy, dx);
if (a < 0) a += (float)Math.PI * 2.0f;
return a;
}
void ExpandBounds(Bounds bounds, float x, float y)
{
if (x < bounds.MinX) bounds.MinX = x;
if (y < bounds.MinY) bounds.MinY = y;
if (x > bounds.MaxX) bounds.MaxX = x;
if (y > bounds.MaxY) bounds.MaxY = y;
}
bool IsAngleInArc(float a1, float a2, float test)
{
if (a2 < a1)
{
a2 += (float)Math.PI * 2.0f;
}
if (test < a1)
{
test += (float)Math.PI * 2.0f;
}
return a1 <= test && test <= a2;
}
If you wanted to be able to do both counter-clockwise and clockwise, I believe you could change the logic to the following, although I have not tested this yet.
if (IsAngleInArc(a1, a2, 0) ^ clockwise)
ExpandBounds(bounds, cx + r, cy);
if (IsAngleInArc(a1, a2, (float)Math.PI * 0.5f) ^ clockwise)
ExpandBounds(bounds, cx, cy + r);
if (IsAngleInArc(a1, a2, (float)Math.PI) ^ clockwise)
ExpandBounds(bounds, cx - r, cy);
if (IsAngleInArc(a1, a2, (float)Math.PI * 1.5f) ^ clockwise)
ExpandBounds(bounds, cx, cy - r);

is it possible to get all point of pixel from line c# drawing 2d

I have a line C# code with drawing graphichpath, how to get all value every line pixel. not just point (x1,y1) and (x2,y2) point but I want all pixel from (x1,y1) to (x2,y2)
Here's an algorithm that should give you an estimation of the pixels between your two Points. Note it will not match what is on screen perfectly (which looks antialiased).
public static IEnumerable<Tuple<int,int>> EnumerateLineNoDiagonalSteps(int x0, int y0, int x1, int y1)
{
int dx = Math.Abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = -Math.Abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = dx + dy, e2;
while(true)
{
yield return Tuple.Create(x0, y0);
if (x0 == x1 && y0 == y1) break;
e2 = 2 * err;
// EITHER horizontal OR vertical step (but not both!)
if (e2 > dy)
{
err += dy;
x0 += sx;
}
else if (e2 < dx)
{ // <--- this "else" makes the difference
err += dx;
y0 += sy;
}
}
}
Replace the Tuple with Point.
For more information, see:
http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
or
http://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm

Moving the mouse along a diagonal line

What kind of math algorithm could I use to calculate the path to move a mouse? I simply want to have this type of function:
animateMouseDiag(int X, int Y){
//Move mouse 1 step towards goal, for loop most likely, from the current Mouse.Position
Thread.Sleep(1);
}
For example, if I give it animateMouseDiag(100,300), it would move the mouse 100 to the right and 300 down, but diagonally, not right-then-down in an 'L'. Similarly, if I gave it (-50,-200) it would move it to those relative coordinates (50 left and 200 up) along the diagonal path.
Thank you! (By the way, this is an alt account since I feel like an idiot asking about basic high school math on my main. I just can't translate it into programming.)
EDIT: I have come up with this:
public static void animateCursorTo(int toX, int toY)
{
double x0 = Cursor.Position.X;
double y0 = Cursor.Position.Y;
double dx = Math.Abs(toX-x0);
double dy = Math.Abs(toY-y0);
double sx, sy, err, e2;
if (x0 < toX) sx = 1;
else sx = -1;
if (y0 < toY) sy = 1;
else sy = -1;
err = dx-dy;
for(int i=0; i < toX; i++){
//setPixel(x0,y0)
e2 = 2*err;
if (e2 > -dy) {
err = err - dy;
x0 = x0 + sx;
}
if (e2 < dx) {
err = err + dx;
y0 = y0 + sy;
}
Cursor.Position = new Point(Convert.ToInt32(x0),Convert.ToInt32(y0));
}
}
This is Bresenham's line algorithm. Strangely though, the lines don't draw on a set angle. They seem to be gravitating towards the top left of the screen.
Store the position coordinates as floating point values, then you can represent the direction as a unit vector and multiply by a specific speed.
double mag = Math.Sqrt(directionX * directionX + directionY * directionY);
mouseX += (directionX / mag) * speed;
mouseY += (directionY / mag) * speed;

Shorten a line by a number of pixels

I'm drawing a custom diagram of business objects using .NET GDI+. Among other things, the diagram consists of several lines that are connecting the objects.
In a particular scenario, I need to shorten a line by a specific number of pixels, let's say 10 pixels, i.e. find the point on the line that lies 10 pixels before the end point of the line.
Imagine a circle with radius r = 10 pixels, and a line with start point (x1, y1) and end point (x2, y2). The circle is centered at the end point of the line, as in the following illustration.
How do I calculate the point marked with a red circle, i.e. the intersection between circle and line? This would give me the new end point of the line, shortening it by 10 pixels.
Solution
Thank you for your answers from which I was able to put together the following procedure. I named it LengthenLine, since I find it more natural to pass a negative number of pixels if I want the line shortened.
Specifically, I was trying to put together a function that could draw a line with rounded corners, which can be found here.
public void LengthenLine(PointF startPoint, ref PointF endPoint, float pixelCount)
{
if (startPoint.Equals(endPoint))
return; // not a line
double dx = endPoint.X - startPoint.X;
double dy = endPoint.Y - startPoint.Y;
if (dx == 0)
{
// vertical line:
if (endPoint.Y < startPoint.Y)
endPoint.Y -= pixelCount;
else
endPoint.Y += pixelCount;
}
else if (dy == 0)
{
// horizontal line:
if (endPoint.X < startPoint.X)
endPoint.X -= pixelCount;
else
endPoint.X += pixelCount;
}
else
{
// non-horizontal, non-vertical line:
double length = Math.Sqrt(dx * dx + dy * dy);
double scale = (length + pixelCount) / length;
dx *= scale;
dy *= scale;
endPoint.X = startPoint.X + Convert.ToSingle(dx);
endPoint.Y = startPoint.Y + Convert.ToSingle(dy);
}
}
Find the direction vector, i.e. let the position vectors be (using floats) B = (x2, y2) and A = (x1, y1), then AB = B - A. Normalize that vector by dividing by its length ( Math.Sqrt(xx + yy) ). Then multiply the direction vector AB by the original length minus the circle's radius, and add back to the lines starting position:
double dx = x2 - x1;
double dy = y2 - y1;
double length = Math.Sqrt(dx * dx + dy * dy);
if (length > 0)
{
dx /= length;
dy /= length;
}
dx *= length - radius;
dy *= length - radius;
int x3 = (int)(x1 + dx);
int y3 = (int)(y1 + dy);
Edit: Fixed the code, aaand fixed the initial explanation (thought you wanted the line to go out from the circle's center to its perimeter :P)
I'm not sure why you even had to introduce the circle. For a line stretching from (x2,y2) to (x1,y1), you can calculate any point on that line as:
(x2+p*(x1-x2),y2+p*(y1-y2))
where p is the percentage along the line you wish to go.
To calculate the percentage, you just need:
p = r/L
So in your case, (x3,y3) can be calculated as:
(x2+(10/L)*(x1-x2),y2+(10/L)*(y1-y2))
For example, if you have the two points (x2=1,y2=5) and (x1=-6,y1=22), they have a length of sqrt(72 + 172 or 18.38477631 and 10 divided by that is 0.543928293. Putting all those figures into the equation above:
(x2 + (10/l) * (x1-x2) , y2 + (10/l) * (y1-y2))
= (1 + 0.543928293 * (-6- 1) , 5 + 0.543928293 * (22- 5))
= (1 + 0.543928293 * -7 , 5 + 0.543928293 * 17 )
= (x3=-2.807498053,y3=14.24678098)
The distance between (x3,y3) and (x1,y1) is sqrt(3.1925019472 + 7.7532190152) or 8.384776311, a difference of 10 to within one part in a thousand million, and that's only because of rounding errors on my calculator.
You can use similar triangles. For the main triangle, d is the hypotenuses and the extension of r is the vertical line that meets the right angle. Inside the circle you will have a smaller triangle with a hypotenuses of length r.
r/d = (x2-a0)/(x2-x1) = (y2-b0)/(y2-y1)
a0 = x2 + (x2-x1)r/d
b0 = y2 + (y2-y1)r/d

Categories

Resources