I have a large set of 3D data points to which I want to fit to an ellipsoid.
My maths is pretty poor, so I'm having trouble implementing the least squares method without any math libraries.
Does anyone know of or have a piece of code that can fit an ellipsoid to data which I can plug straight into my project? In C would be best, but it should be no problem for me to convert from C++, Java, C#, python etc.
EDIT: Just being able to find the centre would be a huge help too. Note that the points aren't evenly spaced so taking the mean won't result in the centre.
here you go:
This paper describes fitting an ellipsoid to multiple dimensions AS WELL AS finding the center for the ellipois. Hope this helps,
http://www.physics.smu.edu/~scalise/SMUpreprints/SMU-HEP-10-14.pdf
(btw, I'm assuming this answer is a bit late, but I figured I would add this solution for anyone who stumbles across your question in search for the same thing :)
If you want the minimum-volume enclosing ellipsoid, check out this SO answer for a bounding ellipsoid.
If you want the best fitting ellipse in a least-squares sense, check out this MATLAB code for error ellipsoids where you find the covariance matrix of your mean-shifted 3D points and use that to construct the ellipsoid.
Least Squares data fitting is probably a good methodology give the nature of the data you describe. The GNU Scientific Library contains linear and non-linear least squares data fitting routines. In your case, you may be able to transform your data into a linear space and use linear least-squares, but that would depend on your actual use case. Otherwise, you'll need to use non-linear methods.
I could not find a good Java based algorithm for fitting an ellipsoid, so I ended up writing it myself. There were some good algorithms for an ellipse with 2D points, but not for an ellipsoid with 3D points. I experimented with a few different MATLAB scripts and eventually settled on Yury Petrov's Ellipsoid Fit. It fits an ellipsoid to the polynomial Ax^2 + By^2 + Cz^2 + 2Dxy + 2Exz + 2Fyz + 2Gx + 2Hy + 2Iz = 1. It doesn't use any constraints to force an ellipsoid, so you have to have a fairly large number of points to prevent a random quardic from being fit instead of the ellipsoid. Other than that, it works really well. I wrote a small Java library using Apache Commons Math that implements Yury Petrov's script in Java. The GIT repository can be found at https://github.com/BokiSoft/EllipsoidFit.
We developed a set of Matlab and Java codes to fit ellipsoids here:
https://github.com/pierre-weiss
You can also check our open-source Icy plugin. The following tutorial can be helpful:
https://www.youtube.com/endscreen?video_referrer=watch&v=nXnPOG_YCxw
Note: most of the existing codes fit a generic quadric and do not impose an ellipsoidal shape. To get more robustness, you need to go to convex programming rather than just linear algebra. This is what is done in the indicated sources.
Cheers,
Pierre
Here is unstrict solution with fast and simple random search approach*. Best side - no heavy linear algebra library required**. Seems it worked fine for mesh collision detection.
Is assumes that ellipsoid center matches cloud center and then uses some sort of mirrored average to search for main axis.
Full working code is slightly bigger and placed on git, idea of main axis search is here:
np.random.shuffle(pts)
pts_len = len(pts)
pt_average = np.sum(pts, axis = 0) / pts_len
vec_major = pt_average * 0
minor_max, major_max = 0, 0
# may be improved with overlapped pass,
for pt_cur in pts:
vec_cur = pt_cur - pt_average
proj_len, rej_len = proj_length(vec_cur, vec_major)
if proj_len < 0:
vec_cur = -vec_cur
vec_major += (vec_cur - vec_major) / pts_len
major_max = max(major_max, abs(proj_len))
minor_max = max(minor_max, rej_len)
It can be improved/optimized even more at some points. Examples what it will produce:
And full experiment code with plots
*i.e. adjusting code lines randomly until they work
**was actually reason to figure out this solution
I have an idea. Approximately solution, not the best but will keep points inside. In XY plane find the radius R1 that will obtain all points. Same do for the XZ plane (R2) and YZ plane (R3). Then use the maximums on each axes. A=max(R1,R2), B=max(R1,R3) and C=max(R2,R3).
But, first of all find the average (center) of all points and align it to origin.
I have just gone through the same process.
Here is a python module which is based on work by Nima Moshtagh. Referenced in many places but also in this question about a Bounding ellipse
This module also handles plotting of the final ellipsoid. Enjoy!
https://github.com/minillinim/ellipsoid/blob/master/ellipsoid.py
I ported Yury Petrov's least-squares Matlab fitter to Java some time ago, it only needs JAMA: https://github.com/mdoube/BoneJ/blob/master/src/org/doube/geometry/FitEllipsoid.java
Related
I'd like to draw the 3-simplex which encloses some random points in 3D. So for example:
pts <- rnorm(30)
pts <- matrix(pts, ncol = 3)
With these points, I'd like to compute the vertices of the 3-simplex (irregular tetrahedron) that just encloses these points. Can someone suggest a package/function that will do this? All manner of searching for simplex-related material is dominated by answers that relate to using simplices for other purposes, of which there are many. I just want to compute one and draw it. Seems simple, but I don't seem to know the relevant keywords for what I need.
If nobody can find a suitable package for this, you'll have to settle for doing it yourself, which isn't so difficult if you don't require it to be the absolute tightest fit. See this question over at mathexchange.
The simplest approach presented in this question seems to me to be translating the origin so that all points lie in the positive orthant (i.e, all point dimensions are positive) and then projecting the points to lie within the simplex denoted by each unit vector. To get this simplex in your original coordinate system you can take the inverse projection and inverse translation of the points in this simplex.
Another approach suggested there is to find the enveloping sphere (which you can for instance use Ritter's algorithm for), and then find an enveloping simplex of the sphere, which might be an easier task depending what you are most comfortable with.
I think you're looking for convhulln in the geometry package, but I'm no expert, so maybe that isn't quite what you are looking for.
I have a general question about what method to use for smoothing a 3D (xyz) grid.
My program has large matrixes of 3D points obtained with a stereovision method. The shape of the result is always something like a semisphere, but it has a rugosity due to stereovision errors I want to eliminate.
The question is, how to do it? Rigth now I have half developed a method for soomthing, but I think there may be a better method.
My actual idea is to use Hermite method. The idea is to:
Take all XY and smooth in two directions ->XYnew and XnewY
Convert the Hermite lines into Bezier lines and find the cross point between XYnew and XnewY, having the new point. (Repeat with all points, normally 2000)
Use hermite XYZ smoothing having XYZnew.
Rigth now I have the hermite surface smoothing and hermite line smoothing inplemented in C++, but the middle part is not as easy as espected.
Anyway, my question is, is this a correct method or is there another one which may be better?
Of course the idea is to elliminate the error generated by the stereovision method, this is not a computer graphics problem, is more a data treatment problem
Appendix:
At first I thougth that with a Z smoothing would be suficient, but clearly it is not, there is also a lot of XY error. In the images below you can see the Z fitting working but still it is really rugous as it can be seen in the 2 image. (The colours are deformations and shoul be quite continous)
Unless you have better priors, it's hard to beat the classic Taubin's algorithm: http://mesh.brown.edu/taubin/pdfs/taubin-iccv95a.pdf
Let's say I have a number of points, each defined by an X and Y coordinate in a two-dimensional cartesian coordinate system. The X coordinate of every point is greater than the one of its predecessor, so there can't be any loops.
How can I draw a smooth line through these points? The result should look something like a sine wave, but with varying amplitude and wavelength. It's absolutely fine if it is simplified or approximated as long as it allows me to calculate the Y coordinate of the interpolated points without using any library functions for lines or splines. Language doesn't matter, I'm interested in the algorithm, not the implementation. For full disclosure, I plan to implement it in JavaScript.
I'd like to stay away from complicated math like Bézier splines or something with control points. I feel there must be a simple solution that maybe works with the distance to the points or something like that.
Any idea is appreciated.
Sounds like you need an interpolating polynomial. There are a number of ways you can fit it. Try reading this
http://en.wikipedia.org/wiki/Polynomial_interpolation#Constructing_the_interpolation_polynomial
If you have a large number of points, then you may consider wanting to use an approximation instead otherwise you could suffer from overfitting and poor representation of your data between points. In that case, you could use least-squares polynomial approximation. It depends on the degree of accuracy that you need.
http://en.wikipedia.org/wiki/Least_squares#Linear_least_squares
In particular, if your data is sinusoidal, you can actually approximate data using trignometric basis functions (sine or cosine functions of different integer frequencies) instead of regular powers of x.
Alternatively you can interpolate using splines in a non parametric way that does not involve control points
http://en.wikipedia.org/wiki/Spline_interpolation
Using splines will prevent you getting the potential wild oscillations that you can get using basic high degree polynomial interpolation.
As with all approximation problems, it is hard to give a definitive answer without seeing the data (and the amount of it). Ultimately though if you have a large number of data, basic polynomial interpolation is not your friend as if you have 1000 points to interpolate, you need a 999 degree polynomial.
You cannot avoid "complicated" math here. And it is not that much complicated.
Cubic splines is good solution for your problem. For the similar task I found this paper with short explanation and a matrix which I used for my computations.
You can try using approximation methods. "Least squares" and its modifications are one of the simplest, and easy to implement.
This is something related with Mathematics as well. But this is useful in computing as well.
Lets say you have 10 coordinates. (x1,y1)(x2,y2)..... in 2D Space. (i.e on a X-Y Plane). Can we find a single smooth curve going across the each coordinate.
While expanding the question, If the space is 3D, then can we find an equation of a smooth surface that going across a given set of spacial coordinates?
Are there any Libraries (Any language) \ tools to perform such calculations?
What you should be looking for is some library implementing NURBS (or Non Uniform Rational B-Splines). This will solve your problem in both 2d and 3d, since 2d is just a special case of the 3d.
Roughly speaking, you are not interested in the actual equation, you are only interested in getting the points approximated with smooth curves or surfaces. This is done by finding "control points" in 2d or 3d space, which are multiplied with B-spline base functions. A NURBS library will do this for you.
Cheers !
Edit:
Have a look at this one
you can always fit an order-10 polynomial through the points. that's not necessarily what you want to do, though - fitting a smooth curve via a series of splines will give you a better-looking result. the curve-fitting article on wikipedia gives you a good overview of the various options.
In the 2D case you are asking for curve fitting. This actually exists in excel, where you plot your points (I usually use XY scatter if you have x and y listed) and then right-click on the curve. Select Add Trendline. There you can choose which kind of function you want to fit to and you can ask excel to display it in the image (Tab named Options, check the box "Display equation on chart"). Nice and quick.
Otherwise you can use matlab and use the lsqr (least square method). If you want to find the polynomial closest that best describes your data you could use the polyfit function. It uses the least square method, but returns coefficients. Matlab has a whole set of other algorithms for solving/finding "best" approximations to systems of linear equations. I mention lsqr because it is one of the simplest to implement yourself if you don't have matlab. On the other hand it is for solving sets of linear equations - I don't know anything about your data.
Have a look at splines
in wiki
an interactive introduction
Searching for 'spline interpolation library' might give some useful hints for implementations.
Given an arbitrary sequence of points in space, how would you produce a smooth continuous interpolation between them?
2D and 3D solutions are welcome. Solutions that produce a list of points at arbitrary granularity and solutions that produce control points for bezier curves are also appreciated.
Also, it would be cool to see an iterative solution that could approximate early sections of the curve as it received the points, so you could draw with it.
The Catmull-Rom spline is guaranteed to pass through all the control points. I find this to be handier than trying to adjust intermediate control points for other types of splines.
This PDF by Christopher Twigg has a nice brief introduction to the mathematics of the spline. The best summary sentence is:
Catmull-Rom splines have C1
continuity, local control, and
interpolation, but do not lie within
the convex hull of their control
points.
Said another way, if the points indicate a sharp bend to the right, the spline will bank left before turning to the right (there's an example picture in that document). The tightness of those turns in controllable, in this case using his tau parameter in the example matrix.
Here is another example with some downloadable DirectX code.
One way is Lagrange polynominal, which is a method for producing a polynominal which will go through all given data points.
During my first year at university, I wrote a little tool to do this in 2D, and you can find it on this page, it is called Lagrange solver. Wikipedia's page also has a sample implementation.
How it works is thus: you have a n-order polynominal, p(x), where n is the number of points you have. It has the form a_n x^n + a_(n-1) x^(n-1) + ...+ a_0, where _ is subscript, ^ is power. You then turn this into a set of simultaneous equations:
p(x_1) = y_1
p(x_2) = y_2
...
p(x_n) = y_n
You convert the above into a augmented matrix, and solve for the coefficients a_0 ... a_n. Then you have a polynomial which goes through all the points, and you can now interpolate between the points.
Note however, this may not suit your purpose as it offers no way to adjust the curvature etc - you are stuck with a single solution that can not be changed.
You should take a look at B-splines. Their advantage over Bezier curves is that each part is only dependent on local points. So moving a point has no effect on parts of the curve that are far away, where "far away" is determined by a parameter of the spline.
The problem with the Langrange polynomial is that adding a point can have extreme effects on seemingly arbitrary parts of the curve; there's no "localness" like described above.
Have you looked at the Unix spline command? Can that be coerced into doing what you want?
There are several algorithms for interpolating (and exrapolating) between an aribtrary (but final) set of points. You should check out numerical recipes, they also include C++ implementations of those algorithms.
Unfortunately the Lagrange or other forms of polynomial interpolation will not work on an arbitrary set of points. They only work on a set where in one dimension e.g. x
xi < xi+1
For an arbitary set of points, e.g. an aeroplane flight path, where each point is a (longitude, latitude) pair, you will be better off simply modelling the aeroplane's journey with current longitude & latitude and velocity. By adjusting the rate at which the aeroplane can turn (its angular velocity) depending on how close it is to the next waypoint, you can achieve a smooth curve.
The resulting curve would not be mathematically significant nor give you bezier control points. However the algorithm would be computationally simple regardless of the number of waypoints and could produce an interpolated list of points at arbitrary granularity. It would also not require you provide the complete set of points up front, you could simply add waypoints to the end of the set as required.
I came up with the same problem and implemented it with some friends the other day. I like to share the example project on github.
https://github.com/johnjohndoe/PathInterpolation
Feel free to fork it.
Google "orthogonal regression".
Whereas least-squares techniques try to minimize vertical distance between the fit line and each f(x), orthogonal regression minimizes the perpendicular distances.
Addendum
In the presence of noisy data, the venerable RANSAC algorithm is worth checking out too.
In the 3D graphics world, NURBS are popular. Further info is easily googled.