icp.py
Go to the documentation of this file.
1 import numpy as np
2 from sklearn.neighbors import NearestNeighbors
3 
5  '''
6  Calculates the least-squares best-fit transform that maps corresponding points A to B in m spatial dimensions
7  Input:
8  A: Nxm numpy array of corresponding points
9  B: Nxm numpy array of corresponding points
10  Returns:
11  T: (m+1)x(m+1) homogeneous transformation matrix that maps A on to B
12  R: mxm rotation matrix
13  t: mx1 translation vector
14  '''
15 
16  assert A.shape == B.shape
17 
18  # get number of dimensions
19  m = A.shape[1]
20 
21  # translate points to their centroids
22  centroid_A = np.mean(A, axis=0)
23  centroid_B = np.mean(B, axis=0)
24  AA = A - centroid_A
25  BB = B - centroid_B
26 
27  # rotation matrix
28  H = np.dot(AA.T, BB)
29  U, S, Vt = np.linalg.svd(H)
30  R = np.dot(Vt.T, U.T)
31 
32  # special reflection case
33  if np.linalg.det(R) < 0:
34  Vt[m-1,:] *= -1
35  R = np.dot(Vt.T, U.T)
36 
37  # translation
38  t = centroid_B.T - np.dot(R,centroid_A.T)
39 
40  # homogeneous transformation
41  T = np.identity(m+1)
42  T[:m, :m] = R
43  T[:m, m] = t
44 
45  return T, R, t
46 
47 
48 def nearest_neighbor(src, dst):
49  '''
50  Find the nearest (Euclidean) neighbor in dst for each point in src
51  Input:
52  src: Nxm array of points
53  dst: Nxm array of points
54  Output:
55  distances: Euclidean distances of the nearest neighbor
56  indices: dst indices of the nearest neighbor
57  '''
58 
59  assert src.shape == dst.shape
60 
61  neigh = NearestNeighbors(n_neighbors=1)
62  neigh.fit(dst)
63  distances, indices = neigh.kneighbors(src, return_distance=True)
64  return distances.ravel(), indices.ravel()
65 
66 
67 def icp(A, B, init_pose=None, max_iterations=20, tolerance=0.001):
68  '''
69  The Iterative Closest Point method: finds best-fit transform that maps points A on to points B
70  Input:
71  A: Nxm numpy array of source mD points
72  B: Nxm numpy array of destination mD point
73  init_pose: (m+1)x(m+1) homogeneous transformation
74  max_iterations: exit algorithm after max_iterations
75  tolerance: convergence criteria
76  Output:
77  T: final homogeneous transformation that maps A on to B
78  distances: Euclidean distances (errors) of the nearest neighbor
79  i: number of iterations to converge
80  '''
81 
82  assert A.shape == B.shape
83 
84  # get number of dimensions
85  m = A.shape[1]
86 
87  # make points homogeneous, copy them to maintain the originals
88  src = np.ones((m+1,A.shape[0]))
89  dst = np.ones((m+1,B.shape[0]))
90  src[:m,:] = np.copy(A.T)
91  dst[:m,:] = np.copy(B.T)
92 
93  # apply the initial pose estimation
94  if init_pose is not None:
95  src = np.dot(init_pose, src)
96 
97  prev_error = 0
98 
99  for i in range(max_iterations):
100  # find the nearest neighbors between the current source and destination points
101  distances, indices = nearest_neighbor(src[:m,:].T, dst[:m,:].T)
102 
103  # compute the transformation between the current source and nearest destination points
104  T,_,_ = best_fit_transform(src[:m,:].T, dst[:m,indices].T)
105 
106  # update the current source
107  src = np.dot(T, src)
108 
109  # check error
110  mean_error = np.mean(distances)
111  if np.abs(prev_error - mean_error) < tolerance:
112  break
113  prev_error = mean_error
114 
115  # calculate final transformation
116  T,_,_ = best_fit_transform(A, src[:m,:].T)
117 
118  return T, distances, i
def nearest_neighbor(src, dst)
Definition: icp.py:48
def best_fit_transform(A, B)
Definition: icp.py:4
def icp(A, B, init_pose=None, max_iterations=20, tolerance=0.001)
Definition: icp.py:67


caster_app
Author(s): Ye Tian
autogenerated on Wed Dec 18 2019 03:34:44