问题
Given 3 points (x and y coordinates) in coordinate system A, and 3 corresponding points in coordinate system B, how can I derive an AffineTransform that will convert from A to B.
My question is similar to Create transform to map from one rectangle to another?, except that question only deals with 2 points - i.e., it assumes there is no rotation.
回答1:
Suppose your transform is of the form
x' = px + qy + r
y' = sx + ty + u
and write your six points as (A1x, A1y), (A2x, A2y), (A3x, A3y), (B1x, B1y), (B2x, B2y), (B3x, B3y)
. Expressing this in matrix form gives
/ \ / \ / \
| B1x B2x B3x | | p q r | | A1x A2x A3x |
| | = | | | |
| B1y B2y B3y | | s t u | | A1y A2y A3y |
\ / \ / | |
| 1 1 1 |
\ /
Now find the inverse of the 3x3 matrix on the right. You'll find plenty of algorithms online telling you how to do this. There's one at http://www.econ.umn.edu/undergrad/math/An%20Algorithm%20for%20Finding%20the%20Inverse.pdf, for example.
Post-multiply both sides of the equation above by the inverse of the 3x3 matrix, to get the values of p, q, r, s, t, u, v
.
回答2:
In case this is useful to anyone else, here is the Java code I used to do this.
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);
}
来源:https://stackoverflow.com/questions/21270892/generate-affinetransform-from-3-points