17
$\begingroup$

We have all see these sidewalk and street images that appear to be 3D based on the viewers perspective, but then wildly distort when viewed from a different perspective.

Proper perspective Art

Wrong Perspective Art

Seems to me anamorphic distortion like this would be something Mathematica could do quite easily, but see only manual methods being used when searching the webs for instructions. Given that simple triangulated perspective would work, the variables would be viewing height, viewing distance and size of the actual chalk drawing. That would produce the triangle needed for distorting the perspective.

So for those variables the average US male is 5'9.5" and the viewing distance of 10 feet and the size of the projected image would be 20 feet tall.
Captain America Using the above normal perspective image image, how can Mathematica be used to create a distorted version that would view properly using the variables of viewer height, distance and viewing angle?

Here is an example done in Photoshop of the Captain America image that has been perspective distorted to appear correct when placed on the ground, by a person who's 5'10" and is 10 feet away

enter image description here

$\endgroup$
2
  • 6
    $\begingroup$ related: QR Code in shopping cart handle $\endgroup$
    – Kuba
    Feb 15, 2017 at 18:14
  • $\begingroup$ @Kuba Basically, it is a duplicate as the method behind it is exactly the same. $\endgroup$
    – halirutan
    Feb 17, 2017 at 21:10

2 Answers 2

18
+100
$\begingroup$
h = 6.0;  (* eye height *)
h0 = 4.0;  (* apparent image height *)
d = 10.0;  (* apparent image distance *)
a = d h0/(h - h0);  (* actual length of painting *)

The geometry is like this:

enter image description here

Now do the transformation.

myimage = ImageResize[Import@"https://i.stack.imgur.com/k78e8.jpg", Scaled[1/5]];

f[{x_, y_}] := h/(h - y) {x, d}

w0 = h0 Divide @@ ImageDimensions[myimage]
(* 3.20667 *)

i = ImageForwardTransformation[myimage, f,
   DataRange -> {{-w0/2, w0/2}, {0, h0}},
   PlotRange -> All, Background -> White];

b = a Divide @@ ImageDimensions[i]
(* 4.81791 *)

The resulting transformed image i:

enter image description here

Using Mathematica's 3D graphics we can paint the transformed image on the ground and view from the appropriate point:

Graphics3D[{Table[{Orange,
    Cylinder[{{-b/2, y, 0}, {-b/2, y, 1}}, 0.1],
    Cylinder[{{b/2, y, 0}, {b/2, y, 1}}, 0.1]}, {y, d, a + d, 2}],
  Texture[i],
  Polygon[{{-b/2, d, 0}, {-b/2, d + a, 0}, {b/2, d + a, 0}, {b/2, d, 0}}, 
   VertexTextureCoordinates -> {{0, 0}, {0, 1}, {1, 1}, {1, 0}}]},
 ViewVector -> {{0, 0, h}, {0, (d + a)/2, 0}},
 ViewAngle -> 0.5, Lighting -> "Neutral", Boxed -> False]

enter image description here

$\endgroup$
6
  • $\begingroup$ Very good answer! Missing the viewing angle variable, but otherwise correct! $\endgroup$ Feb 18, 2017 at 12:15
  • $\begingroup$ @RHall I'm not sure what you mean by viewing angle $\endgroup$ Feb 18, 2017 at 12:20
  • $\begingroup$ so for example if the surface the new image is placed on it angled differently than say ground level. Like a ramp which angles up and away, or a wall that angles away from the viewer. $\endgroup$ Feb 18, 2017 at 12:24
  • $\begingroup$ @RHall in that case I think the same approach should work but you'll need to adjust the transformation function f. $\endgroup$ Feb 18, 2017 at 13:57
  • 1
    $\begingroup$ This just in...ImageForwardTransformation is now broken, confirmed by MMA Support Sept 2017 $\endgroup$ Oct 13, 2017 at 15:41
17
$\begingroup$

Yes. Simply use: ImagePerspectiveTransformation[]

myimage = Import@"https://i.stack.imgur.com/k78e8.jpg";

For example, define myimage to be your image. Then:

ImagePerspectiveTransformation[myimage, TransformationFunction[( \!\(\*
TagBox[GridBox[{
{"0", "1", "0.5"},
{"2", "0.5", "0.1"},
{"2", "0", "1.5"}
},
AutoDelete->False,
GridBoxDividers->{
        "Columns" -> {{False}}, "ColumnsIndexed" -> {-2 -> True}, 
         "Rows" -> {{False}}, "RowsIndexed" -> {-2 -> True}, 
         "Items" -> {}, "ItemsIndexed" -> {}},
GridBoxItemSize->{
        "Columns" -> {{Automatic}}, "ColumnsIndexed" -> {}, 
         "Rows" -> {{Automatic}}, "RowsIndexed" -> {}, "Items" -> {}, 
         "ItemsIndexed" -> {}}],
#& ]\) )]]

enter image description here

The way to set the geometry for a given viewing position is illustrated here (see Seeing the light: Optics in nature, photography, color, vision and holography by Falk, Brill and Stork): the height of the viewer's eye is given by the top of the right vertical line, a C. Draw a straight line from that point through the right of the base of the transformed image and then continue to the bottom left and use a straightedge accordingly. When viewed from that upper right point, the picture will appear undistorted.

enter image description here

$\endgroup$
2
  • 3
    $\begingroup$ @corey: I recommend you wait more than two (yes, literally two) minutes to judge an answer, as answerers typically take some time to fill out a full answer. $\endgroup$ Feb 15, 2017 at 18:39
  • $\begingroup$ how would this solution allow for the variables of observer height, viewing distance and angle as mentioned above to provide the viewer with an accurate image from their perspective? $\endgroup$ Feb 15, 2017 at 18:53

Your Answer

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

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