我正在尝试使用 SVD 将带有 Python 的单个 STL 文件转换为基本模型(主 STL)。我有 8 个可用点(每个角一个)(数组:
[[x-axys], [y-axis], [z-axis]]
。当我使用 SVD 变换点并绘制点的变换(见图 1)时,它工作正常。
如果我将其应用于 STL(红色:主要 STL,蓝色:要转换的 STL,绿色:已转换的 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
网格比较:
-- 法线:
[[-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]]
-- 法线:
[[-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]]
-- 法线:
[[ 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的shpae上。我看不出其他 STL 与其他形状正常的 STL 有什么不同。