给出三点计算仿射变换

Dee*_*eVu 13 matlab geometry image-processing linear-algebra computer-vision

我有两个图像,并使用筛选找到三个相似的2D点.我需要计算图像之间的仿射变换.不幸的是,我错过了讲座,那里的信息对我来说有点密集.计算这个2x3矩阵的一般方法是什么?

我有一个2x3矩阵中的点矩阵[x1 y1; x2 y2; x3 y3],但我从那里迷失了.谢谢你的帮助.

Sha*_*hai 34

通常,2D点的仿射变换被表示为

x' = A*x
Run Code Online (Sandbox Code Playgroud)

原始2D位置x的三向量在哪里[x; y; 1]并且x'是变换点.仿射矩阵A

A = [a11 a12 a13;
     a21 a22 a23;
       0   0   1]
Run Code Online (Sandbox Code Playgroud)

当这种形式是非常有用的x,并A的已知,并希望恢复x'.

但是,您可以以不同的方式表达这种关系.让

X = [xi yi 1  0  0  0;
      0  0 0 xi yi  1 ]
Run Code Online (Sandbox Code Playgroud)

并且a是列向量

a = [a11; a12; a13; a21; a22; a23]
Run Code Online (Sandbox Code Playgroud)

然后

X*a = [xi'; yi']
Run Code Online (Sandbox Code Playgroud)

保留所有对应点x_i, x_i'.

当您知道点对之间的对应关系并希望恢复其中的参数时,这种替代形式非常有用A.
将所有点堆叠在一个大矩阵中X(每个点两行),你将有2*n×6矩阵X乘以未知数的6矢量a等于堆叠对应点的2*n×1列向量(表示x_prime):

X*a = x_prime
Run Code Online (Sandbox Code Playgroud)

解决a:

a = X \ x_prime
Run Code Online (Sandbox Code Playgroud)

恢复a最小二乘意义上的参数.

祝你好运并停止上课!

  • 很好的答案,你走了高路; 只需要添加一件事 - 如果`x`是'N-by-2`,从`x`->`X`开始的便捷方式是`X = kron(eye(2),[x ones(size(size)的x,1),1)])`.另外,对于你正在使用的`X`和`a`大小,你需要`mldivide`来解决系统(`a = X\x_prime`),除非你转置两者(`x_prime'/ X'` ). (6认同)

gue*_*est 9

抱歉没有使用 Matlab,但我只使用了一点 Python。我认为这段代码可以帮助你(抱歉糟糕的代码风格——我是数学家,不是程序员)

import numpy as np
# input data
ins = [[1, 1], [2, 3], [3, 2]]  # <- points
out = [[0, 2], [1, 2], [-2, -1]] # <- 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)
Run Code Online (Sandbox Code Playgroud)

此代码演示了如何将仿射变换恢复为矩阵和向量,并测试初始点是否映射到应有的位置。您可以使用Google colab测试此代码,因此您无需安装任何东西。也许,您可以将其转换为 Matlab。

关于此代码背后的理论:它基于“仿射单纯形映射初学者指南”中提出的方程,矩阵恢复在“规范符号的恢复”一节中进行了描述。同一位作者发表了“仿射单纯形映射工作簿”,其中包含许多此类实际示例。