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

use*_*202 2 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]
Run Code Online (Sandbox Code Playgroud)

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

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

tform = absor(frame1, frame2)
Run Code Online (Sandbox Code Playgroud)

使用时出现如下错误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{:});
Run Code Online (Sandbox Code Playgroud)

注意:ABSOR 不查找仿射变换,它查找相似变换。

gue*_*est 7

首先,3 个点对于恢复仿射变换来说太少了——你需要 4 个点。对于 N 维空间,有一个简单的规则:要明确地恢复仿射变换,您应该知道形成单纯形的 N+1 个点的图像 --- 2D 为三角形,3D 为金字塔等。使用 3 个点,您只能检索 2D仿射变换。关于为什么会出现这种情况的一个很好的解释,您可以在“仿射单纯形映射初学者指南”中找到”中找到一个很好的解释。

关于一些检索算法。恐怕,我不知道 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)
Run Code Online (Sandbox Code Playgroud)

此代码演示了如何将仿射变换恢复为矩阵和向量,并测试初始点是否映射到应有的位置。它基于“仿射单纯形映射初学者指南”中提出的方程,矩阵恢复在“规范符号的恢复”部分中描述。同一作者发表了“仿射单纯形映射工作簿”,其中包含许多此类的实际示例。