如何找到两组3D点之间的仿射变换矩阵?

时间:2019-05-16 10:10:09

标签: matlab affinetransform

我需要注册为视频的每一帧指定的一些3D面部标志。对于此任务,我试图找出为连续帧提供的几个界标坐标之间的转换矩阵。例如,第1帧和第2帧中3个地标的3D坐标为:

frame1 = [2 4 15; 4 15 14; 20 11 7]
frame2 = [16 5 12; 5 7 9; 11 6 19]

我尝试使用matlab提供的imregtform函数和用于matlab的ABSOR工具。

tform = imregtform(frame1, frame2, 'affine','OnePlusOneEvolutionary','MeanSquares');

tform = absor(frame1, frame2)

使用imregtform时发生以下错误:

Error using imregtform>parseInputs (line 261)
The value of 'MovingImage' is invalid. All dimensions of the moving image should be greater than 4.

Error in imregtform (line 124)
parsedInputs = parseInputs(varargin{:});

注意:ABSOR找不到仿射变换,而是找到相似变换。

1 个答案:

答案 0 :(得分:1)

首先,只有3点太少,无法恢复仿射变换-您需要4点。对于N维空间,有一个简单的规则:要明确地恢复仿射变换,您应该知道N + 1个点的图像,这些图像形成了单纯形-对于2D为三角形,对于3D为金字塔等。只有3个点,您只能检索2D仿射变换。为何会在“ Beginner's guide to mapping simplexes affinely”中找到这种情况的很好解释。

关于某些检索算法。恐怕,我不知道Matlab是否为您提供适当的代码,但是我稍微使用了Python,也许此代码可以提供帮助(对不起,不好的代码风格-我是数学家,而不是程序员)

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)

此代码演示了如何将仿射变换恢复为矩阵和向量,并测试了初始点已映射到它们应在的位置。它基于“ Beginner's guide to mapping simplexes affinely”中给出的方程式,矩阵恢复在“规范符号的恢复”部分中进行了描述。同一作者发表了“ Workbook on mapping simplexes affinely”,其中包含许多此类实际示例。