1
$\begingroup$

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?

$\endgroup$
  • 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 '16 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 '16 at 3:32
5
$\begingroup$

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.

$\endgroup$
  • $\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 '16 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$ – J. M. is away Oct 3 '16 at 3:53
  • $\begingroup$ Okay, I understand - thank you! $\endgroup$ – Moo Oct 3 '16 at 3:54
6
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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