仿射变换算法

时间:2010-05-03 01:49:50

标签: algorithm math

有没有人知道任何基于两个坐标系中一组已知点确定仿射变换矩阵的标准算法?

2 个答案:

答案 0 :(得分:30)

仿射变换由2x3矩阵给出。我们通过获取2D输入(x y),将其碰撞到3D矢量(x y 1),然后将(在左侧)乘以M来执行仿射变换M.

因此,如果我们有三个点(x1 y1)(x2 y2)(x3 y3)映射到(u1 v1)(u2 v2)(u3 v3)那么我们有

   [x1 x2 x3]   [u1 u2 u3]
M  [y1 y2 y3] = [v1 v2 v3].
   [ 1  1  1]

只需将右侧乘以

的倒数即可得到M.
[x1 x2 x3]
[y1 y2 y3]
[ 1  1  1].

2x3矩阵右侧乘以3x3矩阵,得到我们想要的2x3。 (您实际上并不需要完整的逆,但如果矩阵逆可用,则很容易使用。)

轻松适应其他方面。如果你有超过3分,你可能想要最小方格最合适。你不得不再次问这个问题,但这有点困难。

答案 1 :(得分:0)

我不确定它的标准如何,但是有一个很好的公式,特别是针对您在“ Beginner's guide to mapping simplexes affinely”和“ Workbook on mapping simplexes affinely”中提出的情况。 将其放入代码应该看起来像这样(对不起,不好的代码风格-我是数学家,而不是程序员)

import numpy as np
# input data
ins = [[1, 1, 2], [2, 3, 0], [3, 2, -2], [-2, 2, 3]]  # <- points
out = [[0, 2, 1], [1, 2, 2], [-2, -1, 6], [4, 1, -3]] # <- mapped to
# calculations
l = len(ins)
B = np.vstack([np.transpose(ins), np.ones(l)])
D = 1.0 / np.linalg.det(B)
entry = lambda r,d: np.linalg.det(np.delete(np.vstack([r, B]), (d+1), axis=0))
M = [[(-1)**i * D * entry(R, i) for i in range(l)] for R in np.transpose(out)]
A, t = np.hsplit(np.array(M), [l-1])
t = np.transpose(t)[0]
# output
print("Affine transformation matrix:\n", A)
print("Affine transformation translation vector:\n", t)
# unittests
print("TESTING:")
for p, P in zip(np.array(ins), np.array(out)):
  image_p = np.dot(A, p) + t
  result = "[OK]" if np.allclose(image_p, P) else "[ERROR]"
  print(p, " mapped to: ", image_p, " ; expected: ", P, result)

此代码从给定的点(从“输入”转换为“输出”)恢复仿射变换,并测试其是否有效。