Finding difference of two plots in C# - c#

I am having a laser scanner application where I want to find the difference between two plots ,one the reference plot without object and the other with the object in view.I am plotting the graph with x y coordinates. currently I have plotted the graphs and filled them with different colors so that I can view the subtracted part clearly. But now I want only the difference area to show up...I thought finding the area under the curve will solve the issue.But I think it will only give the numerical value and not the exact position of the subtracted area.
So,I searched the internet looking for solutions in C# where I can do this in the plot itself.Hope I made myself clear.
Can someone guide me in the search? I am giving my c# code here..
// PointPairList holds the data for plotting, X and Y arrays (one can use other types of objects as well)
PointPairList spl1 = new PointPairList(x1, y1);
PointPairList spl2 = new PointPairList(x2, y2);
PointPairList spl3 = new PointPairList(x, y);
// Add curves to myPane object
LineItem myCurve1 = myPane.AddCurve("LIDAR Data Scanner-Measurement-Normal", spl1, Color.Blue, SymbolType.None);
LineItem myCurve2 = myPane.AddCurve("LIDAR Data Scanner-Measurement-with object", spl2, Color.Red, SymbolType.None);
LineItem myCurve3 = myPane.AddCurve("LIDAR Data Scanner-Measurement-Subtracted curve", spl3, Color.Green, SymbolType.None);
// myCurve1.Line.Width = 3.0F;
//myCurve2.Line.Width = 3.0F;
myCurve1.Line.Fill = new Fill(Color.White, Color.FromArgb(16, 155, 0, 0), 90F);
myCurve2.Line.Fill = new Fill(Color.Black, Color.FromArgb(143, 55, 6, 0), 90F);
I want to display only the rectangle white part in the figure...

I am not sure about data-structures that you are sighted - however, generally speaking, if you are dealing with polygons (closed curves specifies with a set of x,y points) then you can do polygon clipping to find the difference. See
Algorithm to Compute the Remaining Polygon After Subtraction
How to intersect two polygons?
If you can represent your two plots i.e. a reference plot and supplied plot as polygon then above algorithm should allow you compute the difference.

Related

find the center point of coordinate 2d array c#

Is there a formula to average all the x, y coordinates and find the location in the dead center of them.
I have 100x100 squares and inside them are large clumps of 1x1 red and black points, I want to determine out of the red points which one is in the middle.
I looked into line of best fit formulas but I am not sure if this is what I need.
Sometimes all the red will be on one side, or the other side. I want to essentially draw a line then find the center point of that line, or just find the center point of the red squares only. based on the 100x100 grid.
List<Point> dots = new List<Point>();
int totalX = 0, totalY = 0;
foreach (Point p in dots)
{
totalX += p.X;
totalY += p.Y;
}
int centerX = totalX / dots.Count;
int centerY = totalY / dots.Count;
Simply average separately the x coordinates and the y coordinates, the result will be the coordinates of the "center".
What if there are two or more subsets of red points ? Do you want the black point inside them?
Otherwis, if I understood your question, just give a weight of 1 to red points and 0 to blacks. Then do the weighted mean on X and Y coordinate

Real World Distance: Stereo cam, cvPerspectiveTransform, Emgu, C#

I'd really appreciate some help with the following questions:
Have captured, then rectified, grayscale images from a calibrated stereo rig.
Am now attempting to get real world x,y, z coords , relative to the left camera, of specific points, in the left image; I am trying to use cvPerspectiveTransform to do so.
My abbreviated code is below.
The code appears to work to some extent, and returns the following 4 data points:
(15.4510, -474.7451, -527.0327, -912.6536), which I understand to represent x,y,z and w.
Question 1) is this assumption correct? - it may be that division by w has already taken place and that XYZ have already been returned, in which case -912.6536 is an artefact to be ignored - any views on this are welcome.
Question 2) However if ,to achieve realworld coordinates X,Y,Z, each of 'x','y','z' respectively is to be divided by 'w', in what units are the resulting XYZ coordinates? I understand them to be related to the "points" used in calibration - in this case chessboard corners were 2.5 cm apart, however the distance from the camera of the object in this case was approximately 60cm... as you can see the math doesn't quite work.
I have diligently read the relevant pages in the Bradski book (and searched online), but I must be missing something.
Matrix<float> inputMatLeft = new Matrix<float>(4,1,3);
inputMatLeft[0,0] = xL; // xL, a float, the x coord of a point in the left image
inputMatLeft[1,0] = yL; // yL, a float, the y coord of same point in left image
inputMatLeft[2,0] = d; // d, a float, the disparity between the same featurepoint in the left and right rectified images, is calc'd and defined elsewhere
inputMatLeft[3,0] = 1F;
Matrix<float> rwCoords = new Matrix<float>(4,1,3);
rwCoords = computeRealWorldCoords(inputMatLeft);
// ....do stuff with rwCoords
public Matrix<float> computeRealWorldCoords(Matrix <float> leftSrc)
{
Matrix<float> leftDest = new Matrix<float>(4,1,3);
CvInvoke.cvPerspectiveTransform(leftSrc, leftDest, inputMatrixQ); // Q Matrix is 4x4 float
return leftDest;
}
Thanks!

