Search code examples
wolfram-mathematicalinear-algebrasympymapleaffinetransform

Closed form solution for affine transformation matrix between 2 set of 2D points


Given affine transform equation with 6 unknown variables a_11, a_12, a_21, a_22, b_1, b_2 and corresponding 3 pairs of points x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3:

u = a_11 * x + a_12 * y + b_1
v = a_21 * x + a_22 * y + b_2

Is it possible to get solution for a_11, a_12, a_21, a_22, b_1, b_2 in the this form?

a_11 = f1(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3)
a_12 = f2(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3)
a_21 = f3(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3)
a_22 = f4(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3)
b_1 = f5(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3)
b_2 = f6(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3)

I know that this system can be solved via linear system solver like numpy.linalg.solve, but I can't use it and I need f1, f2, f3, f4, f5, f6 to contain common math operations.

Is it possible in general? Which tools can be used to solve such system of equations? Seems maple and mathematica have equation solver, is it suitable for this task? is there any alternatives?


Solution

  • Finally I used sympy to solve this system of equations:

    from sympy.solvers.solveset import linsolve
    from sympy import *
    
        #u1 = a_11 * x1 + a_12 * y1 + b_1
        #v1 = a_21 * x1 + a_22 * y1 + b_2
        #u2 = a_11 * x2 + a_12 * y2 + b_1
        #v2 = a_21 * x2 + a_22 * y2 + b_2
        #u3 = a_11 * x3 + a_12 * y3 + b_1
        #v3 = a_21 * x3 + a_22 * y3 + b_2
    
        a_11, a_12, a_21, a_22, b_1, b_2, x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3 = \
            symbols('a_11, a_12, a_21, a_22, b_1, b_2, x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3')
    
        s = linsolve([a_11 * x1 + a_12 * y1 + b_1-u1,
                      a_21 * x1 + a_22 * y1 + b_2-v1,
                      a_11 * x2 + a_12 * y2 + b_1-u2,
                      a_21 * x2 + a_22 * y2 + b_2-v2,
                      a_11 * x3 + a_12 * y3 + b_1-u3,
                      a_21 * x3 + a_22 * y3 + b_2-v3], (a_11, a_12, a_21, a_22, b_1, b_2))
    
        print(s)
    

    The answer is:

    a_11 = (u1 * y2 - u1 * y3 - u2 * y1 + u2 * y3 + u3 * y1 - u3 * y2) / (
                 x1 * y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2)
    
    a_12 = (-u1 * x2 + u1 * x3 + u2 * x1 - u2 * x3 - u3 * x1 + u3 * x2) / (
                x1 * y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2)
    
    a_21 = (v1 * y2 - v1 * y3 - v2 * y1 + v2 * y3 + v3 * y1 - v3 * y2) / (
                x1 * y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2)
    
    a_22 = (-v1 * x2 + v1 * x3 + v2 * x1 - v2 * x3 - v3 * x1 + v3 * x2) / (
                x1 * y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2)
    
    b_1 = (u1 * x2 * y3 - u1 * x3 * y2 - u2 * x1 * y3 + u2 * x3 * y1 + u3 * x1 * y2 - u3 * x2 * y1) / (
                x1 * y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2)
    
    b_2 = (v1 * x2 * y3 - v1 * x3 * y2 - v2 * x1 * y3 + v2 * x3 * y1 + v3 * x1 * y2 - v3 * x2 * y1) / (
                x1 * y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2)
    

    But it looks like it can be simplified.