我正在尝试实现透视投影。例如,我有一个给定大小的正方形,并知道其角落的坐标(A1..A4)。我有一张图像,在这个图像中,该正方形显示在某个特定位置。我知道它的位置以及显示正方形的角落B1..B4的坐标。我想找到一个转换矩阵M,将B-> A。
我遵循方法数学插图,第10章,并成功地转换了3个角。但是我无法找到正确转换所有4个角的矩阵...我按照第7页上的矩阵进行转换,但不能正确地转换所有4个点。
~
Find a 3x3 matrix T, such that:
it maps each point b to corresponding point a: a = b T
specifically:
w' * [a_x a_y 1] = w * [b_x b_y 1] * [ T_xx T_xy T_xw ]
[ T_yx T_yy T_yw ]
[ T_wx T_wy T_ww ]
w
和w'
设为1。这是因为一个投影变换T
并不一定会保持第三个坐标不变!(如果它确实如此,你可以完全跳过齐次部分,并且只使用三个点对来获得仿射变换……)K = w' / w
。然后,您可以将上述内容表示为线性系统,如下所示:for each point b and corresponding point a,
[a_x a_y 1] * K = [b_x b_y 1] * [ T_xx T_xy T_xw ]
[ T_yx T_yy T_yw ]
[ T_wx T_wy T_ww ]
a
和 b
值都是固定常数;您正在尝试解决 T
矩阵的九个元素。每对点会添加三个约束条件(来自上面的向量相等式)和一个附加参数(该方程的 K),总共有 4*3=12 个约束条件和 9+4=13 个参数。因此,我们在这里缺少一个约束条件...T
实际上具有任意缩放因子:它在同质坐标之间进行映射(所有同质坐标都会除以任意缩放因子),因此没有内在的方法来确定这个缩放因子。一种固定这个因子的方法是将 T_ww = 1
任意设置为一个值:for each point pair (a, b):
[a_x a_y 1] * K = [b_x b_y 1] * [ T_xx T_xy T_xw ]
[ T_yx T_yy T_yw ]
[ T_wx T_wy 1 ]
0 = b1_x*T_xx + b1_y*T_yx + 1*T_wx - a1_x*K1
0 = b1_x*T_xy + b1_y*T_yy + 1*T_wy - a1_y*K1
-1*1 = b1_x*T_xw + b1_y*T_yw - 1*K1
0 = b2_x*T_xx + b2_y*T_yx + 1*T_wx - a2_x*K2
0 = b2_x*T_xy + b2_y*T_yy + 1*T_wy - a2_y*K2
-1*1 = b2_x*T_xw + b2_y*T_yw - 1*K2
0 = b3_x*T_xx + b3_y*T_yx + 1*T_wx - a3_x*K3
0 = b3_x*T_xy + b3_y*T_yy + 1*T_wy - a3_y*K3
-1*1 = b3_x*T_xw + b3_y*T_yw - 1*K3
0 = b4_x*T_xx + b4_y*T_yx + 1*T_wx - a4_x*K4
0 = b4_x*T_xy + b4_y*T_yy + 1*T_wy - a4_y*K4
-1*1 = b4_x*T_xw + b4_y*T_yw - 1*K4
你现在有12个线性方程和12个变量(矩阵元素T_**
和额外的缩放参数K*
)。使用线性代数库解决这个系统并获得结果(假设你不想自己编写求解器...)。
在数学堆栈交换中提供了一个更好的答案,可以解决8x8系统。 https://mathematica.stackexchange.com/questions/9244/solve-system-of-equations-related-to-perspective-projection
T
的缩放因子的方法是任意设置其中一个额外的缩放因子(比如说K1=1
,而不是T_ww
)。这将从线性系统中消除一个不必要的奇异点。 - comingstormK
。 - comingstorm