I have two images and found three similar 2D points using a sift. I need to compute the affine transformation between the images. Unfortunately, I missed lecture and the information out there is a little dense for me. What would the general method be for computing this 2x3 matrix?
I have the matrix of points in a 2x3 matrix [x1 y1;x2 y2;x3 y3] but I am lost from there.
Thanks for any help.
Usually, an affine transormation of 2D points is experssed as
x' = A*x
Where x
is a three-vector [x; y; 1]
of original 2D location and x'
is the transformed point. The affine matrix A
is
A = [a11 a12 a13;
a21 a22 a23;
0 0 1]
This form is useful when x
and A
are known and you wish to recover x'
.
However, you can express this relation in a different way.
Let
X = [xi yi 1 0 0 0;
0 0 0 xi yi 1 ]
and a
is a column vector
a = [a11; a12; a13; a21; a22; a23]
Then
X*a = [xi'; yi']
Holds for all pairs of corresponding points x_i, x_i'
.
This alternative form is very useful when you know the correspondence between pairs of points and you wish to recover the paramters of A
.
Stacking all your points in a large matrix X
(two rows for each point) you'll have 2*n-by-6 matrix X
multiplyied by 6-vector of unknowns a
equals a 2*n-by-1 column vector of the stacked corresponding points (denoted by x_prime
):
X*a = x_prime
Solving for a
:
a = X \ x_prime
Recovers the parameters of a
in a least-squares sense.
Good luck and stop skipping class!
Sorry for not using Matlab, but I only worked with Python a little bit. I think this code may help you (sorry for bad codestyle -- I'm mathematician, not programmer)
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)
This code demonstrates how to recover affine transformation as matrix and vector and tests that initial points are mapped to where they should. You can test this code with Google colab, so you don't have to install anything. Probably, you can translate it to Matlab.
Regarding theory behind this code: it is based on equation presented in "Beginner's guide to mapping simplexes affinely", matrix recovery is described in section "Recovery of canonical notation". The same authors published "Workbook on mapping simplexes affinely" that contains many practical examples of this kind.