I would like to detect all the angles in a given binary image ,
the image contains a handwriting character (black on white bg),
is there a way that i can get the angles at the lines junctions with 100% accuracy?
My current solution (below) do find the angles but sometimes it finds unwanted angles - that is angles near the junction and not exectly on it (ther's an example below).
In this implementation i use Magick.net,
because i cant post more than two links ill post the input letter image that suppose to be a binary image with blue marks that are the lcations of the angles i want to detect - to get the input binary image they will need to be deleted (sorry).
letter A
My code:
var image = new MagickImage(#"xImg.jpg");
const int Radius = 3;//angle points surrounding circle radius
image.Grayscale(PixelIntensityMethod.Average); //redundent
var lineJunctionsImage = image.Clone(); // an image that will contain only the lines junctions points - angle points
//detect all lines junctions points (black pixels points) in the image
//with morphology method HAM + lineJunction kernel
lineJunctionsImage.Negate();
lineJunctionsImage.Morphology(MorphologyMethod.HitAndMiss, Kernel.LineJunctions);
lineJunctionsImage.Negate();
resulting image
The resulting points are supposed to be the points on the middle of the junctions,
but some are not accurate and its critical for me as i want to draw a circle that surrounds each of them and then take the angle between the point and the two points that intercects the circle, now, the next code is doing it but its to complicated and long so ill just write the algorithm here:
for each junction point p do:
detect all black pixels bi(0 >= i) that intersects a circle
with the above radius (3) that surrounds p,
for each bi pairs calculate the angle between p and the pair
print the angles found with the following protocol:
{point1} {angle point} {point 2}
angle
The angles found (the angle points (middle junctions points) marked):
{11,19} {8,17} {5,19} 112.619
{11,19} {8,17} {9,14} 105.255
{5,19} {8,17} {9,14} 142.12
{24,17} {21,20} {18,19} 116.56
{24,17} {21,20} {20,23} 90
{21,1} {24,0} {27,2} 127.87
{24,0} {27,2} {27,5} 123.7
{26,12} {27,9} {27,6} 161.56
I think the main problem is that the angle points are sometimes not the correct points but a close neighbor.
Maybe someone have a better more accurate idea that will find the correct angles.
Related
So basically programmatically, given 4 3D coordinates for the ceiling of a room as well as 3 pairs of 3D coordinates for the water pipes above the ceiling I am to calculate how many sprinklers I can have in the ceiling if each sprinkler has to be 2500mm from the walls and apart from each other.
I could write out the program but the problem is I don't know how this is calculated.
The problem:
calculate the number of sprinklers, their positions on the room’s ceiling and connect each sprinkler to the nearest water pipe.
The room has a rectangular shape. Ceiling coordinates (x, y, z) are:
(97500.00, 34000.00, 2500.00)
(85647.67, 43193.61, 2500.00)
(91776.75, 51095.16, 2500.00)
(103629.07, 41901.55, 2500.00)
Three water pipes are available:
(98242.11, 36588.29, 3000.00) to (87970.10, 44556.09, 3500.00)
(99774.38, 38563.68, 3500.00) to (89502.37, 46531.47, 3000.00)
(101306.65, 40539.07, 3000.00) to (91034.63, 48506.86, 3000.00)
Sprinklers are to be placed on the ceiling 2500mm away from the walls and from each other.
Please, calculate the number of sprinklers that can be fitted into this room, then calculate
coordinates (x, y, z) of each sprinkler.
For each sprinkler calculate coordinates (x, y, z) of the connection point to the nearest water pipe.
Now I understand that the distance formula between two 3d points is d = sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2).
But I'm not sure how to calculate the number of sprinklers using this. or how to calculate their points of intersection on the water pipes. if i could calculate their points of intersection on each pipe and the distance from that point to each sprinkler, then the nearest pipe would be obvious and that would be the pipe the sprinkler connects to.
I have to write this using c# and the dotnet framework. But would I be able to please get some assistance putting this into the form of pseudocode and understanding how to approach, tackle and calculate this problem? I'm not good at the maths side of this but hopefully once understanding how it is solved, I can then possibly put this into a c# function.
This question is so elaborated that, even in pseudocode, it's a big deal.
You might start with a re-calibration of your rectangle (indeed, the four coordinates you provide form a rectangle indeed): you shift your entire rectangle so that one point equals (0,0). The you rotate your rectangle in order for your rectangle to have following coordinates:
(0,0)
(Xmax, 0)
(0, Ymax)
(Xmax, Ymax)
Once you have this, you can start looking for your algorithm for filling the ceiling with sprinklers. First you can base yourself on this "algorithm":
Fill your rectangle with squares where the length of the line equals two times the given radius.
Once you have this, you can upgrade to the following "algorithm":
Fill your rectangle with circles with the given radius.
Revert everything to the original coordinates (rotating back and shifting back).
Once you have this, you might start calculating the distances to the pipes, using basic "distance-between-point-and-line" formula.
Notice that the ceiling can be tiled with 4x6 squares of side 2500 mm. That tells you the number of sprinklers.
You can find their positions by computing vectors of length 2500 mm, parallel to the sides (first compute unit vectors). It is not too difficult to obtain then coordinates using a matrix arrangement.
Next, you compute the distance of every sprinkler to the three pipes and keep the shortest. (CAUTION: distance to the line segments, not to the lines of support.)
I need an inverse perspective transform written in Pascal/Delphi/Lazarus. See the following image:
I think I need to walk through destination pixels and then calculate the corresponding position in the source image (To avoid problems with rounding errors etc.).
function redraw_3d_to_2d(sourcebitmap:tbitmap, sourceaspect:extended, point_a, point_b, point_c, point_d:tpoint, megapixelcount:integer):tbitmap;
var
destinationbitmap:tbitmap;
x,y,sx,sy:integer;
begin
destinationbitmap:=tbitmap.create;
destinationbitmap.width=megapixelcount*sourceaspect*???; // I dont how to calculate this
destinationbitmap.height=megapixelcount*sourceaspect*???; // I dont how to calculate this
for x:=0 to destinationbitmap.width-1 do
for y:=0 to destinationbitmap.height-1 do
begin
sx:=??;
sy:=??;
destinationbitmap.canvas.pixels[x,y]=sourcebitmap.canvas.pixels[sx,sy];
end;
result:=destinationbitmap;
end;
I need the real formula... So an OpenGL solution would not be ideal...
Note: There is a version of this with proper math typesetting on the Math SE.
Computing a projective transformation
A perspective is a special case of a projective transformation, which in turn is defined by four points.
Step 1: Starting with the 4 positions in the source image, named (x1,y1) through (x4,y4), you solve the following system of linear equations:
[x1 x2 x3] [λ] [x4]
[y1 y2 y3]∙[μ] = [y4]
[ 1 1 1] [τ] [ 1]
The colums form homogenous coordinates: one dimension more, created by adding a 1 as the last entry. In subsequent steps, multiples of these vectors will be used to denote the same points. See the last step for an example of how to turn these back into two-dimensional coordinates.
Step 2: Scale the columns by the coefficients you just computed:
[λ∙x1 μ∙x2 τ∙x3]
A = [λ∙y1 μ∙y2 τ∙y3]
[λ μ τ ]
This matrix will map (1,0,0) to a multiple of (x1,y1,1), (0,1,0) to a multiple of (x2,y2,1), (0,0,1) to a multiple of (x3,y3,1) and (1,1,1) to (x4,y4,1). So it will map these four special vectors (called basis vectors in subsequent explanations) to the specified positions in the image.
Step 3: Repeat steps 1 and 2 for the corresponding positions in the destination image, in order to obtain a second matrix called B.
This is a map from basis vectors to destination positions.
Step 4: Invert B to obtain B⁻¹.
B maps from basis vectors to the destination positions, so the inverse matrix maps in the reverse direction.
Step 5: Compute the combined Matrix C = A∙B⁻¹.
B⁻¹ maps from destination positions to basis vectors, while A maps from there to source positions. So the combination maps destination positions to source positions.
Step 6: For every pixel (x,y) of the destination image, compute the product
[x'] [x]
[y'] = C∙[y]
[z'] [1]
These are the homogenous coordinates of your transformed point.
Step 7: Compute the position in the source image like this:
sx = x'/z'
sy = y'/z'
This is called dehomogenization of the coordinate vector.
All this math would be so much easier to read and write if SO were to support MathJax… ☹
Choosing the image size
The above aproach assumes that you know the location of your corners in the destination image. For these you have to know the width and height of that image, which is marked by question marks in your code as well. So let's assume the height of your output image were 1, and the width were sourceaspect. In that case, the overall area would be sourceaspect as well. You have to scale that area by a factor of pixelcount/sourceaspect to achieve an area of pixelcount. Which means that you have to scale each edge length by the square root of that factor. So in the end, you have
pixelcount = 1000000.*megapixelcount;
width = round(sqrt(pixelcount*sourceaspect));
height = round(sqrt(pixelcount/sourceaspect));
Use Graphics32, specifically TProjectiveTransformation (to use with the Transform method). Don't forget to leave some transparent margin in your source image so you don't get jagged edges.
I need to implement connections in the form of curved lines in C# (Unity). I would like to get the result as similar as possible to the implementation in Miro.com (see screenshot).
After attaching the curve, I calculate the path of the cubic Bezier curve. For this first segment, the anchor points and offsets from the objects it connects are used. There are no problems at this stage.
Problem: When dividing the curve into segments by clicking and dragging one of the blue points of the segment (see screenshot), it is split in two in the middle. At the junction of two new curves, a new interactive (movable) point is formed for which the tangent and coordinates of the control points are unknown. I need to find the position of these control points every time the position of the interactive points changes (white points in the picture below). Moreover, the curve should not drastically change its position when dividing, not form loops, have different lengths of control point vectors (I'm not sure here) and behave as adequately as possible (like on the board in Miro).
By control points I mean 2 invisible guide points for the Bezier segment.
In black I painted the known control points, and in red those that I need to find. (Pn - interactive points, Cn - control points)
The algorithms I have tried to find them give incorrect distances and directions of control points.
The following algorithms were tested:
Interpolation from Tacent - jumps of the curve when separating, inappropriate direction and amount of indentation of control points;
Chaikin's algorithm - curve jumps during separation, creates loops;
"Custom" interpolation based on guesses (takes into account the distance to the center of the segment between the start and end points of the segment, as well as the direction between the start and end points) - has all the same problems, but looks slightly better than those above.
I suspect the solution is to chordally interpolate the points using a Catmull-Rom spline and translate the result to points for a Bezier curve. However, there are still problems with implementation.
The curves from 3DMax also look very similar. In their documentation, I found only a mention of the parametric curve.
Methods that I did not use (or did not work):
Catmull-Rom interpolation;
B-spline interpolation;
Hermitian interpolation;
De Casteljau's algorithm (although it seems not for this)
I would be immensely grateful for any help, but I ask for as much detail as possible.
Find helpful sources to understand bezier curves here and here.
To do what you want, I would give a try to the Catmull-Rom approach which I believe is much more simple than Bezier's, which is the one used in the itween asset, that is free, and you got plenty of funtionality implemented.
If you want to stick to the bezier curves and finding the control points, I will tell you what I would do to find them.
For the case of 2 control point bezier curve:
P = (1-t)P1 + tP2
To get to know the control points P1(x1,y1) and P2(x2,y2), you need to apply the equation in a known point of your curve. Take into account that the 2D equation is vectorial, so each points provides 2 equations one for x and one for y, and you got 4 unknows, x and y for each point.
So for the first node of the curve (t=0), you would have:
Px = (1-0)P1x + 0*P2x
Py = (1-0)P1y + 0*P2y
For the last point (t=1)
Px = (1-1)P1x + 1*P2x
Py = (1-1)P1y + 1*P2y
With these 4 equations I would try to achieve the control points P1 and P2. You can do it with t=0 and t=1 which are the supposed points you know of your curve and the ones that simplify the math due to the t values, but you should be able to use any as long as you know the points coords in the curve for determined t.
If the curve is a 3 control point bezier, you would need 6 equations for the 3 control points and so on.
I think that the best approach is to compound the curve of cuadratic curves composition, and calculate the control points for each chunk, but I am not sure about this.
Once maths are understood and control points achieved, In case that was successful I would try to implement that in the code.
Given a 3D solid model and an edge, I am testing whether that edge is concave or convex.
What is the best way to do this? I'd like to minimize the assumptions regarding the input geometry. My first pass at the problem takes the average of the vertices of the two adjacent faces to generate center points, offsets one of those points by the face normal at that point, and tests whether the offset point is closer or farther to the opposing face than the original. This works for pairs of simple faces, approximately the same size. It fails, for example, with small faces far from the center of larger faces.
I'm doing this in Revit, but I imagine the problem is the same in Rhino, Catia, any solid modeler. From the edge I can extract the adjacent faces. I know the faces are oriented correctly such that the normals point outward. I can project 3D points to the faces, calculate normals of the faces at those points, etc.
Here's the code for the naive version:
public static Boolean AreFacesConcave(Face face_0, Face face_1, Document doc)
{
UV uvMid_0 = VertexAverageUV( face_0 ); //3D average of the vertices
UV uvMid_1 = VertexAverageUV( face_1 ); // approximates the center of the face
XYZ pt_0 = face_0.Evaluate(uvMid_0);
XYZ pt_1 = face_1.Evaluate(uvMid_1);
// normals at those points
XYZ normal_0 = face_0.ComputeNormal(uvMid_0);
XYZ normal_1 = face_1.ComputeNormal(uvMid_1);
// third point, offset from face 2 by normal
XYZ pt_2 = pt_1.Add(normal_1.Normalize());
Double d0 = pt_0.DistanceTo(pt_1);
Double d1 = pt_0.DistanceTo(pt_2);
return (d1 < d0);
}
If you know that normal vectors always are outward, get two points A and B inside two adjacent faces (either mean of three non-collinear vertices or your 'center points').
Then check the sign of dot (scalar) product of vectors AB and nA (normal to the face containing point A).
Result = DotProduct(AB, nA)
Negative sign denotes 'convex' edge, positive - 'concave' one.
2D example: nA is outward normal, D-edge for CDF is concave, D-edge for CDE is convex
At the moment I have detected edges in an image and I am planning to extract line segments from the edges using a hough transform. Once I have the segments I am planning on finding corners where two segments cross over. Is there an algorithm that can detect rectangles from the corners? say I have four corners detected, is it possible to get the relative lengths of the sides of the rectangle that the four corners make up knowing a rectangle has 4 right angles?
The reason I want to do this is so I can extract the texture bound by the rectangle and draw it as a flat rectangle on the screen.
Edit:
Thanks for the answers so far, I think I should explain my problem more clearly as I think I was slightly misinterpreted. I am actually trying to transform a warped rectangle into a flat rectangle. I read through some of the aforge articles and saw this function: link. I was wondering if it is possible to determine the ratio between the sides of the rectangle just from the 4 corners?
You're already using the tool you need - the Hough transform.
The standard formulation of the Hough transform is used to identify lines within an image, by translating from the (x,y) space of the image to the (theta,d) solution space of possible lines.
You can do the same thing to identify candidate rectangles by translating from the (x,y) space of the image to the solution space of possible rectangles (theta,d,width,height,rotation).
Taking this approach retains the strengths of the Hough transform to work with partially visible features from your image - a two step approach using the Hough transform to identify edges, and combining those edges in to rectanges, will fail to identify a rectangle if one edge or corner is sufficiently obscured.
Her is some code you can use to detect quadrilateral shapes in an image using the AForge.NET Framework:
// get angles between 2 pairs of opposite sides
float angleBetween1stPair = Tools.GetAngleBetweenLines(corners[0], corners[1], corners[2], corners[3]);
float angleBetween2ndPair = Tools.GetAngleBetweenLines(corners[1], corners[2], corners[3], corners[0]);
// check 1st pair for parallelism
if (angleBetween1stPair <= angleError)
{
subType = PolygonSubType.Trapezoid;
// check 2nd pair for parallelism
if (angleBetween2ndPair <= angleError)
{
subType = PolygonSubType.Parallelogram;
// check angle between adjacent sides
if (Math.Abs(Tools.GetAngleBetweenVectors(corners[1], corners[0], corners[2]) - 90) <= angleError)
subType = PolygonSubType.Rectangle;
//get length of 2 adjacent sides
float side1Length = (float)corners[0].DistanceTo( corners[1] );
float side2Length = (float)corners[0].DistanceTo( corners[3] );
if (Math.Abs(side1Length - side2Length) <= maxLengthDiff)
subType = (subType == PolygonSubType.Parallelogram) ? PolygonSubType.Rhombus : PolygonSubType.Square;
}
}
else
{
// check 2nd pair for parallelism - last chence to detect trapezoid
if (angleBetween2ndPair <= angleError)
{
subType = PolygonSubType.Trapezoid;
}
}
See this article for examples of how to detect various shapes:
http://www.aforgenet.com/articles/shape_checker/
Here's a link to download the AForge.NET Framework:
http://www.aforgenet.com/framework/downloads.html
try this brother :
http://www.emgu.com/wiki/index.php/Shape_(Triangle,_Rectangle,_Circle,_Line)_Detection_in_CSharp
have fun coding :)