三维平面方程定义为:
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'
可以达到最佳效果。
答案 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)