I was playing around with some of the Image processing commands like ImageRotate.

I thought it would be fun to try and make up some basic linear transformation rules - starting in 2D and then going to 3D.

I wrote up some naive rules as:

iden = {{1, 0}, {0, 1}}; (* identity, leave all points unmoved *)

axisres[a_, b_] := {{a, 0}, {0, b}} (* axis rescaling *)

rot[th_] := {{Cos[th],-Sin[th]},{Sin[th],Cos[th]}} (* rotation *)

reflect = {{-1, 0}, {0, 1}}; (* reflection *)

shearleft[a_] := {{1, a}, {0, 1}} (* shear left direction *)

shearright[b_] := {{1, 0}, {b, 1}} (* shear right direction *)

However, when I do the following - only the identity works properly.

 image1 = {{0.1, 0.2}, {0.4, 0.5}};








I suspect it is some silly error, but I still do not see it. Why do these simple transformations not preserve the image and just perform their intended operation?

  • 2
    $\begingroup$ Those transformations are designed to work on the position of a pixel, that is its coordinates. Whereas the image data you are applying them to, is just an array of pixel intensities. $\endgroup$
    – wxffles
    Oct 3, 2016 at 3:28
  • $\begingroup$ So, I have to somehow use an image as opposed to the way I defined the image? Maybe easier, how can I get the transformations to do what I need? $\endgroup$
    – Moo
    Oct 3, 2016 at 3:32

2 Answers 2


What you want here is ImageForwardTransformation[]. For instance, to demonstrate rotation and shearing, we can do this:

lenna = ExampleData[{"TestImage", "Lena"}];

(* rotation *)
ImageForwardTransformation[lenna, RotationTransform[π/4], DataRange -> {{-1, 1}, {-1, 1}}]

Lenna rotated by 45°

(* shearing + translation *)
ImageForwardTransformation[lenna, AffineTransform[{{{1, Sqrt[3]/2}, {0, 1}}, {1/2, 0}}], 
                           DataRange -> {{-1, 1}, {-1, 1}}]

sheared Lenna

Note the use of a TransformationFunction[] (RotationTransform[] in the first case, and the more general AffineTransform[] in the second case) to perform the mapping, as well as the use of the DataRange option to specify the domain in which the image being transformed is embedded in.

  • $\begingroup$ I can certainly use the built in functions, but is there a way to get the naive variants that I posted to work? $\endgroup$
    – Moo
    Oct 3, 2016 at 3:48
  • $\begingroup$ As wxffles explained in a comment, performing affine transformations on an image is different from applying that same affine transformation to the array of graylevel/RGB intensities that make up an image. You certainly could try re-implementing ImageForwardTransformation[], but I'm not sure why you want to. $\endgroup$ Oct 3, 2016 at 3:53
  • $\begingroup$ Okay, I understand - thank you! $\endgroup$
    – Moo
    Oct 3, 2016 at 3:54

Just for completeness sake: You can use your own transformation functions, with ImageTransformation or ImageForwardTransformation, like this:

img = ExampleData[{"TestImage", "Clock"}];
ImageTransformation[img, rot[π/4].# &, DataRange -> {{-1, 1}, {-1, 1}}]

ImageTransformation[img, reflect.# &, DataRange -> {{-1, 1}, {-1, 1}}]

The second argument to ImageTransformation is a function that gets an xy coordinate pair in the destination image and returns a transformed xy coordinate pair in the source image.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.