正确实现scipy.optimize以求解平面方程的所有参数

时间:2019-03-20 19:26:54

标签: python scipy

三维平面方程定义为:

a * x + b * y + c * z + d = 0

其中x,y和z是数据点的坐标,而a,b,c和d定义平面参数。 我有一堆x,y,z数据点,我知道它们大致构成一个平面。现在,我想将这些数据点拟合到平面上并找到a,b,c,d参数。 到目前为止,我具有此功能:

import scipy.optimize as op
def _plane(ws,x,y,z):
    cost = np.sum(ws[0]*x + ws[1]*y + ws[2]*z + ws[3])
    print cost, np.sum(ws)
    return cost
out = op.minimize(_plane,ws,args=(x,y,z),method='SLSQP',options={'maxiter':1000, 'disp':1})

ws = plane([np.mean(x),np.mean(y),np.mean(z),0.001],x,y,z)

输出:

130.78467 -0.3011288588643074
130.78467 -0.3011288588643074
130.78467 -0.3011288439631462
130.78467 -0.3011288439631462
130.78468 -0.3011288439631462
130.78467 -0.3011288439631462
-119765.375 -1024.3011288588643
-119765.375 -1024.3011288588643
-119765.375 -1024.3011288439632
-119765.375 -1024.3011288439632
-119765.375 -1024.3011288439632
-119765.375 -1024.3011288439632
Optimization terminated successfully.    (Exit mode 0)
            Current function value: -119765.375
            Iterations: 2
            Function evaluations: 12
            Gradient evaluations: 2
out:      fun: -119765.375
     jac: array([0., 0., 0., 0.])
 message: 'Optimization terminated successfully.'
    nfev: 12
     nit: 2
    njev: 2
  status: 0
 success: True
       x: array([-4.07030255e-01, -8.12448636e-02, -1.02381385e+03,  1.00000000e-03])

如您所见,cost总是在减少,而无论我最初给出的内容如何,​​d的值都不会改变。这个实施正确吗?

更新:

使用cost = abs(np.sum(ws[0]*x + ws[1]*y + ws[2]*z + ws[3]))可以解决优化问题,而设置method='cg'可以达到最佳效果。

1 个答案:

答案 0 :(得分:0)

对于将平面调整为一组点的特定问题,可以使用更简单的方法:

>>> import numpy as np
>>> points = np.array([(3,0,0), (0,4,0), (3,0,1),
...                    (0,4,1), (6,-4,0), (6,-4,1)])

计算质心并从每个点中减去它。

>>> centroid = np.average(points, axis=0)
>>> centered = points - centroid

计算中心点数组的单值分解。第三个特征向量垂直于平面,并且具有范数1,因此您可以将其直接用作平面的a,b,c系数。

>>> _, _, vh = np.linalg.svd(centered)
>>> a, b, c = normal = vh[2]

质心必须位于平面上,因此可以从法向矢量和质心计算出最后一个系数(d)。

>>> d = -normal @ centroid
>>> plane_coefficients = a, b, c, d
>>> print(plane_coefficients)
(0.8, 0.6, 0.0, -2.4000000000000004)