拟合"二次" 3D中的表面到数据点

时间:2018-03-01 16:53:42

标签: python python-2.7 math 3d data-fitting

我正在尝试将二次平面拟合到python中的数据点云。我的飞机功能的形式是

   f(x,y,z) = a*x**2 + b*y**2 + c*x*y + d*x + e*y + f - z

目前,我的数据点没有与之关联的错误,但是,如果需要,可以假设一些错误。根据{{​​3}}的建议,我计算出从点p0 =(x0,y0,z0)(对应于我的数据点)到平面上的点的垂直距离p =(x,y,z)关注here。然后我结束了

def vertical_distance(params,p0):
    *** snip ***
    nominator = f + a*x**2 + b*y**2 + c*x*y - x0*(2*a*x-c*y-d) - y0*(2*b*y-c*x-e) + z0
    denominator = sqrt((2*a*x+c*y+d)**2 + (2*b*y+c*x+e)**2 + (-1)**2)
    return nominator/denominator

最终,我认为我需要最小化的是vertical_distance函数。我很乐意在两个维度上提供一个起始参数列表(params)和数据点数组,但是,我不确定如何在3D中实现这一点。 ODR包似乎只允许包含x,y或2维的数据。此外,如何将平面(p)上的点实现到最小化程序中?我想在拟合操作期间,点会根据参数优化而变化,从而确定当时平面的精确方程。

1 个答案:

答案 0 :(得分:0)

我猜«二次曲面»将是一个比“飞机”更正确的术语。

问题是适合z = a x ^ 2 + b y ^ 2 + c x y + d x + e y + f 给出一组点P。

要通过优化来实现这一点,您需要制定残差函数(例如,垂直距离)。

对于P残差的每个3D点p

| p_2 - p_0 ^ 2 + b p_1 ^ 2 + c * p_0 * p_1 + d p_0 + e p_1 + f |

你需要最小化所有残差,即它们的平方和,改变参数a ... f。

以下代码在技术上应该解决上述问题。但是适应这个问题是多极端的,如果没有良好的起点或搜索全球化,这样的例程可能无法找到正确的参数集。

import numpy
import scipy.optimize

P = numpy.random.rand(3,10) # given point set

def quadratic(x,y, a, b, c, d, e, f): 
  #fit quadratic surface
  return a*x**2 + b*y**2 + c*x*y + d*x + e*y + f

def residual(params, points):
  #total residual
  residuals = [
    p[2] - quadratic(p[0], p[1],
    params[0], params[1], params[2], params[3], params[4], params[5]) for p in points]

  return numpy.linalg.norm(residuals)

result = scipy.optimize.minimize(residual, 
                                 (1, 1, 0, 0, 0, 0),#starting point
                                 args=P)