从3个点生成AffineTransform

问题描述 投票:0回答:3

给定坐标系 A 中的 3 个点(x 和 y 坐标)和坐标系 B 中的 3 个对应点,我如何导出将从 A 转换为 B 的 AffineTransform。

我的问题类似于创建变换以从一个矩形映射到另一个矩形?,但该问题仅处理 2 个点 - 即,它假设没有旋转。

java awt affinetransform
3个回答
3
投票

假设您的变换具有以下形式

x' = px + qy + r
y' = sx + ty + u

并将您的六点写为

(A1x, A1y), (A2x, A2y), (A3x, A3y), (B1x, B1y), (B2x, B2y), (B3x, B3y)
。以矩阵形式表达它给出

/               \       /           \   /               \
| B1x  B2x  B3x |       | p   q   r |   | A1x  A2x  A3x |
|               |   =   |           |   |               |
| B1y  B2y  B3y |       | s   t   u |   | A1y  A2y  A3y |
\               /       \           /   |               |
                                        |  1    1    1  |
                                        \               /

现在求右侧 3x3 矩阵的逆矩阵。您会在网上找到大量算法来告诉您如何做到这一点。例如,http://www.econ.umn.edu/undergrad/math/An%20Algorithm%20for%20Finding%20the%20Inverse.pdf 中有一个。

将上式两边分别乘以 3x3 矩阵的逆矩阵,得到

p, q, r, s, t, u, v
的值。


3
投票

如果这对其他人有用,这里是我用来执行此操作的 Java 代码。

    public static AffineTransform deriveAffineTransform(
        double oldX1, double oldY1,
        double oldX2, double oldY2,
        double oldX3, double oldY3,
        double newX1, double newY1,
        double newX2, double newY2,
        double newX3, double newY3) {

    double[][] oldData = { {oldX1, oldX2, oldX3}, {oldY1, oldY2, oldY3}, {1, 1, 1} };
    RealMatrix oldMatrix = MatrixUtils.createRealMatrix(oldData);

    double[][] newData = { {newX1, newX2, newX3}, {newY1, newY2, newY3} };
    RealMatrix newMatrix = MatrixUtils.createRealMatrix(newData);

    RealMatrix inverseOld = new LUDecomposition(oldMatrix).getSolver().getInverse();
    RealMatrix transformationMatrix = newMatrix.multiply(inverseOld);

    double m00 = transformationMatrix.getEntry(0, 0);
    double m01 = transformationMatrix.getEntry(0, 1);
    double m02 = transformationMatrix.getEntry(0, 2);
    double m10 = transformationMatrix.getEntry(1, 0);
    double m11 = transformationMatrix.getEntry(1, 1);
    double m12 = transformationMatrix.getEntry(1, 2);

    return new AffineTransform(m00, m10, m01, m11, m02, m12);       
}

0
投票

避免 org.apache.commons.math 的答案:

// See https://www.math.ucla.edu/%7Ebaker/149.1.02w/handouts/i_affine_II.pdf
public static AffineTransform deriveAffineTransform(
        double oldX1, double oldY1,
        double oldX2, double oldY2,
        double oldX3, double oldY3,
        double newX1, double newY1,
        double newX2, double newY2,
        double newX3, double newY3 ) {

    try {
        final AffineTransform oldT= triangleTransform( oldX1, oldY1, oldX2, oldY2, oldX3, oldY3 );
        final AffineTransform newT= triangleTransform( newX1, newY1, newX2, newY2, newX3, newY3 );
        
        AffineTransform result = new AffineTransform( oldT );
        result.invert();
        result.preConcatenate( newT );
        return result;
    } catch (NoninvertibleTransformException e) {
        // Will only occur if _from_ is not really a triangle because the points are collinear
        throw new RuntimeException( e );
    }
}

/**
 * @return the transform that maps triangle (0,0), (1,0), (0,1) to (x1,y1), (x2,y2), (x3,y3)
 */
private static AffineTransform triangleTransform(
        double x1, double y1,
        double x2, double y2,
        double x3, double y3 ) {
    return new AffineTransform(
            x2 - x1,y2 - y2,
            x3 - x1,y3 - y1,
            x1, y1 );
}
© www.soinside.com 2019 - 2024. All rights reserved.