Exploring Mathematical Transformations in Art through the Animated Cup Project
Dr. Tong’s AP Precalculus course at Concordia International School of Shanghai introduced an innovative transformational art project this academic year. Dr. Tong showed us multiple examples of transformational art, notably a Luycho-style animated cup and shadow art. I found the animated cup exciting and feasible (the projected animation), so I attempted to produce similar results, blending anamorphic illusions with physical artistry.
Research and Conceptualization
The project started with deep research into anamorphic illusions, where I learned how converting images from Cartesian to polar coordinates keeps them (mostly) undistorted on a cylindrical surface (a vertical flip of the image is first required). This transformation, known as polar coordinate transformation, became the heart of my project.
As a proof of concept, I used Photopea to manipulate a stock image of an apple and verified the theoretical application using 3D rendering in Fusion360. I discovered that reflective cylinders have a preferred viewing angle where the image is least distorted (higher = taller image, lower = shorter image).
Next, in order to understand how to add in the animated effects, I researched on barrier-grid animations. Apparently, this technique originated in the late 1890s and involves using a grid of barriers to control images reaching the viewer’s eyes (1 frame at a time). To create a barrier-grid animation, I would need to cut images into strips and interleave them in the way that once reflected onto the cup, one image could be seen at a time.
Ready for Action
To jump start the project, I bought a white mug that comes with printed reflective stripes. I noted down some basic measurements of my mug before starting to work on the animation pattern:
- The diameter of the cup varies from 69 to 87mm from bottom to top (slanted wall)
- The evenly spaced reflective stripes are 1mm in width each
- The spacing in between are 2mm at the top and 1.5mm at the bottom
For the saucer choice of my own Luycho-style animated cup, I searched our kitchen and chose three saucers/small plates of different steepness, hoping that one of them would work with the cup.
Challenges and Experimentation
As with any creative task, challenges arose during the experimentation phase. I first tried creating barrier-grid animations following YouTube tutorials using Adobe Photoshop, slicing images into strips to simulate movement.
Unfortunately my initial attempt with animated blinking eyes proved to be too intricate, with details such as the thin eyelashes getting blurry and lost in the transformation (as there were only two frames). This setback taught me the importance of selecting visual content that could withstand mathematical distortions and a low framerate while maintaining clarity.
Refinement and Mathematical Integration
Starting from scratch, I decided to opt for more straightforward, high-contrast images (silhouette) of a pigeon in two poses, hoping these will return apparent, distinguishable features that could easily align and transform.
Once I selected my new images, I utilized translation (shifting images to align precisely for interleaving) and dilation (adjusting image size to fit the cup dimensions precisely) through a few rounds of trial and error. This iterative process taught me how mathematical ideas directly influenced artistic decisions.
Automation Through Programming
To simplify the animation pattern creation, I decided to investigate developing Python program to automate the slicing and interlacing of images, instead of repeating the same tedious manual process in Photoshop. This could definitely save me time if I had to change the images yet again for any reason and would ensure a more seamless and accurate pattern.
With the help of a similar tool shared on GitHub, I was able to put together my own version of a simple Barrier-grid Animator that performs two primary functions:
- Image Slicing: The script reads two (or more) digital images and cuts each into vertical strips. These strips are defined by two parameters: the width of the transparent columns where parts of the image remain visible and the opaque columns where the image is masked.
# Load images
images = [np.array(Image.open(f).convert('RGB')) for f in files]
# Calculate total number of columns based on image width and column widths
slice_width = clear_width_px + opaque_width_px
step_size = slice_width * len(images)
final_width = (img_width // step_size) * step_size
- Interleaving Strips: After slicing, the script interleaves these strips from the two images in a precise sequence, ensuring the strips align correctly to create the desired animation effect when viewed through a moving grid of matching dimension.
interlaced = np.zeros((img_height, final_width, img_depth), dtype=np.uint8)
# Generate interlaced image
for i, img in enumerate(images):
# Crop each image to the final width
img = img[:, :final_width, :]
# Calculate where each slice will go in the interlaced image
for j in np.arange(slice_width):
# Place the slice in the interlaced image,
# skipping appropriately to create the interleaved effect
interlaced[:, ((i * slice_width)+j)::step_size, :] = img[:, j::step_size, :]
Also in this script, I implemented a dilation transformation where the widths of the transparent and opaque strips are converted from millimeters (as measured from my cup) to pixels (as required by software in image processing):
This conversion helps to ensure that the digitally created animation pattern will match my striped cup once printed.
# Open the first image to get the DPI and dimensions
# assume all images share the same size and resolution
with image.open(files[0]) as img:
dpi = img.info.get('dpi', (300, 300))[0]
img_array = np.array(img.convert('RGB'))
img_height, img_width, img_depth = img_array.shape
# Convert mm to pixels using the retrieved DPI
clear_width_px = int(clear_width * (dpi / 25.4))
opaque_width_px = clear_width_px * 2
In order to test my script to be functioning correctly, I printed out my auto-generated animation pattern on regular paper, and a matching grid overlay on a transparent PVC (plastic) sheet. After iterations of troubleshooting and bug-fixing, I finally got the animation working as expected in 2D!
Final Transformation and Artistic Realization
Time to move on to the last and most challenging yet rewarding step of the project — projecting the 2D pattern on a 3D surface. I decided to stick with Photopea’s cartesian-to-polar coordinate converter than implementing my own, as it tested it to be working in my prototyping. Before applying the final transformation though, I had to vertically flipped the animation, a reflection transformation that ensured its orientation matched the viewing perspective when applied to the cup (so that it wouldn’t appear upside down).
Playing with Photopea’s converter, I learned that to achieve the animated effect, polar coordinate transformation had to be applied meticulously to my animation pattern, so that
- it suitably integrates with the cup’s curvature, and
- the strips that make up the pattern align consistently with those reflective strips on my cup (both angle and width).
To accomplish these goals, I first aligned the center of my animation pattern (pigeon body) against the canvas used in the transformation (X-axis), so that once distorted, the stripes in the pattern would be angled symmetrically towards the center (like an unfolded fan). Next, I needed to make sure that the top of the pattern (feet of the pigeon) would be properly distanced from the edge of the canvas (Y-axis). This is apparently because the converter calculates polar coordinates relative to the middle of the top edge of the canvas.
Additionally, I found that the width and height of the canvas would affect the extent of the image distortion. To find the suitable dimensions for the canvas, I estimated the ideal segment of the cup’s circumference to cover to be 120–150 degrees, which is about 1/3 of a circle. Because of this, I decided to size the canvas to be about 3x the dimensions of the pigeon pattern. And to add to the complexity, angle or steepness of the saucer’s rim directly influences how the transformed image is perceived.
With the determination to overcome the imprecise nature of the project and achieve the desired effect, I ended up spending hours repeating the process of:
- creating polarized conversion
- printing and cutting out the distorted pattern
- fitting it on the saucers and testing against the cup
- observing and analyzing the encountered failure (and just to name a few examples: misaligned strips, mismatched curvature, broken animation etc.)
- recalibrating the various variables based on the analysis
- and, repeat…
Reflection on Challenges and Artistic Growth
Looking back on this project, I realized how mathematical transformations are commonly utilized in artistic design and it helped me to think creatively about visually representing abstract concepts. Despite the initial setbacks, challenges in alignment, and the remaining imperfection, even after extensive efforts, tweaking mathematical parameters to achieve artistic harmony was incredibly fulfilling.
Overall, this project was a testament to the connection between mathematics and art, reminding me of the delicate balance required to bring digital transformations to life on physical objects.
(And lastly, here is the nowhere-near-perfect-yet-could-be-close version for my transformational art project of a Luycho-style animated cup, for your amusement. :)