【问题标题】:Fitting an ellipsoid to 3D data points将椭球拟合到 3D 数据点
【发布时间】:2011-11-08 11:48:13
【问题描述】:

我有大量的 3D 数据点,我想将它们拟合成一个椭球体。

我的数学很差,所以在没有任何数学库的情况下我无法实现最小二乘法。

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

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

【问题讨论】:

  • 您希望您的点落在椭圆体的表面上还是您希望您的点在椭圆云中?
  • 我希望它们落在椭圆体的表面,所以中心是空心的。

标签: math geometry least-squares


【解决方案1】:

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

【讨论】:

  • 这就是我到现在为止一直在做的事情。问题是它没有找到椭圆体的实际最大值。另外,我希望所有点的平均值都是中心!但这只有在点均匀分布在表面上时才有效。
  • 嗯,这不是个好主意。 :) 它比一开始看起来更复杂。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    如果您想要最小体积的封闭椭球体,请查看此 SO 答案以获取 bounding ellipsoid

    如果您想要最小二乘意义上的最佳拟合椭圆,请查看error ellipsoids 的此 MATLAB 代码,您可以在其中找到均值偏移的 3D 点的协方差矩阵,并使用它来构造椭圆体。

    【讨论】:

      【解决方案4】:

      给你:

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

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

      (顺便说一句,我假设这个答案有点晚了,但我想我会为任何偶然发现你的问题以寻找相同内容的人添加这个解决方案:)

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

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

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

          【讨论】:

            【解决方案7】:

            我前段时间将 Yury Petrov 的最小二乘 Matlab 拟合器移植到 Java,它只需要 JAMA:https://github.com/mdoube/BoneJ/blob/master/src/org/doube/geometry/FitEllipsoid.java

            【讨论】:

            【解决方案8】:

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

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

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

            干杯, 皮埃尔

            【讨论】:

              【解决方案9】:

              这是一个非常简单的方法来找到焦点,基于随机搜索。没有使用线性代数。因此,如果您对不完美的解决方案感到满意:

              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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2016-09-10
                • 1970-01-01
                • 2011-01-22
                • 2017-02-03
                • 1970-01-01
                • 2015-06-04
                • 2016-10-27
                相关资源
                最近更新 更多