matlab从3D数据点拟合椭圆
我在给定平面(3D)中有一组3D(X,Y,Z)数据点。我希望能在这些问题上找到一个答案matlab从3D数据点拟合椭圆,matlab,3d,transform,points,ellipse,Matlab,3d,Transform,Points,Ellipse,我在给定平面(3D)中有一组3D(X,Y,Z)数据点。我希望能在这些问题上找到一个答案 我找到了很多关于如何在二维点上拟合椭圆的答案。因此,更准确地说,我的问题是如何转换3D数据(x,y,z)点->2D数据(x,y)?在标准投影中,椭圆(圆被a=b=r省略)将投影在椭圆或直线上。所以我将使用这个行为,这样你想要的3D椭圆将由你可以计算的不同椭圆来定义 我不会显示代码,但方法可以是: 在M x 3矩阵中定义数据,其中M是点数,形式为[x,y,z] 以z=f(x,y) 在数据矩阵中搜索与[x,y,f
我找到了很多关于如何在二维点上拟合椭圆的答案。因此,更准确地说,我的问题是如何转换3D数据(x,y,z)点->2D数据(x,y)?在标准投影中,椭圆(圆被a=b=r省略)将投影在椭圆或直线上。所以我将使用这个行为,这样你想要的3D椭圆将由你可以计算的不同椭圆来定义 我不会显示代码,但方法可以是:
[x,y,z]
z=f(x,y)
[x,y,f(x,y)]
向量相等或相似的行[x,y]
对的答案(忽略z
部分可以被视为x-y平面的投影)[x\u fit,y\u fit]
[x\u-fit,y\u-fit,f(x\u-fit,y\u-fit)]
下面是我针对这个问题的Python代码。 此链接帮助我完成了我的实施:
将numpy导入为np
从skimage.measure导入EllipseModel
#-------------------------------------------------------------------------------
#罗德里格斯旋转
#-基于起始和结束向量旋转给定点
#-轴k和旋转角度θ,由矢量n0,n1给出
#P_rot=P*cos(θ)+(kxp)*sin(θ)+k**(1-cos(θ))
#-------------------------------------------------------------------------------
国防部罗德里格斯大学(P、n0、n1):
#如果P仅为一维数组(单点坐标),则将其固定为矩阵
如果P.ndim==1:
P=P[np.newaxis,:]
#得到旋转向量k和角度θ
n0=n0/np.线性范数(n0)
n1=n1/np.线性范数(n1)
k=np.交叉(n0,n1)
k=k/np.linalg.norm(k)
θ=np.arccos(np.dot(n0,n1))
#计算旋转点
P_rot=np.zero((len(P),3))
对于范围内的i(len(P)):
P_rot[i]=P[i]*np.cos(θ)+np.cross(k,P[i])*np.sin(θ)+k*np.dot(k,P[i])*(1-np.cos(θ))
返回P_rot
def拟合椭圆(P):
P_平均值=P平均值(轴=0)
P_居中=P-P_平均值
#均值中心数据的奇异值分解拟合平面
U、 s,V=np.linalg.svd(P_居中,全矩阵=False)
#拟合平面的法向量由V中的第三列给出
#注意linalg.svd返回V^T,因此我们需要从V^T中选择第三行
#三维平面上的法线
正常=V[2,:]
#将点投影到二维平面中的坐标X-Y
P_xy=rodrigues_rot(P_居中,法线,[0,0,1])
#使用skimage EllipseModel将椭圆拟合到一组二维点
ell=EllipseModel()
估计值(P_xy[:,:2])
#在拟合的Elipse上生成n个2D点
n=100
xy=ell.predict_xy(np.linspace(0,2*np.pi,n))
#将二维生成的点转换为三维空间
点数=[]
对于范围内的i(len(xy)):
points.append([xy[i,0],xy[i,1],0])
点=np.数组(点)
椭圆点3d=罗德里格斯旋转(点[0,0,1],法线)+P平均值
返回椭圆\u点\u 3d
要测试代码,可以运行此命令并检查输出结果:
将numpy导入为np
绘声绘色地导入
导入plotly.graph_objs作为go
P=np.数组([[52.21818786,7.86337722,57.83456389],
[30.55316226, 32.36591494, 14.35753359],
[59.77387002, 14.29531811, 53.6462596 ],
[42.85677086, 32.67223954, -5.95323959],
[44.46449002, 1.43144171, 54.0253186 ],
[27.6464027 , 19.80836045, -1.5754063 ],
[63.48591069, 6.88329618, 57.55556516],
[44.19484831, 28.32302575, 6.01730042],
[46.09443886, 2.71782362, 57.98617489],
[22.55050927, 30.28315605, 42.5642505 ],
[20.16244533, 18.55944689, 34.06871328],
[69.4591254 , 33.62256919, 40.91996533],
[24.42183439, 5.95578526, 35.80224431],
[70.09161495, 24.03152634, 45.77915268],
[28.68122335, -6.64788396, 37.53577535],
[59.84340586, 23.47833222, 60.01530894],
[23.98376474, 14.23114661, 32.43676647],
[73.28044481, 29.29426891, 39.28801852],
[28.48679585, -5.33220296, 36.04206575],
[54.66351746, 15.7561502 , 51.20981383],
[38.33444206, -0.08003422, 41.2639318 ],
[57.27722964, 39.91662965, 20.63778872],
[43.24856256, 7.79042068, 50.95451935],
[64.68788661, 31.78841088, 27.19632274],
[41.67377653, -0.18313508, 49.56081237],
[60.577958 , 35.8138609 , 28.9005053 ]])
椭圆点=拟合椭圆(P)
行=[]
追加(go.Scatter3d(x=P[:,0],y=P[:,1]\
z=P[:,2],name='P'\
,不透明度=1,))
lines.append(go.Scatter3d(x=椭圆点[:,0],y=椭圆点[:,1]\
z=椭圆_点[:,2],name='ellipse_点'\
,不透明度=1,))
plotly.offline.iplot(行)
输出结果:
您可以在colab中自己尝试代码:将平面拟合到这些点。那么你就有了一个平面上的坐标。也许还有更多关于这个问题的信息: