问题描述
根据转换完成前和转换完成后的点列表,我们如何推导出原点旋转和轴移动的角度。
示例:
改造前 - [(-3173.24,1503.76),(-3173.24,1599.98),(-2921.24,1941.7),(-2777.24,(-2969.24,1905.7),(-3017.24,(-3065.24,(-3161.24,2013.6),(-3179.24,2049.6),(-2759.24,1803.81),(-3113.24,1839.81),(-2789.24,1623.98),1527.76),(-2760.86,1737.92)]
改造后 - [(52.12,146.39),(52.12,242.61),(592.12,584.33),(448.12,(256.12,548.33),(640.12,(688.12,(160.12,(64.12,656.22),(46.12,692.22),(466.12,(208.12,446.44),(112.12,482.44),(436.12,266.61),170.39),(464.5,380.54)]
我们如何生成这些点之间的相关性,以便给定一个较旧的点(x,y),我们可以找到派生点(x',y')
产地详情未知。我们使用的是具有 x 和 y 轴的笛卡尔坐标系。
解决方法
您正在寻找一个 2x2 的旋转矩阵 M 和一个 2x1 的平移向量 T,例如:
(x',y') = M.(x,y) + B
对于您的所有积分。
假设 M 是以下矩阵:
( a b )
( c d )
T 以下向量:
(Tx,Ty)
转换前 P = (Px,Py)
和转换后 P' = (P'x,P'y)
的每个点都为您提供 2 个方程:
P'x = a.Px + b.Py + Tx
P'y = c.Px + d.Py + Ty
-
其中 a,b,c,d,Tx,Ty 是未知元素。
-
收集所有点给出的所有方程,您可以使用优化算法(如 Levenberg Marquart 或 Gradient Descent)找到那些未知元素...
-
请注意,您有 6 个未知数,因此您至少需要 3 个点,这将为您提供 6 个方程来解决此问题。 (如果你喜欢笔和纸,你可以手动解决这个问题:P)
一旦你解决了方程组,你就可以得到旋转角 theta,因为矩阵 M 是由以下定义的旋转矩阵:
( cos(theta) -sin(theta) )
( sin(theta) cos(theta) )
- 有关旋转矩阵的更多详细信息以及角度 theta 与矩阵系数之间的关系,请访问:https://en.wikipedia.org/wiki/Rotation_matrix
注意1:请注意,在一般情况下,“Rotation THEN Translation”并不等同于“Translation THEN Rotation”,因为如果您之前旋转,您将不会在相同的方向;-)
- 我上面提到的方程对应于“旋转然后平移”。
注意 2:我的回答假设变换实际上只是旋转和平移,但如果您不是 100% 确定是这种情况,则变换可以是仿射变换 (P' = MP + T 与 M 不一定是旋转矩阵)甚至非线性变换(在这种情况下,它不能用矩阵表示,我会使用 2D 模型,如 2D 多边形或类似的东西:>
f(x,y) = a.x² + b.y² + c.xy + dx + ey + f 并尝试使用数值方法找到不那么直的 a,e,f)前进。
,新编辑。
import numpy as np
import matplotlib.pyplot as plt
x = np.array([(-3173.24,1503.76),(-3173.24,1599.98),(-2921.24,1941.7),(-2777.24,(-2969.24,1905.7),(-3017.24,(-3065.24,(-3161.24,2013.6),(-3179.24,2049.6),(-2759.24,1803.81),(-3113.24,1839.81),(-2789.24,1623.98),1527.76),(-2760.86,1737.92)])
y = np.array([(52.12,146.39),(52.12,242.61),(592.12,584.33),(448.12,(256.12,548.33),(640.12,(688.12,(160.12,(64.12,656.22),(46.12,692.22),(466.12,(208.12,446.44),(112.12,482.44),(436.12,266.61),170.39),(464.5,380.54)])
def centroid(s):
# Centroid of a set s
c = np.sum(s,axis=0) / len(s)
return c[np.newaxis,:]
def rotation_translation(x,y):
# Centroids of each set
xG = centroid(x)
yG = centroid(y)
# Shape of each set
Mx = (x-xG).T.dot(x-xG)
My = (y-yG).T.dot(y-yG)
# Eigendecomposition
ex,Ux = np.linalg.eig(Mx)
ey,Uy = np.linalg.eig(My)
# rotation matrix
U = Uy.dot(Ux.T)
# translation vector
t = yG - xG.dot(U.T)
return U,t,xG,yG
def matrix_vector(x,y):
# Centroids of each set
xG = centroid(x)
yG = centroid(y)
# Shape of each set
Mx = (x-xG).T.dot(x-xG)
My = (y-yG).T.dot(y-yG)
# Eigendecomposition: eigeinvalues,rotation matrices
ex,Uy = np.linalg.eig(My)
ex = np.sqrt(ex)
ey = np.sqrt(ey)
ex = ex[:,np.newaxis]
ey = ey[:,np.newaxis]
# linear matrix,rotation-scaling-rotation
U = (ey/ex) * Ux.T
U = Uy.dot(U)
# trasnlation vector
t = yG - xG.dot(U.T)
return U,yG
def Transform(v,mtrx_vctr):
return v.dot(mtrx_vctr[0].T) + mtrx_vctr[1]
U,yG = rotation_translation(x,y)
z_rot = Transform(x,(U,t))
U,yG = matrix_vector(x,y)
z_aff = Transform(x,t))
plt.plot(x[:,0],x[:,1],'go')
plt.plot(y[:,y[:,'bo')
plt.plot(z_rot[:,z_rot[:,'ro')
plt.plot(z_aff[:,z_aff[:,'yo')
plt.show()
初始答案。
这两个三角形不全等,即没有平移和旋转可以将 x 转换为 y。存在仿射变换。
import numpy as np
import matplotlib.pyplot as plt
def Affine_map(before,after):
b0 = before - before[0,:][np.newaxis,:]
b0 = b0[1:3,:]
a0 = after - after[0,:]
a0 = a0[1:3,:]
A = np.linalg.inv(b0).dot(a0)
t = after[0,:] - before[0,:].dot(A)
return A,t
x = np.array([[-4648,2144],[-4311,2155],[-3589,357]])
y = np.array([[591,157],[1073,168],[1596,-223]])
A,t = Affine_map(x,y)
# map is applied as y = x.dot(A) + t
print('')
print('Matrix of affine triansformation:')
print(A)
print('')
print('Vector of translation:')
print(t)
print('')
print('Check that y = Ax + t ')
print( y - x.dot(A) - t)
print('')
plt.plot(x[:,'ro')
plt.plot(y[:,'bo')
plt.show()