import numpy as np
##Based on Arun et al., 1987
#Writing points with rows as the coordinates
p1_t = np.array([[0,0,0], [1,0,0],[0,1,0]])
p2_t = np.array([[0,0,1], [1,0,1],[0,0,2]]) #Approx transformation is 90 degree rot over x-axis and +1 in Z axis
#Take transpose as columns should be the points
p1 = p1_t.transpose()
p2 = p2_t.transpose()
#Calculate centroids
p1_c = np.mean(p1, axis = 1).reshape((-1,1)) #If you don't put reshape then the outcome is 1D with no rows/colums and is interpeted as rowvector in next minus operation, while it should be a column vector
p2_c = np.mean(p2, axis = 1).reshape((-1,1))
#Subtract centroids
q1 = p1-p1_c
q2 = p2-p2_c
#Calculate covariance matrix
H=np.matmul(q1,q2.transpose())
#Calculate singular value decomposition (SVD)
U, X, V_t = np.linalg.svd(H) #the SVD of linalg gives you Vt
#Calculate rotation matrix
R = np.matmul(V_t.transpose(),U.transpose())
assert np.allclose(np.linalg.det(R), 1.0), "Rotation matrix of N-point registration not 1, see paper Arun et al."
#Calculate translation matrix
T = p2_c - np.matmul(R,p1_c)
#Check result
result = T + np.matmul(R,p1)
if np.allclose(result,p2):
print("transformation is correct!")
else:
print("transformation is wrong...")
事实上,有一个解析解。这在Arun et al., 1987, Least square fitting of two 3D point sets的论文中有描述
我编写了一个测试脚本来测试他们的算法,它似乎工作得很好(如果您想要一个最小化平方误差总和的解决方案,如果您有一个异常值,这可能并不理想):
相关问题 更多 >
编程相关推荐