使用PYTHON将圆柱体拟合到散射的3D XYZ点数据

时间:2017-05-04 13:43:52

标签: python geometry surface point-clouds

在标题中,我想用PYTHON将圆柱体装到一组3D点上。这是一个很好的solution with MATLAB。我们怎样才能用Python做到这一点?

enter image description here

3 个答案:

答案 0 :(得分:3)

David Eberly网站"Fitting 3D Data with a Cylinder"上有一篇文章描述了数学基础并展示了伪代码。

您还可以在同一站点的Geometric Tools Engine中引用C ++代码。我认为可以在NymPy中实现一些辅助数学函数,如矩阵逆等。

答案 1 :(得分:2)

使用scipy.optimize.leastsq,我们可以创建一个误差函数,其中观察到的圆柱半径和建模半径之间的差异被最小化。以下是安装垂直圆柱的示例

import numpy as np
from scipy.optimize import leastsq


def cylinderFitting(xyz,p,th):

    """
    This is a fitting for a vertical cylinder fitting
    Reference:
    http://www.int-arch-photogramm-remote-sens-spatial-inf-sci.net/XXXIX-B5/169/2012/isprsarchives-XXXIX-B5-169-2012.pdf

    xyz is a matrix contain at least 5 rows, and each row stores x y z of a cylindrical surface
    p is initial values of the parameter;
    p[0] = Xc, x coordinate of the cylinder centre
    P[1] = Yc, y coordinate of the cylinder centre
    P[2] = alpha, rotation angle (radian) about the x-axis
    P[3] = beta, rotation angle (radian) about the y-axis
    P[4] = r, radius of the cylinder

    th, threshold for the convergence of the least squares

    """   
    x = xyz[:,0]
    y = xyz[:,1]
    z = xyz[:,2]

    fitfunc = lambda p, x, y, z: (- np.cos(p[3])*(p[0] - x) - z*np.cos(p[2])*np.sin(p[3]) - np.sin(p[2])*np.sin(p[3])*(p[1] - y))**2 + (z*np.sin(p[2]) - np.cos(p[2])*(p[1] - y))**2 #fit function
    errfunc = lambda p, x, y, z: fitfunc(p, x, y, z) - p[4]**2 #error function 

    est_p , success = leastsq(errfunc, p, args=(x, y, z), maxfev=1000)

    return est_p

if __name__=="__main__":

    np.set_printoptions(suppress=True)    
    xyz = np.loadtxt('cylinder11.xyz')
    #print xyz
    print "Initial Parameters: "
    p = np.array([-13.79,-8.45,0,0,0.3])
    print p
    print " "

    print "Performing Cylinder Fitting ... "
    est_p =  cylinderFitting(xyz,p,0.00001)
    print "Fitting Done!"
    print " "


    print "Estimated Parameters: "
    print est_p

答案 2 :(得分:1)

Cylinder Image

我遇到过类似的情况,通过几个点拟合圆柱体。我们使用间隙传感器在几个点测量了两个圆柱体之间的间隙,我必须想象与圆柱体相比间隙是如何变化的。

我使用了 ax.plot_surface(x, y, z, alpha=0.5) 其中 x , y, z 是所有点的 3D 位置的 numpy 数组。看看下面的图片。

代码片段,

# Extract X,Y,Z values from the sensor data 
for i in range(num_of_sensors):
  ax.scatter(x[:,i], y[:,i], z[:,i], color = "k", marker=".", s=5, cmap='hot')
  ax.text(x[0,i]+ 10, y[0,i] + 10, z[0,i]+100, '%s' % (idx[i]), size=5, zorder=1, color='b') 

# plot the surface
ax.plot_surface(x, y, z, alpha=0.5)