Trying to accurately measure 3D distance from a 2D image

I am trying to extract out 3D distance in mm between two known points in a 2D image. I am using square AR markers in order to get the camera coordinates relative to the markers in the scene. The points are the corners of these markers.
An example is shown below:
The code is written in C# and I am using XNA. I am using AForge.net for the CoPlanar POSIT
The steps I take in order to work out the distance:
1. Mark corners on screen. Corners are represented in 2D vector form, Image centre is (0,0). Up is positive in the Y direction, right is positive in the X direction.
2. Use AForge.net Co-Planar POSIT algorithm to get pose of each marker:
float focalLength = 640; //Needed for POSIT
float halfCornerSize = 50; //Represents 1/2 an edge i.e. 50mm
AVector[] modelPoints = new AVector3[]
{
new AVector3( -halfCornerSize, 0, halfCornerSize ),
new AVector3( halfCornerSize, 0, halfCornerSize ),
new AVector3( halfCornerSize, 0, -halfCornerSize ),
new AVector3( -halfCornerSize, 0, -halfCornerSize ),
};
CoplanarPosit coPosit = new CoplanarPosit(modelPoints, focalLength);
coPosit.EstimatePose(cornersToEstimate, out marker1Rot, out marker1Trans);
3. Convert to XNA rotation/translation matrix (AForge uses OpenGL matrix form):
float yaw, pitch, roll;
marker1Rot.ExtractYawPitchRoll(out yaw, out pitch, out roll);
Matrix xnaRot = Matrix.CreateFromYawPitchRoll(-yaw, -pitch, roll);
Matrix xnaTranslation = Matrix.CreateTranslation(marker1Trans.X, marker1Trans.Y, -marker1Trans.Z);
Matrix transform = xnaRot * xnaTranslation;
4. Find 3D coordinates of the corners:
//Model corner points
cornerModel = new Vector3[]
{
new Vector3(halfCornerSize,0,-halfCornerSize),
new Vector3(-halfCornerSize,0,-halfCornerSize),
new Vector3(halfCornerSize,0,halfCornerSize),
new Vector3(-halfCornerSize,0,halfCornerSize)
};
Matrix markerTransform = Matrix.CreateTranslation(cornerModel[i].X, cornerModel[i].Y, cornerModel[i].Z);
cornerPositions3d1[i] = (markerTransform * transform).Translation;
//DEBUG: project corner onto screen - represented by brown dots
Vector3 t3 = viewPort.Project(markerTransform.Translation, projectionMatrix, viewMatrix, transform);
cornersProjected1[i].X = t3.X; cornersProjected1[i].Y = t3.Y;
5. Look at the 3D distance between two corners on a marker, this represents 100mm. Find the scaling factor needed to convert this 3D distance to 100mm. (I actually get the average scaling factor):
for (int i = 0; i < 4; i++)
{
//Distance scale;
distanceScale1 += (halfCornerSize * 2) / Vector3.Distance(cornerPositions3d1[i], cornerPositions3d1[(i + 1) % 4]);
}
distanceScale1 /= 4;
6. Finally I find the 3D distance between related corners and multiply by the scaling factor to get distance in mm:
for(int i = 0; i < 4; i++)
{
distance[i] = Vector3.Distance(cornerPositions3d1[i], cornerPositions3d2[i]) * scalingFactor;
}
The distances acquired are never truly correct. I used the cutting board as it allowed me easy calculation of what the distances should be. The above image calculated a distance of 147mm (expected 150mm) for corner 1 (red to purple). The image below shows 188mm (expected 200mm).
What is also worrying is the fact that when measuring the distance between marker corners sharing an edge on the same marker, the 3D distances obtained are never the same. Another thing I noticed is that the brown dots never seem to exactly match up with the colored dots. The colored dots are the coordinates used as input to the CoPlanar posit. The brown dots are the calculated positions from the center of the marker calculated via POSIT.
Does anyone have any idea what might be wrong here? I am pulling out my hair trying to figure it out. The code should be quite simple, I don't think I have made any obvious mistakes with the code. I am not great at maths so please point out where my basic maths might be wrong as well...
You are using way to many black boxes in your question. What is the focal length in the second step? Why go through ypr in step 3? How do you calibrate? I recommend to start over from scratch without using libraries that you do not understand.
Step 1: Create a camera model. Understand the errors, build a projection. If needed apply a 2d filter for lens distortion. This might be hard.
Step 2: Find you markers in 2d, after removing lens distortion. Make sure you know the error and that you get the center. Maybe over multiple frames.
Step 3: Un-project to 3d. After 1 and 2 this should be easy.
Step 4: ???
Step 5: Profit! (Measure distance in 3d and know your error)
I think you need to have 3D photo (two photo from a set of distance) so you can get the parallax distance from image differences

