【问题标题】:Calculate a 2D homogeneous perspective transformation matrix from 4 points in MATLAB在MATLAB中从4个点计算一个2D齐次透视变换矩阵
【发布时间】:2016-06-19 13:13:52
【问题描述】:

我有 4 个 2D 点的坐标,它们形成一个矩形,以及在应用透视变换后它们的坐标。

透视变换在齐次坐标中计算并由 3x3 矩阵M 定义。如果矩阵未知,我如何从给定的点计算它?

一个点的计算是:

| M11 M12 M13 |   | P1.x |   | w*P1'.x |
| M21 M22 M23 | * | P1.y | = | w*P1'.y |
| M31 M32 M33 |   | 1    |   | w*1     |

为了同时计算所有点,我将它们一起写在一个矩阵A 中,类似地用于矩阵B 中的转换点:

    | P1.x P2.x P3.x P4.x |
A = | P1.y P2.y P3.y P4.y |
    | 1    1    1    1    |

所以等式是M*A=B,这可以通过M = B/AM = (A'\B')' 在MATLAB 中求解M

但这并不容易。我知道变换后点的坐标,但我不知道确切的B,因为有因子w,在齐次变换后不需要1。因为在齐次坐标中,向量的每个倍数都是同一个点,我不知道我会得到哪个倍数。

考虑到这些未知因素,我将等式写为M*A=B*W 其中W 是一个对角矩阵,其对角线上B 中的每个点的因子为 w1...w4。所以AB 现在已经完全知道了,我必须为MW 求解这个方程。

如果我可以将方程重新排列为x*A=BA*x=B 的形式,其中x 将类似于M*W,我可以解决它并且知道M*W 的解决方案可能已经足够了。然而,尽管尝试了所有可能的重新排列,但我没有成功。直到我意识到封装 (M*W) 是不可能的,因为一个是 3x3 矩阵,另一个是 4x4 矩阵。我在这里卡住了。

另外,M*A=B*W 没有针对M 的单一解,因为M 的每个倍数都是相同的转换。把它写成一个线性方程组,可以简单地修复M 的一个条目来获得一个单一的解决方案。此外,可能有一些输入根本无法解决M,但我们暂时不用担心。

我实际上想要实现的是某种矢量图形编辑程序,用户可以在其中拖动形状边界框的角来对其进行变换,同时在内部计算变换矩阵。

实际上我在 JavaScript 中需要这个,但如果我什至不能在 MATLAB 中解决这个问题,我就会完全陷入困境。

