2

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.

lurker
  • 56,987
  • 9
  • 69
  • 103
Muhammad Adeel
  • 2,877
  • 1
  • 22
  • 18
  • Probably a duplicate of http://stackoverflow.com/questions/4361242/extract-rotation-scale-values-from-2d-transformation-matrix . I personally would have recommended the approach from this answer: http://stackoverflow.com/a/9625358/ – Marco13 Feb 04 '14 at 20:10
  • thank you Marco, do you have a similar java code for this – Muhammad Adeel Feb 04 '14 at 20:20
  • Added some code in http://stackoverflow.com/a/21565237/ – Marco13 Feb 04 '14 at 22:52

4 Answers4

3

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;
    }


}
Marco13
  • 53,703
  • 9
  • 80
  • 159
  • Thank you @Marco13, this is exactly what i was looking for. Do you know if it's also possible to find **scale** and **translate** information from given values. – Muhammad Adeel Feb 06 '14 at 01:52
  • The translation is given by the result of transforming the point (0,0) with the given matrix. The scaling can be computed from the distance between `pp0` and `pp1` in the above code (or the difference in their x- and y-coordinates, if the scaling is non-homogenous) – Marco13 Feb 06 '14 at 09:18
2

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.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • If you only have those six parameters, the implication is that they are properly scaled, otherwise you are missing information from the last row of the matrix. – Mad Physicist Feb 04 '14 at 20:28
1

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]
TripleS
  • 1,216
  • 1
  • 23
  • 39
0

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.

pentadecagon
  • 4,717
  • 2
  • 18
  • 26