Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inside-out image transform

After exploring the very excellent answer from Heike to my previous question about anamorphic transformations, I eventually wanted to see an image turned inside out completely.

The idea is that, instead of just stretching the image out with an anamorphic transform, like you're pulling the edges of the paper around, you can actually turn the paper 'inside out'. The inside 'pixels' will be pulled out to the edges (greatly distorted/stretched), while the outside pixels will be squashed inwards towards the centre (greatly shrunk).

I can't illustrate it, but another way of trying to describe it is in this picture:

inside out image transform

so, the more red the pixels are, the more they are transformed to the edges (and vice versa).

I tried FindGeometricTransform, but it didn't seem to lead anywhere.

findgeometrictransform

It's not been easy to google for this, and I've yet to find any clues in Mathematica that such a destructive transformation is possible. It's kind of a 2.5D re-projection.

What do you think? Is it possible?

Edit

So thanks to your great answers I can now illustrate my question properly:

Here's Leonardo's famous Anom Asil, the result of subjecting poor Lisa to the inside-out transform ():

introverted mona lisa

and here's the Prague Orloj:

inside out clock

Practical uses for this will be forthcoming, er, soon...

Thanks!

like image 262
cormullion Avatar asked Nov 25 '11 14:11

cormullion


2 Answers

Perhaps something like this:

f[x_, y_] := {x, y} (1/Norm@{x, y} - 1);
GraphicsGrid[{{ 
       p = Rasterize[Graphics[ {Black, Disk[{0, 0}, 5],
                                Red,   Disk[{0, 0}, 3],
                                Blue,  Disk[{0, 0}, 2]}]],
       ImageTransformation[p, f[#[[1]], #[[2]]] &, 
                           DataRange -> {{-1, 1}, {-1, 1}}]}}, 
       Frame -> All]

enter image description here

Edit

Using Heike's fthe function is bijective, and it's own inverse:

f[x_, y_] := {x, y} (1/Norm[{x, y}, Infinity] - 1);
g[x_]:=ImageTransformation[x, f[#[[1]], #[[2]]] &,DataRange ->{{-1, 1}, {-1, 1}}]

GraphicsGrid[{{i, g@i, g@g@i}}, Frame -> All]

enter image description here

Edit

Setting:

f[x_, y_, t_] := {x, y} ((1/Norm[{x, y}, Infinity] - 1 ) t + (1 - t));

enter image description here

like image 173
Dr. belisarius Avatar answered Sep 30 '22 05:09

Dr. belisarius


If the native transform functions do not accommodate this in a single pass, you could probably get what you want by converting the image to polar coordinates, then inverting the radius data. Hopefully Heike will be along shortly to fix you up. ;-)


Against my better judgement, here is my rough and nasty code as an example. Zero oversampling, poorly conceived, magic numbers, and generally useless. But, belisarius asked for it, and here it is!

Starting with img = this image:

enter image description here

dat = ImageData[img];

atan2[0., 0.] := 0
atan2[a_, b_] := ArcTan[a, b]

coords = Array[
   Round@{# Cos[#2], # Sin[#2]} + 144 &[(144 - Norm[{#, #2}]), 
       atan2[#2, #]] &[N@#, N@#2] &, {289, 289}, -144];

Image@Apply[dat[[##]] &, coords, {2}]

Yields this pixellated atrocity:

enter image description here

like image 41
Mr.Wizard Avatar answered Sep 29 '22 05:09

Mr.Wizard