我如何在数学上描述 x/y 轴上 4 个 2D 点到 4 个 2D 点的转换?

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

(请参阅此问题的底部以获取更新)

我绝不是数学专家,所以请原谅术语等方面的错误

在我的应用程序 (Python) 中,总是有一个稍微独特的可能输入坐标空间,可以用 4 边多边形来描述,这里显示了一个示例(预先调整为将质心直接放在原点上):

我想弄清楚如何描述将该空间转换为该受限空间的转换(或系列转换):

如果我能找到那个变换,那么稍后,当我在程序的使用过程中从用户那里得到一个单独的输入坐标时,我将应用相同的变换来给我一个单独的坐标值,该值将被约束到变换最后一张图片中描绘的坐标空间。

为了让最后一部分更清楚,这里是我所描述的图形,不按比例:

我不太精通线性代数(也许线性代数甚至都不是可行的方法?),所以也许我遗漏了一些明显的东西。我的计划如下:

设T为我要找的变换矩阵

设A为原始坐标矩阵

设 A_T 为变换后的坐标矩阵

A_T = T * A

因此,我认为我会通过说来隔离T:

T = A_T * 逆(A)

问题是,A 不是正方形,(因为它包含 4 个 2D 点),所以我无法计算它的逆。

基本上,我想描述从 (ax, ay) (bx, by) (cx, cy) (dx, dy) 到 (1, 0) (0, 1) (-1, 0) (0 , -1) 我现在没主意了。

更新

我一直在尝试改编@wychmaster 对这个问题的回答:

https://computergraphics.stackexchange.com/questions/12819/how-to-determine-transformation-matrix-for-an-object-given-a-graph

import numpy as np

x_all = [x - x_center for x in x_all]
y_all = [y - y_center for y in y_all]

# All x coordinates
x_all = [258.75, -401.25, -741.25, 883.75]
# All y coordinates
y_all = [156.25, 171.25, -188.75, -138.75]

# original coordinate matrix
A = np.array([x_all, y_all, [1, 1, 1, 1], [1, 1, 1, .9999999]])
# transformed coordinate matrix
A_T = np.array([[1, 0, -1, 0], [0, 1, 0, -1], [1, 1, 1, 1], [1, 1, 1, 1]])

# Solve for T where A_T = T @ A
T_1 = np.linalg.solve(A.transpose(), A_T.transpose()[:, 0])
T_2 = np.linalg.solve(A.transpose(), A_T.transpose()[:, 1])
T_3 = np.linalg.solve(A.transpose(), A_T.transpose()[:, 2])
T_4 = np.linalg.solve(A.transpose(), A_T.transpose()[:, 3])
T = np.array([T_1, T_2, T_3, T_4])

# Check to see if T @ A = A_T
print((T @ A).round(decimals=3))

# Multiply each original coordinate pair of the original coordinate space to see if they are correctly transformed
for i in range(4):
    print((T @ np.matrix([[x_all[i]], [y_all[i]], [1], [1]])).round(decimals=3))

这实际上几乎有效,但有一个问题!

您会在第 12 行注意到,我在 A 矩阵的最后一行的最后一个元素中放入了一些可怕的 hackiness,这是我为了让它运行而添加的;否则 Python 会正确地抱怨这是一个奇异矩阵。当我乘以 T @ A 时,它正确地吐出 A_T。然而,当我单独乘以每个向量时,这类似于我将如何在程序中使用这个矩阵(将单个输入坐标转换为受限空间),.999999 值搞砸了最后一个坐标,这是输出打印乘法结果的 for 循环:

[[1.]
[0.]
[1.]
[1.]]

[[-0.]
[ 1.]
[ 1.]
[ 1.]]

[[-1.]
[ 0.]
[ 1.]
[ 1.]]

[[ 1.577]
[-2.104]
[ 1.   ]
[ 1.   ]]

如您所见,它几乎有效,只需要一种方法将任意值添加到最后一行。

python transform linear-algebra
1个回答
0
投票

对于任意大小的点集,使用

lstsq
。变换矩阵将是近似的。

import numpy as np

px_space = np.array((
    ( 487.5,  200),
    (-412.5,  200),
    (-762.5, -200),
    ( 687.5, -200),
))
px_space_augmented = np.hstack((px_space, np.ones((px_space.shape[0], 1))))

norm_space = np.array((
    ( 1,  0),
    ( 0,  1),
    (-1,  0),
    ( 0, -1),
))

T, *_ = np.linalg.lstsq(px_space_augmented, norm_space)
print(T)
[[ 8.06866953e-04 -8.06866953e-04]
 [ 2.34871245e-03  2.65128755e-03]
 [-1.91559047e-36 -2.77555756e-17]]
© www.soinside.com 2019 - 2024. All rights reserved.