Алгоритм аффинного преобразования

Кто-нибудь знает какие-либо стандартные алгоритмы для определения матрицы аффинного преобразования на основе набора известных точек в двух системах координат?

1 ответ

Решение

Аффинные преобразования задаются матрицами 2x3. Мы выполняем аффинное преобразование M, взяв наш 2D-ввод (xy), увеличив его до трехмерного вектора (xy 1), а затем умножив (слева) на 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 очков, вы можете выбрать наименьшие квадраты. Вам придется еще раз спросить об этом, но это немного сложнее.

Я не уверен, насколько это стандартно, но есть хорошая формула, специально для вашего случая, представленная в " Руководстве для начинающих по аффинному отображению симплексов" и " Рабочей книге по аффинному сопоставлению симплексов". Ввод его в код должен выглядеть примерно так (извините за плохой стиль кода - я математик, а не программист)

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)

Этот код восстанавливает аффинное преобразование из заданных точек ("входы" преобразуются в "выходы") и проверяет, что оно работает.

Другие вопросы по тегам