I have a transform matrix with values like this.
Transform: xx, xy, yx, yy, tx, and ty respectively.
How can I find the angle from the above set of gives values.
I have a transform matrix with values like this.
Transform: xx, xy, yx, yy, tx, and ty respectively.
How can I find the angle from the above set of gives values.
If it's only about the rotation, one can transform the vector (1,0) using the given matrix, and compute the angle between the resulting vector and the x-axis, as already mentioned in the comment to the original question
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.Random;
public class ExtractRotation
{
public static void main(String[] args)
{
for (int i=0; i<=180; i++)
{
double angleRad = Math.toRadians(i);
AffineTransform at = createRandomTransform(angleRad);
double extractedAngleRad = extractAngle(at);
System.out.println(
"In: "+Math.toDegrees(angleRad)+ " " +
"Out "+Math.toDegrees(extractedAngleRad));
}
}
private static double extractAngle(double m[])
{
return extractAngle(new AffineTransform(m));
}
private static double extractAngle(AffineTransform at)
{
Point2D p0 = new Point();
Point2D p1 = new Point(1,0);
Point2D pp0 = at.transform(p0, null);
Point2D pp1 = at.transform(p1, null);
double dx = pp1.getX() - pp0.getX();
double dy = pp1.getY() - pp0.getY();
double angle = Math.atan2(dy, dx);
return angle;
}
private static Random random = new Random(0);
private static AffineTransform createRandomTransform(double angleRad)
{
AffineTransform at = new AffineTransform();
double scale = 1.0;
at.translate(randomDouble(), randomDouble());
scale = Math.abs(randomDouble());
at.scale(scale, scale);
at.rotate(angleRad);
at.translate(randomDouble(), randomDouble());
scale = Math.abs(randomDouble());
at.scale(scale, scale);
return at;
}
private static double randomDouble()
{
return -5.0 + random.nextDouble() * 10;
}
}
Referring to the Wikipedia page on transformation matrices: http://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations.
tx
and ty
are translations. The remaining elements make up a rotation matrix:
xx xy
yx yy
Note that this is equivalent to
cos(θ) sin(θ)
-sin(θ) cos(θ)
where θ
is the clockwise rotation angle. From this you get that xx = yy = cos(θ)
and xy = -yx = sin(θ)
. The angle can be calculated as Math.atan2(xy, xx)
. This will give you a result that is between -π
and π
. Math.acos(xx)
, Math.acos(yy)
, Math.asin(xy)
, Math.asin(-yx)
and -Math.asin(yx)
all work for angles between zero than π/2
.
In case you'll choose to use affine transform with 4 degrees of freedom (scaling, rotation and translation) you don't have to decompose the rotation matrix. There is a direct solution for extracting the translation and rotation
Here is a python implementation with opencv
# Note: This function calculate only 4 degrees of freedom !!! scaling, rotation and translation
h, mask = cv.estimateAffinePartial2D(pointsRef, pointsCur, method=cv.RANSAC, ransacReprojThreshold=3, confidence=0.9)
# Estimate the rotation angle from the matrix [s]
# Extract traslation
dx = h[0, 2]
dy = h[1, 2]
# Extract rotation angle
da = np.arctan2(h[1, 0], h[0, 0])
print(np.rad2deg(da))
# Store transformation
transforms = [dx, dy, da]
Those 6 numbers describe an affine transformation, which in general consists of (non-uniform) scaling, rotation and translation. The translation is represented by (tx, ty)
. This leaves the remaining 4 numbers, which must be decomposed into scaling and rotation. The easiest way to do this would be a Singular value decomposition: Here you decompose the matrix as M=UDV
, where M
is your original matrix
xx xy
yx yy
U and V are orthogonal rotation matrices, and D is a diagonal matrix. This represents your affine transformation as three steps, the rotation V
, followed by scaling D
, and rotation U
. The two entries of D
are the two scaling coefficients for x and y. From U
and V
you can obtain the rotation angles, as described by Mad Physicist . The total rotation is the sum of both.