MCPcopy Create free account
hub / github.com/MotrixLab/AiOS / compute_similarity_transform

Function compute_similarity_transform

detrsmpl/core/evaluation/mesh_eval.py:9–77  ·  view source on GitHub ↗

Computes a similarity transform (sR, t) that takes a set of 3D points source_points (N x 3) closest to a set of 3D points target_points, where R is an 3x3 rotation matrix, t 3x1 translation, s scale. And return the transformed 3D points source_points_hat (N x 3). i.e. solves the ort

(source_points,
                                 target_points,
                                 return_tform=False)

Source from the content-addressed store, hash-verified

7
8
9def compute_similarity_transform(source_points,
10 target_points,
11 return_tform=False):
12 """Computes a similarity transform (sR, t) that takes a set of 3D points
13 source_points (N x 3) closest to a set of 3D points target_points, where R
14 is an 3x3 rotation matrix, t 3x1 translation, s scale.
15
16 And return the
17 transformed 3D points source_points_hat (N x 3). i.e. solves the orthogonal
18 Procrutes problem.
19 Notes:
20 Points number: N
21 Args:
22 source_points (np.ndarray([N, 3])): Source point set.
23 target_points (np.ndarray([N, 3])): Target point set.
24 return_tform (bool) : Whether return transform
25 Returns:
26 source_points_hat (np.ndarray([N, 3])): Transformed source point set.
27 transform (dict): Returns if return_tform is True.
28 Returns rotation: r, 'scale': s, 'translation':t.
29 """
30
31 assert target_points.shape[0] == source_points.shape[0]
32 assert target_points.shape[1] == 3 and source_points.shape[1] == 3
33
34 source_points = source_points.T
35 target_points = target_points.T
36
37 # 1. Remove mean.
38 mu1 = source_points.mean(axis=1, keepdims=True)
39 mu2 = target_points.mean(axis=1, keepdims=True)
40 X1 = source_points - mu1
41 X2 = target_points - mu2
42
43 # 2. Compute variance of X1 used for scale.
44 var1 = np.sum(X1**2)
45
46 # 3. The outer product of X1 and X2.
47 K = X1.dot(X2.T)
48
49 # 4. Solution that Maximizes trace(R'K) is R=U*V', where U, V are
50 # singular vectors of K.
51 U, _, Vh = np.linalg.svd(K)
52 V = Vh.T
53 # Construct Z that fixes the orientation of R to get det(R)=1.
54 Z = np.eye(U.shape[0])
55 Z[-1, -1] *= np.sign(np.linalg.det(U.dot(V.T)))
56 # Construct R.
57 R = V.dot(Z.dot(U.T))
58
59 # 5. Recover scale.
60 scale = np.trace(R.dot(K)) / var1
61
62 # 6. Recover translation.
63 t = mu2 - scale * (R.dot(mu1))
64
65 # 7. Transform the source points:
66 source_points_hat = scale * R.dot(source_points) + t

Callers 5

keypoint_mpjpeFunction · 0.85
vertice_pveFunction · 0.85
keypoint_3d_pckFunction · 0.85
keypoint_3d_aucFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected