一旦获得一些 3-D 点坐标,我应该使用什么算法来拟合最佳圆柱并获得中心轴的方向向量和半径?
圆柱体上不同横截面的点 我之前的想法是把一个圆柱体分成几层,随着层数的增加,点组成的图形越来越接近圆柱体,但这样我就无法得到圆柱体的精确半径。 (通过每一层拟合圆心得到中心轴)
这是一个 MCVE,用于回归由
p0
和 p1
(向量)和半径 R
(标量)定义的轴。
首先我们创建一些虚拟数据集:
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
from scipy.spatial.transform import Rotation
def cylinder(n=60, m=20, r=2, h=5):
t = np.linspace(0, m * 2 * np.pi, m * n)
z = np.linspace(0, h, m * n)
x = r * np.cos(t)
y = r * np.sin(t)
return np.stack([x, y, z]).T
X = cylinder()
rot = Rotation.from_rotvec(np.array([-1, 2, 0.5]))
x0 = np.array([1., 2., 0.])
X = rot.apply(X)
X = X + x0
这创建了一个通用用例,包括原点转移。
现在只需将几何方程(参见方程 10)写为残差并通过最小二乘法将其最小化即可。
def residuals(p, xyz):
return np.power(np.linalg.norm(np.cross((xyz - p[0:3]), (xyz - p[3:6])), axis=1) / np.linalg.norm((p[3:6] - p[0:3])), 2) - p[6] ** 2
p, res = optimize.leastsq(residuals, x0=[0., 0., 0., 1., 1., 1., 0.], args=(X,), full_output=False)
在这种情况下返回:
# array([ -1.8283916 , -1.65918186, 3.29901757, # p0
# 20.31455462, 26.98786514, -22.52837088, # p1
# 2. ]) # R
从图形上看,它导致: