使用 SVD 转换 3D 对象(STL 文件)时的奇怪行为

问题描述 投票:0回答:0

我正在尝试使用 SVD 将带有 Python 的单个 STL 文件转换为基本模型(主 STL)。我有 8 个可用点(每个角一个)(数组:

[[x-axys], [y-axis], [z-axis]]
。当我使用 SVD 变换点并绘制点的变换(见图 1)时,它工作正常。 Plottet Transformation of Points

如果我将其应用于 STL(红色:主要 STL,蓝色:要转换的 STL,绿色:已转换的 STL),那么它看起来不太好。 Transformed STL

主要STL要点:

[[  -68.48762512   -59.97864914   -60.66869354   -68.05758667
    -54.52422714   -46.40756989   -47.04969406   -54.54148102]
 [ -197.0960083   -231.55140686  -231.37744141  -196.91946411
   -193.69078064  -228.49227905  -228.53533936  -193.79853821]
 [-1263.79602051 -1263.46337891 -1315.14160156 -1315.29614258
  -1263.61401367 -1264.01965332 -1315.79614258 -1315.11779785]]

STL需要改造的地方:

[[   -2.59021759    24.76242638    33.26348877     6.55995178
    -11.57139301    15.20143509    24.31353569    -2.37344408]
 [ -187.66265869  -166.51126099  -156.92207336  -178.09362793
   -176.34576416  -155.03430176  -145.77209473  -166.58743286]
 [-1717.6965332  -1709.48144531 -1759.2890625  -1767.99304199
  -1717.22412109 -1708.5213623  -1759.08874512 -1767.58447266]]

旋转矩阵(ret_R):

[[-0.44074192 -0.88135646 -0.17016858]
 [ 0.8925356  -0.41011557 -0.18757777]
 [ 0.0955341  -0.2345549   0.96739714]]

平移矩阵(ret_t):

[[-421.26808458]
 [-444.43884049]
 [-535.26757996]]

如图1所示,使用SVD对Points进行变换是正确的。

我用来在 STL 上应用转换的代码(ret_R 和 ret_t 你能在上面看到):

    # Calculate rigid transformation from A to B
    ret_R, ret_t = rigid_transform_3D(points_A, mainPoints_B)
        
    # Create rotation matrix from ret_R
    R = np.array([[ret_R[0][0], ret_R[0][1], ret_R[0][2]],
                  [ret_R[1][0], ret_R[1][1], ret_R[1][2]],
                  [ret_R[2][0], ret_R[2][1] ,ret_R[2][2]]])
    
    # Create translation vector from ret_t
    t = np.array([ret_t[0][0], ret_t[1][0] ,ret_t[2][0]])
    
    # Create transformation matrix from R and t
    transform = np.hstack((R, t.reshape(3,1)))
    transform = np.vstack((transform, [0, 0, 0, 1]))
    
    # Apply transformation matrix to original mesh
    orgMesh.transform(transform)
    
    # Find the center points of each mesh
    referencCenter = np.mean(referenceMesh.points, axis=0)[:3]
    orgCenter = np.mean(orgMesh.points, axis=0)[:3]

    # Find the translation vector that maps the second center to the first one
    translation_vector = referencCenter - orgCenter

    # Apply the translation to the second mesh
    orgMesh.translate(translation_vector)
       
    # Save transformed STL file for specific island
    orgMesh.save(f'{stlSVDPath}{volumeName}/{volumeName}_{island}.stl')

功能

rigid_transform_3D

def rigid_transform_3D(A, B):
    # Check that A and B have the same shape
    assert A.shape == B.shape

    # Check that A is a 3xN matrix
    num_rows, num_cols = A.shape
    if num_rows != 3:
        raise Exception(f"matrix A is not 3xN, it is {num_rows}x{num_cols}")

    # Check that B is a 3xN matrix
    num_rows, num_cols = B.shape
    if num_rows != 3:
        raise Exception(f"matrix B is not 3xN, it is {num_rows}x{num_cols}")

    # Find the center of each column in A and B
    cA = np.mean(A, axis=1)
    cB = np.mean(B, axis=1)

    # Ensure centroids are 3x1 column vectors
    cA = cA.reshape(-1, 1)
    cB = cB.reshape(-1, 1)

    # Subtract the center from A and B
    Am = A - cA
    Bm = B - cB

    # Compute H matrix
    H = Am @ np.transpose(Bm)

    # Find rotation using singular value decomposition
    U, S, Vt = np.linalg.svd(H)
    R = Vt.T @ U.T

    # Check for reflection case and correct for it if necessary
    if np.linalg.det(R) < 0:
        print("det(R) < R, reflection detected!, correcting for it ...")
        Vt[2,:] *= -1
        R = Vt.T @ U.T

    # Compute translation vector
    t = -R @ cA + cB

    return R, t

网格比较:

  • 主要STL(红色):

-- 法线:

[[-9.6677500e-04 -2.6232842e-04 -2.3740600e-04]
 [-5.5828094e-03 -1.0147095e-03  6.6956913e-05]
 [-1.4789581e-02 -4.0130615e-03  1.4778937e-04]
 ...
 [ 2.1938324e-02  9.8915100e-03  4.4992968e-04]
 [ 1.0566711e-02  4.6043396e-03  2.2347202e-04]
 [ 5.1904037e-03  2.2616668e-03  1.9461091e-04]]

-- 向量:

[[ 75.52459   36.400085  35.49998 ]
 [ 75.52459   36.400085  35.49998 ]
 [ 75.532616  36.370506  35.49998 ]
 ...
 [107.24851   90.679794  25.999987]
 [107.25772   90.65866   25.999987]
 [107.24851   90.65866   26.245588]]
[[ 75.532616  36.400085  35.467297]
 [ 75.532616  36.38892   35.99998 ]
 [ 75.532616  36.38892   35.99998 ]
 ...
 [107.268295  90.65866   25.499987]
 [107.268295  90.65866   25.499987]
 [107.25772   90.65866   25.999987]]
[[ 75.532616  36.370506  35.49998 ]
 [ 75.53059   36.400085  35.99998 ]
 [ 75.52459   36.400085  35.49998 ]
 ...
 [107.24851   90.70254   25.499987]
 [107.24851   90.679794  25.999987]
 [107.24851   90.679794  25.999987]]
  • 待转换STL(蓝色):

-- 法线:

[[-2.1351801e-04 -1.8506320e-04 -3.1405580e-06]
 [-1.2950897e-03 -1.1234283e-03 -1.5463374e-06]
 [-9.5176697e-04 -8.2492828e-04 -1.1328666e-06]
 ...
 [ 4.4162076e-02  3.4066408e-03  3.3909243e-03]
 [ 3.6591128e-02  1.1264640e-02 -2.4043699e-03]
 [ 3.2203790e-02  9.9139912e-03  2.4043699e-03]]

-- 向量:

[[22.05981  36.41117  16.499994]
 [22.05981  36.41117  16.499994]
 [22.06146  36.409267 16.499994]
 ...
 [65.5358   37.19211  39.999985]
 [65.50106  37.289726 39.58594 ]
 [65.50106  37.289726 40.364384]]
[[22.06146  36.41117  16.387825]
 [22.06146  36.40858  16.999994]
 [22.06146  36.40858  16.999994]
 ...
 [65.52827  37.289726 39.999985]
 [65.50106  37.3781   39.999985]
 [65.52827  37.289726 39.999985]]
[[22.06146  36.409267 16.499994]
 [22.059214 36.41117  16.999994]
 [22.05981  36.41117  16.499994]
 ...
 [65.50106  37.19211  40.45238 ]
 [65.52827  37.289726 39.999985]
 [65.50106  37.3781   39.999985]]
  • 转换后的STL(绿色):

-- 法线:

[[ 2.5854260e-04 -1.1374429e-04  2.0112842e-05]
 [ 1.5655681e-03 -7.0197880e-04  1.3771188e-04]
 [ 1.1496954e-03 -5.0927885e-04  1.0230392e-04]
 ...
 [-2.3056319e-02  3.7390001e-02  6.7013074e-03]
 [-2.5641572e-02  2.8484236e-02 -1.4713183e-03]
 [-2.3335047e-02  2.4221176e-02  3.0756257e-03]]

-- 向量:

[[132.65839   59.98535   29.969849]
 [132.65839   59.98535   29.969849]
 [132.65933   59.98761   29.970459]
 ...
 [108.80945   94.06088   56.67392 ]
 [108.80917   94.067505  56.24716 ]
 [108.6767    93.92148   57.000214]]
[[132.67673   60.007874  29.86145 ]
 [132.57486   59.894104  30.454285]
 [132.57486   59.894104  30.454285]
 ...
 [108.726715  94.0141    56.6503  ]
 [108.66083   93.95358   56.626984]
 [108.726715  94.0141    56.6503  ]]
[[132.65933   59.98761   29.970459]
 [132.57355   59.89102   30.453491]
 [132.65839   59.98535   29.969849]
 ...
 [108.74777   93.94501   57.108246]
 [108.726715  94.0141    56.6503  ]
 [108.66083   93.95358   56.626984]]

我试过的

  • 查看STL文件
  • 使用相同的代码尝试使用其他形状和其他点 --> 按预期工作

问题只出现在矩形STL的shpae上。我看不出其他 STL 与其他形状正常的 STL 有什么不同。

python stl transformation svd
© www.soinside.com 2019 - 2024. All rights reserved.