2组二维点间仿射变换矩阵的闭式解
Closed form solution for affine transformation matrix between 2 set of 2D points
给定具有 6 个未知变量 a_11, a_12, a_21, a_22, b_1, b_2
和对应的 3 对点的仿射变换方程 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
是否有可能以这种形式获得 a_11, a_12, a_21, a_22, b_1, b_2
的解决方案?
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)
我知道这个系统可以通过像 numpy.linalg.solve 这样的线性系统求解器求解,但我不会使用它,我需要 f1, f2, f3, f4, f5, f6
来包含常见的数学运算。
一般情况下可以吗?哪些工具可以用来求解这样的方程组?好像maple and mathematica有方程求解器,适合这个任务吗?有没有其他选择?
我假设你的意思是点 (x1,y1,u1,v1)、(x2,y2,u2,v2) 和 (x3,y3,u3,v3) 满足方程。在这种情况下,将其中的那些代入,会产生六个具有六个未知数的方程式。许多系数为零或一。因此,稍微取消一下,我们就会得到您要求的解决方案。
您的解决方案(假设您具有线性独立性)是:
a11 = ((u1-u2)(y2-y3)-(u2-u3)(y1-y2))/((x1-x2)(y2-y3)-((x2-x3)(y1-y2))
a12 = ((u1-u2)(x2-x3)-(u2-u3)(x1-x2))/((y1-y2)(x2-x3)-((y2-y3)(x1-x2))
a21 = ((v1-v2)(y2-y3)-(v2-v3)(y1-y2))/((x1-x2)(y2-y3)-((x2-x3)(y1-y2))
a22 = ((v1-v2)(x2-x3)-(v2-v3)(x1-x2))/((y1-y2)(x2-x3)-((y2-y3)(x1-x2))
b1 = u1-a11×x1-a12×y2
b2 = v1-a21×x1-a22×y2
我应该指出。这个问题更多的是mathoverflow。真的和编程无关
最后我用sympy
解了这个方程组:
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)
答案是:
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)
不过好像可以简化一下
给定具有 6 个未知变量 a_11, a_12, a_21, a_22, b_1, b_2
和对应的 3 对点的仿射变换方程 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
是否有可能以这种形式获得 a_11, a_12, a_21, a_22, b_1, b_2
的解决方案?
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)
我知道这个系统可以通过像 numpy.linalg.solve 这样的线性系统求解器求解,但我不会使用它,我需要 f1, f2, f3, f4, f5, f6
来包含常见的数学运算。
一般情况下可以吗?哪些工具可以用来求解这样的方程组?好像maple and mathematica有方程求解器,适合这个任务吗?有没有其他选择?
我假设你的意思是点 (x1,y1,u1,v1)、(x2,y2,u2,v2) 和 (x3,y3,u3,v3) 满足方程。在这种情况下,将其中的那些代入,会产生六个具有六个未知数的方程式。许多系数为零或一。因此,稍微取消一下,我们就会得到您要求的解决方案。
您的解决方案(假设您具有线性独立性)是:
a11 = ((u1-u2)(y2-y3)-(u2-u3)(y1-y2))/((x1-x2)(y2-y3)-((x2-x3)(y1-y2))
a12 = ((u1-u2)(x2-x3)-(u2-u3)(x1-x2))/((y1-y2)(x2-x3)-((y2-y3)(x1-x2))
a21 = ((v1-v2)(y2-y3)-(v2-v3)(y1-y2))/((x1-x2)(y2-y3)-((x2-x3)(y1-y2))
a22 = ((v1-v2)(x2-x3)-(v2-v3)(x1-x2))/((y1-y2)(x2-x3)-((y2-y3)(x1-x2))
b1 = u1-a11×x1-a12×y2
b2 = v1-a21×x1-a22×y2
我应该指出。这个问题更多的是mathoverflow。真的和编程无关
最后我用sympy
解了这个方程组:
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)
答案是:
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)
不过好像可以简化一下