# Images and Linear Transformations

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

Image[image1]

Image[image1.iden]

Image[image1.axisres[1,2]]

Image[image1.rot[Pi]]

Image[image1.reflect]

Image[image1.shearleft[.2]]

Image[image1.shearright[-.2]]


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?

• 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. – wxffles Oct 3 '16 at 3:28
• 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? – Moo Oct 3 '16 at 3:32

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


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


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.

• I can certainly use the built in functions, but is there a way to get the naive variants that I posted to work? – Moo Oct 3 '16 at 3:48
• 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. – J. M. is away Oct 3 '16 at 3:53
• Okay, I understand - thank you! – Moo Oct 3 '16 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.