pythontransformationsvdrigid-bodieshomogenous-transformation

The same SVD for points with different precisions got completely different transformation matrix


I am trying to do a rigid-body transformation in Python to register a source point set to a target point set by only allowing the source point set to rotate around one point shared by both the source and the target, i.e., the 2nd point. I basically translate the source and target by subtracting that user-defined center of rotation rather than the centroids. I then applied np.linalg.svd for getting a rotation_matrix.

However, when I tried the source and target points with different precisions, they got completely different results.

The first set of source and targets are:

source_points = np.array([[29.930, 65.059, -692.872], [20.588, 38.868, -675.454], [18.266, 57.316, -682.061]])
target_points = np.array([[27.474, 61.970, -689.958], [20.588, 38.868, -675.454], [15.340, 60.875, -681.762]])  # Your target points

The script is https://github.com/chz31/surgical_plate_registration/blob/main/proper_svd.py

I got a neat rotation transformation matrix that yielded good alignment as

array([[ 0.99795083, -0.05814411,  0.02670959],
       [ 0.05909811,  0.99758699, -0.03643628],
       [-0.02452659,  0.0379401 ,  0.99897898]])

The second set of source and targets have higher precisions but are essentially the same points:

source_points = np.array([[29.92973456, 65.05863408, -692.87207321], [20.58772087,38.86774826, -675.45440674],[18.2662661, 57.31554544, -682.06144071]])
target_points = np.array([[27.47413063, 61.97033691, -689.95812988], [20.58772087, 38.86774826, -675.45440674], [15.33987617, 60.87537766, -681.76153564]])

The script is: https://github.com/chz31/surgical_plate_registration/blob/main/svd_deform_error.py

I then got a completely different transformation:

array([[ 0.49127036, -0.40722086, -0.76995104],
       [-0.2900711 ,  0.75702601, -0.58546595],
       [-0.82128691, -0.51096261, -0.25378144]])

So for the second set, the homogeneous transformation matrix I reconstructed essentially deformed the source. For rigid-body registration, it should not deform the source.

#translation
t = rotation_center.T - np.dot(rotation_matrix, rotation_center.T)

#homogeneous transform matrix
T = np.identity(4)
T[:3, :3] = rotation_matrix
T[:3, 3] = t

I assumed that the two scripts should yield very similar results since they are essentially the same points only differing by precisions. In particular, a rigid transformation should not deform the source. Can anyone give some suggestions of what I did wrong or why this happened?


Solution

  • All right, I forgot the case that the signs of the rotation matrix might be reflected.

    Adding this piece solved the problem:
    # special reflection case 
    m = translated_source_points.shape[1] 
    if np.linalg.det(rotation_matrix) < 0:
        Vt[m - 1, :] *= -1 rotation_matrix = np.dot(Vt.T, U.T)