将椭球拟合到3D数据点

时间:2011-09-01 15:00:44

标签: math geometry least-squares

我有一大堆3D数据点,我想要适合椭圆体。

我的数学很差,所以在没有任何数学库的情况下实现最小二乘法时遇到了麻烦。

有没有人知道或者有一段代码可以将椭球放到数据中,我可以直接插入到我的项目中?在C中最好,但从C ++,Java,C#,python等转换对我来说应该没问题。

编辑:能够找到该中心也将是一个巨大的帮助。请注意,这些点的间距不均匀,因此取平均值不会产生中心。

9 个答案:

答案 0 :(得分:6)

你去:

本文描述了将椭圆体拟合到多个维度,以及找到椭圆体的中心。希望这会有所帮助,

http://www.physics.smu.edu/~scalise/SMUpreprints/SMU-HEP-10-14.pdf

(顺便说一句,我假设这个答案有点晚了,但我想我会为那些在你的问题中遇到同样事情的人添加这个解决方案:)

答案 1 :(得分:2)

如果你想要最小体积的封闭椭圆体,请查看bounding ellipsoid的这个SO答案。

如果你想要在最小二乘意义上得到最佳拟合椭圆,请查看error ellipsoids的MATLAB代码,在那里找到均值移位3D点的协方差矩阵,并用它来构造椭球。 / p>

答案 2 :(得分:1)

Least Squares数据拟合可能是一种很好的方法,可以提供您描述的数据的性质。 GNU Scientific Library包含linearnon-linear最小二乘数据拟合程序。在您的情况下,您可以将数据转换为线性空间并使用线性最小二乘,但这取决于您的实际用例。否则,您将需要使用非线性方法。

答案 3 :(得分:1)

我找不到一个很好的基于Java的算法来拟合椭圆体,所以我最终自己编写了它。对于具有2D点的椭圆,存在一些良好的算法,但是对于具有3D点的椭圆体则不是。我尝试了几个不同的MATLAB脚本,最终选择了Yury Petrov的Ellipsoid Fit。它适合椭圆体到多项式Ax ^ 2 + By ^ 2 + Cz ^ 2 + 2Dxy + 2Exz + 2Fyz + 2Gx + 2Hy + 2Iz = 1.它不使用任何约束来强制椭圆体,所以你必须要有相当多的点,以防止随机的quardic适合而不是椭圆体。除此之外,它的效果非常好。我使用Apache Commons Math编写了一个小型Java库,用Java实现了Yury Petrov的脚本。可以在https://github.com/BokiSoft/EllipsoidFit找到GIT存储库。

0

答案 4 :(得分:1)

我们在这里开发了一套Matlab和Java代码来拟合椭圆体: https://github.com/pierre-weiss

您还可以查看我们的开源Icy插件。以下教程可能会有所帮助: https://www.youtube.com/endscreen?video_referrer=watch&v=nXnPOG_YCxw

注意:大多数现有代码都符合通用二次曲线,并且不会形成椭圆形。为了获得更强大的稳定性,您需要使用凸面编程而不仅仅是线性代数。这是在指定的来源中所做的。

干杯, 皮尔

答案 5 :(得分:0)

我有个主意。近似解决方案,不是最好的,但会保持内部点。在XY平面中找到将获得所有点的半径R1。对于XZ平面(R2)和YZ平面(R3)也是如此。然后使用每个轴上的最大值。 A = max(R1,R2),B = max(R1,R3),C = max(R2,R3)。 但是,首先找到所有点的平均值(中心)并将其与原点对齐。

答案 6 :(得分:0)

我刚刚经历了同样的过程。 这是一个基于Nima Moshtagh工作的python模块。在很多地方引用过,但在这个问题中也提到了Bounding ellipse

该模块还处理最终椭球的绘图。享受!

https://github.com/minillinim/ellipsoid/blob/master/ellipsoid.py

答案 7 :(得分:0)

我不久前将Yury Petrov的最小二乘法Matlab钳工移植到Java,它只需要JAMA:https://github.com/mdoube/BoneJ/blob/master/src/org/doube/geometry/FitEllipsoid.java

答案 8 :(得分:0)

这是基于随机搜索找到病灶的非常简单的方法。不使用线性代数。因此,如果您使用非完美的解决方案还可以:

3DPoints - Array of some Amount of points
vecCenter - average of 3DPoints
AngleCosine - cos of angle between two vectors

RandomOrder(3DPoints)

vecFocus := (0, 0, 0)
for i := 0 to Amount:
    vecRadius := 3DPoints[i] - vecCenter

    // Change vecRadius direction to parallel
    if AngleCosine(vecFocus, vecRadius) < 0 then
        vecRadius *= -1
    vecFocus += (vecRadius - vecFocus) / Amount

通过向后第二次传递数组可以改善结果 将焦点放在vecCenter +/- vecFocus