【问题讨论】:

    标签: matlab matrix transform linear-algebra


    【解决方案1】:

    应该是一个简单的问题。那么如何将M*A=B*W 转换为可解形式?它只是矩阵乘法,所以我们可以把它写成一个线性方程组。你知道:M11*A11 + M12*A21 + M13*A31 = B11*W11 + B12*W21 + B13*W31 + B14*W41。每个线性方程组都可以写成Ax=b 的形式,或者为了避免与我的问题中已经使用的变量混淆:N*x=y。就是这样。

    根据我的问题的一个例子:我用已知的MW 生成一些输入数据:

    M = [
        1 2 3;
        4 5 6;
        7 8 1
    ];
    A = [
        0 0 1 1;
        0 1 0 1;
        1 1 1 1
    ];
    W = [
        4 0 0 0;
        0 3 0 0;
        0 0 2 0;
        0 0 0 1
    ];
    B = M*A*(W^-1);
    

    然后我忘记了MW。这意味着我现在有 13 个变量要解决。我将M*A=B*W 改写为线性方程组,并从那里改写为N*x=y 的形式。在N 中,每一列都有一个变量的因子:

    N = [
        A(1,1) A(2,1) A(3,1)      0      0      0      0      0      0 -B(1,1)       0       0       0;
             0      0      0 A(1,1) A(2,1) A(3,1)      0      0      0 -B(2,1)       0       0       0;
             0      0      0      0      0      0 A(1,1) A(2,1) A(3,1) -B(3,1)       0       0       0;
        A(1,2) A(2,2) A(3,2)      0      0      0      0      0      0       0 -B(1,2)       0       0;
             0      0      0 A(1,2) A(2,2) A(3,2)      0      0      0       0 -B(2,2)       0       0;
             0      0      0      0      0      0 A(1,2) A(2,2) A(3,2)       0 -B(3,2)       0       0;
        A(1,3) A(2,3) A(3,3)      0      0      0      0      0      0       0       0 -B(1,3)       0;
             0      0      0 A(1,3) A(2,3) A(3,3)      0      0      0       0       0 -B(2,3)       0;
             0      0      0      0      0      0 A(1,3) A(2,3) A(3,3)       0       0 -B(3,3)       0;
        A(1,4) A(2,4) A(3,4)      0      0      0      0      0      0       0       0       0 -B(1,4);
             0      0      0 A(1,4) A(2,4) A(3,4)      0      0      0       0       0       0 -B(2,4);
             0      0      0      0      0      0 A(1,4) A(2,4) A(3,4)       0       0       0 -B(3,4);
             0      0      0      0      0      0      0      0      1       0       0       0       0
    ];
    

    y 是:

    y = [ 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 1 ];
    

    注意N 中最后一行描述的方程,根据y,其解为1。这就是我在问题中提到的,您必须修复 M 的其中一个条目才能获得单一解决方案。 (我们可以这样做,因为M 的每个倍数都是相同的变换。)通过这个等式,我说 M33 应该是 1。

    我们为x解决了这个问题:

    x = N\y
    

    然后得到:

    x = [ 1.00000; 2.00000; 3.00000; 4.00000; 5.00000; 6.00000; 7.00000; 8.00000; 1.00000; 4.00000; 3.00000; 2.00000; 1.00000 ]
    

    [ M11, M12, M13, M21, M22, M23, M31, M32, M33, w1, w2, w3, w4 ]的解决方案有哪些

    在 JavaScript 中执行此操作时,我可以使用 Numeric JavaScript 库,它具有所需的函数 solve 来解决 Ax=b。

    【讨论】:

      【解决方案2】:

      OpenCV 有一个简洁的函数,称为getPerspectiveTransform。此函数的源代码可在on github 获得,并附有说明:

      /* Calculates coefficients of perspective transformation
       * which maps (xi,yi) to (ui,vi), (i=1,2,3,4):
       *
       *      c00*xi + c01*yi + c02
       * ui = ---------------------
       *      c20*xi + c21*yi + c22
       *
       *      c10*xi + c11*yi + c12
       * vi = ---------------------
       *      c20*xi + c21*yi + c22
       *
       * Coefficients are calculated by solving linear system:
       * / x0 y0  1  0  0  0 -x0*u0 -y0*u0 \ /c00\ /u0\
       * | x1 y1  1  0  0  0 -x1*u1 -y1*u1 | |c01| |u1|
       * | x2 y2  1  0  0  0 -x2*u2 -y2*u2 | |c02| |u2|
       * | x3 y3  1  0  0  0 -x3*u3 -y3*u3 |.|c10|=|u3|,
       * |  0  0  0 x0 y0  1 -x0*v0 -y0*v0 | |c11| |v0|
       * |  0  0  0 x1 y1  1 -x1*v1 -y1*v1 | |c12| |v1|
       * |  0  0  0 x2 y2  1 -x2*v2 -y2*v2 | |c20| |v2|
       * \  0  0  0 x3 y3  1 -x3*v3 -y3*v3 / \c21/ \v3/
       *
       * where:
       *   cij - matrix coefficients, c22 = 1
       */
      

      这个方程组更小,因为它避免了求解WM33(OpenCV 称为c22)。那么它是怎样工作的?可以通过以下步骤重新创建线性系统:

      从投影变换的公式开始:

           c00*xi + c01*yi + c02
      ui = ---------------------
           c20*xi + c21*yi + c22
      
           c10*xi + c11*yi + c12
      vi = ---------------------
           c20*xi + c21*yi + c22
      

      两边乘以分母:

      (c20*xi + c21*yi + c22) * ui = c00*xi + c01*yi + c02
      (c20*xi + c21*yi + c22) * vi = c10*xi + c11*yi + c12
      

      分发uivi

      c20*xi*ui + c21*yi*ui + c22*ui = c00*xi + c01*yi + c02
      c20*xi*vi + c21*yi*vi + c22*vi = c10*xi + c11*yi + c12
      

      假设c22 = 1:

      c20*xi*ui + c21*yi*ui + ui = c00*xi + c01*yi + c02
      c20*xi*vi + c21*yi*vi + vi = c10*xi + c11*yi + c12
      

      收集左侧所有cij

      c00*xi + c01*yi + c02 - c20*xi*ui - c21*yi*ui = ui
      c10*xi + c11*yi + c12 - c20*xi*vi - c21*yi*vi = vi
      

      最后将四对点转化为矩阵形式:

      / x0 y0  1  0  0  0 -x0*u0 -y0*u0 \ /c00\ /u0\
      | x1 y1  1  0  0  0 -x1*u1 -y1*u1 | |c01| |u1|
      | x2 y2  1  0  0  0 -x2*u2 -y2*u2 | |c02| |u2|
      | x3 y3  1  0  0  0 -x3*u3 -y3*u3 |.|c10|=|u3|
      |  0  0  0 x0 y0  1 -x0*v0 -y0*v0 | |c11| |v0|
      |  0  0  0 x1 y1  1 -x1*v1 -y1*v1 | |c12| |v1|
      |  0  0  0 x2 y2  1 -x2*v2 -y2*v2 | |c20| |v2|
      \  0  0  0 x3 y3  1 -x3*v3 -y3*v3 / \c21/ \v3/
      

      现在是Ax=b 的形式,可以通过x = A\b 获得解决方案。请记住c22 = 1

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-19
        • 2020-07-09
        • 1970-01-01
        相关资源
        最近更新 更多