fitting two ellipses to outline of a body - java

I'm trying to fit two ellipses to what happens to be the top view / outline of a body. For simplicity let's use the following example:
As you can see, this simple body is made up of a long core (blue) and a head (red). In reality this outline would be in one color, I'm just using two colors for visualization purposes here.
I know how to fit a single ellipse to either parts of that outline, but I do not know how to do the fit to two ellipses, given the constraint that these two ellipses are actually connected. In this particular case the constraint is that the two ellipses will never part and that there can only be a certain angle between ellipse 1 and ellipse 2.
I'm grateful for any pointers that tell me how to write a function, so that after calling magic_fitting_function(body_outline) the program returns to me the coordinates of the two underlying ellipses:
EDIT1:
what is are the minimal requirements that could make solving this problem easier? E.g. if I were given one point, two points, etc, how would that possibly simplify the problem?
EDIT2:
I'm looking for a programming language independent solution.
EDIT3:
any hints on how to formulate the constraint of these two ellipses being located in a certain relationship to each other programmatically? E.g.: I know that the small ellipse will always be located at one end of the major axis of the big ellipse. Plus the small ellipse can only rotate by +- 90 degrees relative to the big ellipse.

I have never solved this problem, so I'm just throwing out a suggestion.
First, generate a bounding ellipse for the entire figure in order to determine what are the topmost and the bottommost points. (This step may not be necessary if you have a better way of finding these points.)
Next, detect the location of the "neck" by using a modified binary search. (Here I'm assuming that your bounding ellipse has a vertical orientation, as though the figure were standing up or standing on its head.) Generate two sets of bounding ellipses: one with an ellipse from the top of the figure to the 1/4 point of the figure (meaning if you draw a line through the bounding ellipse then the 1/4 point is between the top-left point and the middle) and with an ellipse from the 1/4 point to the bottom of the figure, and one with an ellipse from the top of the figure to the 3/4 point and with an ellipse from the 3/4 point to the bottom of the figure; the set of ellipses with the smaller total area is the one that is better encapsulating the head. Continue the search (e.g. next test an ellipse from the top to the 1/8 point / 7/8 point, and/or from the top to the 3/8 point / 5/8 point) until you've minimized the total bounding area of the set of ellipses; the point at which the ellipses meet is the neck. (No need to be too precise with this, it probably doesn't make much difference if you put the neck at the 34/256ths point or at the 35/256ths point.)
To detect the neck you may want to use bounding boxes instead of bounding ellipses.
Finally, adjust the two bounding ellipses in order to meet their angle constraints, e.g. by moving their extreme points in 5% increments (so assuming that the head ellipse's extreme points are on the y-coordinates 0 and 50 and the body ellipse's extreme points are on the y-coordinates 50 and 200, adjust them so that their extreme y-coordinates are on 0 and 60 and on 40 and 200).

If you have the complete outline, you can find where the two ellipses intersect - just look for the two sharp corners where the first derivative of your outline becomes discontinuous. Then, draw a straight line between those corners.
Everything on one side of the line is in ellipse A, everything on the other side is in ellipse B. The sharp corners are in both ellipses. Now, just fit a single ellipse to each of the two ellipses you've found and recalculate the points where the fitted ellipses intersect.

You can try isolating ellipses using the Hough transform. There are some FEX tools out there that are worth trying, for example this Ellipse Detection Using 1D Hough Transform.

Find the two points that are furthest from each other. One will belong to Ellipse1, the other to Ellipse2.
Check the nearest neighbors of these points to get 5 points belonging to Ellipse1, and 5 to Ellipse2.
Check out Wikipedia, and choose your favorite equation of an ellipse.
Using junior high algebra, for each ellipse, plug in the points to get 5 simultaneous equations, and solve these to get the 5 parameters that define your ellipse.
EDIT
I didn't realize this was tagged "matlab". In that case, once you have identified some points for each ellipse, there are matlab functions for fitting the points to an ellipse.

Related

Determining IF & WHERE a line intersects with a 2D plane (in 3D space)

The following problem im working on is for one of my favorite past-times: game development.
Problem:
We're in 3D space. I'm trying to determine if a line between two vectors in said space is passing through a circle; the latter of which consists of: center vector, radius, yaw & pitch.
In order to determine that, my aim is to convert the circle to a plane which can either be infinite or just have the diameter of the circle for all it's sides.
Should the line between the two vectors in fact pass through that plane, i am left with the simple task of determining wether that intersection point is within the radius of the circle, in which case i can return either true or false.
What's already working:
I have my circles set up and the general framework is there. The circles are appearing/rendered in the 3D space exactly as specified, great!
What was already tried:
Copied some github gist codes and tried to make them work for my purposes. I kinda worked, sometimes at least. Unfortunately due to the nature of how the code was written, i had no idea what it was doing and just scrapped all of that.
Researched the topic a lot, too. But due to me not really understanding the language people speak when talking about line/plane intersections, i could have read the answer without recognizing it as such.
Question:
I'm stuck at line intersections. No idea where to go and how it works logically! So, where do i go from here and how can one comprehend all of this?
Note:
I did tag this issue as "java", but i'm not looking for spoon-fed code. It's a logical issue i'm trying to get past. If explained well enough, i will make the code work with trial and error!
Say if your circle is a circle in the XY plane with its centre on (0,0,0) and radius 1. How would you solve that?
You would check the values of X and Y when Z is equal to zero. And X squared plus Y squared would be less than 1 (radius squared) if the line passes through the circle.
In other words, you could transform the 3D coordinates to a simpler reference frame. So I think you need to learn transformation of 3D coordinates, which is really not too hard to do. You need to rotate the 3D space around until the centre vector only has a Z component, and yaw and pitch are zero. And then offset the coordinates so the circle centre is in (0, 0, 0). Then apply the same transformation to the line. You could lastly scale by radius, but to be honest that is not so important since the circle math is easy.

The shortest connection algorithm, mind game

This is a question from a mind games book. I tried solving it like this (http://pastebin.com/sdfcuxW1) but had no luck. It also has to be very optimized to process outputs for 2000 input coordinates under 4 seconds.
Any suggestions about my code, or any new algorithm ideas would be very helpful.
Question:
We have a coordinate plane, and we are only using the first quadrant. We are supplied with a number of coordinates each with +X and +Y values. For example 0,2 - 5,4 etc. We are required to connect each of these coordinates with rectangles (one corner of the rectangle touches one coordinate and another corner touches another coordinate) so that all coordinates are in contact with each other (no left-outs). We also have to make sure that the rectangles that we use to connect our 2 coordinates do not overlap with any other coordinate (on the edges is fine). What kind of algorithm can print out the best solution to this problem, given that the goal is to use the smallest total rectangle area possible.
http://cl.ly/image/1P012s3p1E1g
purple areas are rectangles and green dots are coordinates. we can have rectangles which have 0 height of width, which consume no area.
What I couldn't figure out: find the closest coordinates to our starting coordinate is easy. but it is hard to make sure that all coordinates are connected together. i always get pieces of coordinates floating in different areas of the plane. my code also lags with >1000 points.
Here is a solution:
Let's model this problem as a graph problem.
The vertices are the given points.
There is an edge between every pair vertices. The weight of this edge is the area of the rectangle formed by this pair of points.
The answer is the minimum spanning tree in this graph. We can use Prim's algorithm to find it.
The time complexity of this solution is O(n ^ 2).
The only question is: why can't a rectangle generated by this algorithm contain another point? I will not post a formal proof here, but drawing some pictures shows that if there is such a rectangle, the solution is not optimal(an idea of a proof: let's assume that there is a point inside. We can split this rectangle into two so that this points becomes one of their corner. The total area can only decrease after performing this operation).

Java circle intersection - central section

I'm trying to get the coordinates of the arcs (denoted in blue) (so that I can visually draw them [in Android path.drawArc()]) of any 2 (and eventually $n$) circles for the 'central' portion (denoted in red).
I have found this, but unfortunately I'm not at all mathematically minded!
I have coded something to find the intersection points... If that helps?
I see no path.drawArc(), only Canvas.drawArc, Path.addArc and Path.arcTo. All of these need a RectF oval argument which I would guess describes the size and position of the circle. So if you want to draw the right boundary of the lens-shaped area, this belongs to the boundary of the left circle, so you'd set oval to the bounding box of the left circle. Then you need two angles, startAngle and sweepAngle. You can get them from Math.atan2(y, x), where (x, y) is the vector which points from the center of the circle to one of the points of intersection. So knowing the points of intersection will be very useful. You'd use one to compute the start angle and the other the end angle of the first arc. The sweep angle is simply the difference between end and start. For the second arc, reverse the roles of start and end and you'll obtain an essentially closed path, although you might have to issue an explicit close call to make that closing explicit.
An alternative approach would be using Path.op(circle1, circle2, Path.Op.INTERSECT). circle1 and circle2 could be formed by Path.addCircle. This approach would delegate the whole intersection math to the Framework, but it does require a recent API (namely API level 19), so it will not work on older devices.
All of the above is untested, from reading the reference and knowing how similar frameworks behave.

Polygon "Fixing" Algorithm

I bring you a maybe complex question which i would love your help with. Allow me to go straight to the point:
I desire an algorithm or logic in which i draw a shape using my mouse (for example a square) and it becomes a perfect square, with all the 4 sides in straight lines and perfectly regular. A human-drawn square is hardly perfect, but i wish that after it goes through the "filter" of this algorithm ,it becomes such.
A fine example of what i wish is in the game Trine, where the Wizard works by a similar principle: You draw a shape in the screen and it becomes the closest shape, that is, if you draw something similar to a square it becomes a perfect square box, but if you draw a triangle it becomes a perfect triangular box. Its like it detects what kind of shape it is and then draws a better version of it.
I want this for a game, just so you know what is the goal of all this.
Please help me figure out either the algorithm or logic behind this, or at least tell me what is the name of this kind of action (:
P.S. i added a simple image so it becomes even more clear what i intend =)
If I had to implement this task, I would store the recognizable patterns, and would try to make a match for them.
Take the minX, maxX, minY, maxY values form the user-drawn points, that will help you to scale the pattern. Choose the scaling so that the aspect ratio for the pattern would be the average of the X and Y aspect ratios.
The patterns can consist of certain number of straight lines. The pattern matches if
There are no points outside of the threshold
There is at least one user-drawn point close to each key points in the pattern
If you have the pattern matched, you will have the key points for your pattern (calculating the center of your pattern, and the size/aspect ratio). Then you can replace the user-drawn points with your image - that may be totally different from the pattern used to match (imagine a circle).
There are many ways to do this. One way that you could do it is to create a neural net that recognizes these shapes. I would generate variations of circles, squares, lines, and triangles with random perturbations to replicate "hand-drawn" versions. Then you would want to represent this as a two-dimensional array (where locations that have been drawn on would be 1's and locations that haven't been drawn on, would contain 0's). You can then convert this two-dimensional array into an input vector of n x n elements. The output of the neural net would be a vector with four elements, each one representing either a line, circle, square, or triangle. You would then train this neural net using your randomly-perturbed images until you end up with a neural net that recognizes the input with an error that is under some error-threshold. This is actually quite similar to recognizing handwritten digits.
Other ways include:
Shape contexts.
k-means clustering
Support vector machines
You don't have just an arbitrary shape, you also have the shape's path. So try counting corners. Decide on a angle threshold that will represent a corner. For each point, sample the next consecutive x number of points. Measure the angle between the first half and second half. If the angle surpasses your threshold, consider it a corner. (Obviously select the point that give you the best angle with the least amount of error, not just the first one that surpasses the threshold.) Mark the location of the corners and draw your shape to match.
Ellipses & lines: if no angles are detected, sample a few segments. Measure the orientation. If they are very similar, then line. If very different, then ellipse. If ellipse, find the bounding box and draw inside.

Connect the dots - connect the line between contour points

I have a gray scale image of 64x64. I found the dots of the contour by a simple algorithm:
find brightest spot (Example: 100)
divide by 2 (100/2 = 50)
define a band around the result (50-5=45 to 50+5=55)
mark all dots that have value in the band (between 45 to 55)
The question now is, how do I decide of the order of connecting the dots?
(All references will be accepted, links, thoughts, etc')
Your algorithm allows the entire image, save for one pixel, to be "the contour". I'm not sure that's exactly what you want; usually a contour is a border between two different regions. The problem with your method is that you can get huge blobs of pixels that have no particularly obvious traversal order. If you have a contour that is a single pixel thick, then the traversal order is much more obvious: clockwise or counterclockwise.
Consider the following image.
........
..%%%%..
.%%%%...
...%%%%.
....%...
........
Here, I've marked everything "dark" (<50, perhaps) as % and everything bright as .. Now you can pick any pixel that is on the border between the two regions (I'll pick the dark side; you can draw the contour on the light side also, or with a little more work, directly between the light and dark sides.)
........
..%%%%..
.*%%%...
...%%%%.
....%...
........
Now you try to travel along the outer edge of the dark region, one pixel at a time. First, you look in the direction of something bright (directly left, for example). Then you rotate around--counterclockwise, let's say--until you hit a dark pixel.
........
..%%%%..
1*5%%...
234%%%%.
....%...
........
Once you hit position 5, you see that it's dark. So, you mark it as part of the contour and then try find the next piece on the contour by sweeping around starting from the pixel you just came from
........
..%%%%..
.0*%%...
.123%%%.
....%...
........
Here 0 is where you came from--and you're not going back there--and then you try pixels 1 and 2 (both light, which is not okay), until you hit pixel 3, which is dark.
In this way, you can walk around the contour pixel by pixel--both identifying the contour and getting the order of pixels--until you collide with the same pixel you started with and will leave from it so that you hit the same pixel that you did the first time you left it. Then the contour is closed. In our example, where we're making an 8-connected contour (i.e. we look at 8 neighbors, not 4), we'd get the following (where # denotes a contour point).
........
..####..
.##%#...
...#%##.
....#...
........
(You have to have this two-in-a-row criterion or if you have a dark region a single pixel wide, you'll walk up it but then not be able to walk back down along it.)
At this point, you've covered one entire boundary. But there might be others. Keep looking for dark pixels next to light ones until you have drawn a contour on top of all of them. Now you've converted your two-level picture (dark & bright pixels) into a set of contours.
If the contours end up too noisy, consider blurring the image first. That will smooth the contours out. (Alternatively, you can find the contours first and then average the coordinates with a moving window.)
In general, a given set of points can be connected in multiple ways to make different shapes.
For example, consider a set of 5 points consisting of the corners of a square and its center. These points can be connected to form a square with one side "dented in" to the center. But which side? There is no unique answer.
Other shapes can be much more complicated, with no obvious way to connect the dots.
If you are allowed to reduce your set of points to a convex hull, then it would be much easier.
I have also tried to create an algorithm that will connect contour dots into the smooth curve. See my open-source project http://outliner.codeplex.com.
The idea is the same as proposed by FUZxxl but I do not understand his worries about complexity: the time of processing is proportional to the total length of all contour strokes.
I don't know if collecting those points will get you far. (I can come up with situations in which it's almost impossible to tell which order they should come in.)
How about going to the brightest point.
Go to the brightness point of, say, 360 points surrounding this point at a distance of, say, 5 pixels.
Continue from there, but make sure you don't go back where you came from :)
Maybe try:
Start at a
Find the nearest point b
Connect a with b
and so on.
Probably not good, as complexity is something like O(n²). You may simplify this by looking only for points near the start, as aioobe suggest. This algorithm is good, if the points are just like 2-3px away from each other, but may create very strange grids.
See also Flood fill
and the lovely applet under SO
mapping-a-branching-tile-path .

Categories