简体   繁体   English

具有已知对应关系的两个点云的刚性配准

[英]Rigid registration of two point clouds with known correspondence

Imagine I have two (python) lists (with a limited) amount of 3D points.想象一下,我有两个(python)列表(数量有限) 3D 点。 How do I find a rigid transformation to match the points as closely as possible.我如何找到一个刚性转换来尽可能地匹配这些点。 For each point of each list it is known to which other point that point corresponds.对于每个列表的每个点,都知道该点对应于哪个其他点。 Is there an algorithm/library for this?有为此的算法/库吗?

I found the Iterative closest point algorithm, but this assumes there is no correspondence known and it seems to be made for large point clouds.我找到了迭代最近点算法,但这假设没有已知的对应关系,它似乎是为大型点云制作的。 I'm talking about limited sets of 3 to 8 points.我说的是有限的 3 到 8 点。

Possible point sets (correspondence according to index in the list)可能的点集(根据列表中的索引对应)

a = [[0,0,0], [1,0,0],[0,1,0]]
b = [[0,0,0.5], [1,0,1],[0,0,2]]

Turns out there is actually an analytical solution.事实证明,实际上有一个分析解决方案。 It is described in the paper of Arun et al., 1987, Least square fitting of two 3D point sets它在Arun 等人的论文中有所描述,1987,两个 3D 点集的最小二乘拟合

I wrote a testscript to test their algorithm and it seems to work fine (if you want to have a solution that minimizes the sum of the square errors, if you have an outlier this might not be ideal):我写了一个测试脚本来测试他们的算法,它似乎工作正常(如果你想要一个最小化平方误差总和的解决方案,如果你有一个异常值,这可能不是理想的):

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...")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM