Construction of Generic Anamorphoses : A Step by Step Tutorial
Francesco De Comité |
Take me directly to the example !
A set of images mostly produced by this method
Abstract: Anamorphoses are distorted images needing to be seen from a special point of view , or to be reflected into a mirror in order to restitute the correct image. We describe an effective procedure, using a chain of several public domain softwares, for defining, testing and building generic mirror anamorphoses, where ’generic’ means :The method can be used to virtually render and test anamorphoses designs or to output a distorted image in any suitable image format (jpg, png…) that can be printed at any scale, in order to obtain a real size version of the anamorphosis.
- The mirror can have any ’reasonnable’ three-dimensionnal shape.
- The observer’s eye (the point of view) can be set anywhere.
Since the time of Early Renaissance, when artists and scientists discover the laws of perspective and optics, anamorphoses have been studied from several points of view : empirical and analytical[5][6].
Examples can be found for pinhole or planar anamorphoses, for example in Hans Holbein’s Ambassadors[1] or in the work of stree paining artists, like John Beever[3] and Kurt Wenner[4].
Other examples imply the use of conical or cylindrical mirrors, like in the works of István Orosz[2].
However, few has been done for anamorphoses using other types of mirrors (spherical, inverted cones1…), and less, if any, for anamorphoses using mirrors that are not easily described by mathematical formulae.
Even for the classical cases of cylindrical or conical mirrors, analysis often assume that the observer’s eye is placed at an infinite distance from the mirror.
We show that we can accurately approximate a distorted image to be seen into a general shaped mirror, from any observer’s position.
Section 3 defines a possible vision of what we call the Anamorphosis Principle.Then section 4 details the procedure through an example.
I assume that you know already Pov-Ray (but just how to launch the program), ImageJ (installing, putting new plug-ins and auxiliary classes into the right directory/package).
Knowledge of Java will help a lot too.
Figure 1 illustrates the principle behind our method :
Considering in turn each pixel Si of E, we can :
We then obtain on P the distorted image we were looking for. We must now collect the information of pixels Wi and reorder them if we want to obtain an image in some standard format (jpg,png…).
Figures 3 to 10 depict the complete procedure.
File anamorphoseTemplate.pov contains quite all the information for the scene description. You will also need the auxiliary file inclusions.inc
There are several parameters that can or must be set by the user. Most of them are at the beginning of the file :
// rendering=0 : first step --> computing the grid and outputting the coordinates data // rendering=1 : final step --> rendering the anamorphosis #declare rendering=1; // Controls the position of the screen between the eye and the mirror #declare boing=1.5; // Screen size (can be tuned for better overlap with the mirror). #declare hauteurEcran=1; // The position of the eye #declare visionPoint=<2,1,-5>; //The focus point #declare centreObjet=<0,1.5,0>; // appearance of the reflected grid #declare diamCylinder=0.028; #declare diamSphere=2.5*diamCylinder;
Two other lines of this file will have to be edited, but only at the end of the job (lines 149 and 220).
For this first step, you just set render to 0, and call Pov-Ray, also setting Debug_File=nameOfFile.txt : this file will contain all the information we need to build the distorted image.
If everything goes fine, you must obtain an image like figure 6.
You can play around with the parameters to obtain differents grids, at different resolutions, seen from different point of views (modify the description of the camera, at the end of file).
The mirror we choose is an inverted egg-shaped one. Figure 3 shows all the objects in the scene :
Figure 4 shows the same scene, from the observer’s point of view, i.e. as seen from the sphere of figure 3. Remark that, from this point of view, the screen is quite totally overlapping the mirror. More, the part of the mirror covered by the screen mainly reflects the plane. That means that the biggest part of the image will be visible in the mirror. This fact, i.e. setting the scene in such a way that the screen overlaps the part of the mirror that reflects the plane can be controlled by the user, by tuning variables inside the Pov-Ray description file, controlling both the size of the screen and its position relatively to the mirror and the observer’s point of view.
(Figure 3, figure 4, figure 5 and figure 8 were obtained from modified versions of file anamorphoseTemplate.pov, not directly through parameters tuning. )
At this point you can either take the file output by PovRay and use your favorite programming language to
compute the interpolation (and then come back to PovRay for visualization), or continue to follow this tutorial, using ImageJ.
Figure 5 illustrates the key concept of the method : rays are thrown from the observer’s eye, through selected points on the screen. Those rays hit the mirror and are reflected onto the plane. Considering all such reflections, we can draw a grid on the plane, which is the image of the points of the grid reflected by the mirror and reaching the plane.
Data concerning the coordinates of the intersection of rays and the plane are saved in a text file. Identifying images of squares, mapping squares to corresponding quadrilaterals, computing the transform relating each square to its image on the plane will be done through ImageJ, as the next step of the process.
Figure 6 shows how the distorted grid laying on the plane is seen from the observer’s point of view, when reflected in the mirror. It can be verified that this image is a very good approximation of the square grid. In fact, grid intersections are exactly at the right place (they would be hidden by the corresponding points laying on the screen). A close view would show that lines joining two adjacent grid points are not necessarily straight lines. Once again, this behaviour can be tuned, by controlling, through the Pov-Ray scene description file,the distance between two adjacent points on the grid : as this distance decreases, the distorted grid becomes more accurate. This would increase the scene computing time, but as this is not the bottleneck point of the whole process, we can easily afford this waste of time.
Now, go back to Pov-Ray, set rendering=1 (line 18). You might see now the final image. If it seems too blury, rerun anamorphTemplate.pov, setting rendering=0 (to re-produce the data file !), go back to Anamorph5.java, and tune parameters scaleb,mstepx,mstepy at the beginning of the class.
As the base image, we have chosen Leonardo da Vinci’s Gioconda, cut to a square (to conform to the screen’s shape). Mapping each square of the grid to its quadrilateral image on the plane divides the image into elementary squares. For each pixel of any of those squares, we compute the position of its reflection into the corresponding quadrilateral by linear interpolation, based on the transform mapping the square to the quadrilateral.
The resulting image, as produced by ImageJ, is shown on figure 7. Note that the distortion is not anecdotal : the resolution of the interesting part of the image will not be very good, some points are out of bounds, there also will be gaps between image pixels in the highly distorted parts of the image. Those are not real problems, as low definition parts of the image will lay on little mirror surfaces, hence imperfections would hardly be visible.
Figure 9 shows the mapping of the distorted image onto the plane, as seen from above the plane. The mirror is at the exact center of the picture. We still let the grid image, to show the good correspondance between this grid and the computed image. Due to integer rounding, there are some wrong pixels on the squares edges. Once again, those wrong pixels will not be visible on the final reflection, and could be corrected by interpolation with surrounding pixels.
Figure 8 is the same scene as in figure 9, as seen from the right place, for which the computations were performed, showing the validity of the procedure. Finally, figure 10 shows the expected result. All relative dimensions of the mirror, the image, and the position of the observer being known, one can in theory build a real size model of this render.
The method can handle any mirror shapes (as long as you can define the normal to the surface at each point of the mirror), but experiments with concave mirrors, and with mirrors where multiple reflections can occur are often giving very poor results : in those cases the transformed grid overlaps itself, and no "good" distorted image can be produced. Using the method to study more precisely those degenerated cases could lead to interesting results.
Did you successfully follow this ’tutorial’ till here ? Congratulations ! Please let me see your resulting render.
(You can also send me remarks of all type…)
This document was translated from LATEX by HEVEA.