Drawing an I-Beam based on two points

I have two Point structures and I need to draw an I-Beam based on those points, where each point represents the cross-section on either side of the I-Beam. The width of the end caps should be fixed and arbitrary.
Basically I need to draw three lines. First I'll DrawLine(Point1, Point2), then I need the math to figure out how to draw the next two lines on perpendicular angles so that they are centered on Point1 and Point2.
The image below shows what I need to draw based on the center line. However, this line can be at any angle. The Point1 and Point2 that connect the line can be anywhere in a 2D space.
You can try playing around with LineCaps:
protected void DrawIBeam(Graphics g, Point fromPoint, Point toPoint)
{
using (GraphicsPath hPath = new GraphicsPath())
{
hPath.AddLine(new Point(-5, 0), new Point(5, 0));
CustomLineCap myCap = new CustomLineCap(null, hPath);
myCap.SetStrokeCaps(LineCap.Round, LineCap.Round);
using (Pen myPen = new Pen(Color.Black, 2))
{
myPen.CustomStartCap = myCap;
myPen.CustomEndCap = myCap;
g.DrawLine(myPen, fromPoint, toPoint);
}
}
}
and call it:
DrawIBeam(e.Graphics, new Point(10, 10), new Point(60, 60));
From CustomLineCap Class
Assuming a width that's half the width of the I part of the I beam, first you find the slope of the first line you drew.
Next, you take the negative inverse of the slope, and draw a line from Point1 of length width in both directions. That's why width is half of the width you want to draw.
Finally you draw a line from Point 2 of length width in both directions.
Here's the mathematical formula for drawing a perpendicular line.

ZedGraph - How to display a cursor at an x,y point without using the mouse?

I am drawing a curve in Zedgraph like this:
GraphPane myPane = zgc.GraphPane;
PointPairList list1 = new PointPairList();
for(int i =0; i<10; i++)
list1.Add(i,i);
LineItem myCurve = myPane.AddCurve("Title",
list1, Color.Red, SymbolType.None);
zgc.AxisChange();
zgc.Refresh();
How can I display a cursor (or any other graphic object) at a certain x, y point on myCurve like this:
SetCursor(myCurve, list1[3]);
Knowing specific point of your curve you can use GraphPane.GeneralTransform(...) method
So using following code:
var myPoint = myCurve[3];
var screenPoint = myPane.GeneralTransform(myPoint.X, myPoint.Y, CoordType.AxisXYScale);
would give you coordinates transformed to specific point on screen (in pixels).
Then you need to find some higher-level method (probably in windows forms...) that would move your cursor to that point.
Here is a simple and more efficient example to create a cross cursor wich is part of the objects collection of the graph so you can operate zooming, printing on it. It add two "LineObj" in the "GraphObjList" collection.
The code : Put a cursor at the 10th point of the first curve
Dim myPane As GraphPane = zg1.GraphPane
Dim myPoint As PointPair = myPane.CurveList.Item(0).Points(10)
Dim CurseurV1 As New LineObj(Color.Blue, myPoint.X,myPane.YAxis.Scale.Min, myPoint.X, myPane.YAxis.Scale.Max)
CurseurV1.Line.Width = 0.5
myPane.GraphObjList.Add(CurseurV1)
Dim CurseurH1 As New LineObj(Color.Blue, myPane.XAxis.Scale.Min,myPoint.Y, myPane.XAxis.Scale.Max, myPoint.Y)
CurseurH1.Line.Width = 1
myPane.GraphObjList.Add(CurseurH1)
It's done : you'd have a blue "cross" cursor on your graphe using ZedGraph.dll Version 5.1.2.878.

Categories