Given a AffineTransform, how can I determine rotation, mirroring, scaling, etc.?

Mike Cantrell :

I'm working on a problem I have with analyzing images in a PDF. Sometimes the images are resized, rotated, mirrored, etc.. I have access to the PDF context matrix as a AffineTransform:

For instance:

resized image:

AffineTransform[[432.2279052734375, 0.0, 90.0], [0.0, 150.67495727539062, 555.257080078125]]

rotated/mirrored image:

AffineTransform[[593.25, 0.0, 0.0], [0.0, -768.0, 768.1500244140625]]

Given an AffineTransform instance, I assume it's possible to determine:

  • scaleX
  • scaleY
  • rotation
  • shear

Unfortunately, my geometry skills are lacking (to say the least). Can anyone point me in the right direction for performing these calculations?

Joni :

It is possible to represent an affine transform as sequences of translations, rotations, reflections, scales, and shears. The way to compute them is called matrix decomposition.

There are lots of options for software packages to do it, for example the JAMA package or Apache Commons Math.

Singular value decomposition (SVD) gives you a decomposition into rotation, followed by scaling, followed by another rotation.

Here's a sample that uses JAMA to compute the SVD of a shear, and extract angles of rotation and factors of scale from it:

import Jama.*;

public class Demo {
    public static void main(String[] args) {
        double[][] vals = {{1, 1}, {0, 2}};
        Matrix a = new Matrix(vals);
        SingularValueDecomposition svd = a.svd();
        Matrix u = svd.getU();
        Matrix v = svd.getV();
        double[] s = svd.getSingularValues();
        System.out.printf("rotate=%f scaleX=%f scaleY=%f rotate=%f\n",
                Math.toDegrees(Math.atan2(u.get(0, 1), u.get(0, 0))),
                s[0], s[1],
                Math.toDegrees(Math.atan2(v.get(0, 1), v.get(0, 0))));
    }
}

The output tells you it's a 76 degree rotation, followed by scale X and scale Y, followed by a 58 degree rotation:

rotate=-58.282526 scaleX=2.288246 scaleY=0.874032 rotate=-76.717474

Beware: if your transform involves flipping the image, this code will not work. The SVD routine in JAMA will lump the mirroring together with one of the rotations. Since you only have 2x2 matrices, you may want to consider writing your own specialized SVD implementation.

With other matrix decompositions you can get other representations, for example shear-scale-shear (LU decomp), or rotation-scale-shear (QR decomp)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=335373&siteId=1