As we’ve seen, the Arduino sketch uses massive tables of precomputed stuff. These tables are generated with a script written in Python, using image files as inputs.
To generate new tables, you need some familiarity with Python and command-line script usage. Your computer must have Python installed, plus the Python Imaging Library. That’s going to vary on different systems and is beyond the scope of this guide, but Googling will turn up some getting-started resources.
So we’re singing from the same page, let’s lay out some eye terminology…
The “white” of the eye is known as the sclera. The iris is the muscle that contracts to adjust the size of the pupil in response to light. The upper and lower eyelids are involved in blinking. |
Eyes are weirder than you might think. They’re not simply football-shaped, they’ve got two lids, and the pupil and eyelids interact. The Arduino sketch takes a few shortcuts, but makes an effort at simulating these effects.
The Python script (located in the “convert” folder from the Github repository) — tablegen.py — takes six or seven images (corresponding to eye parts above) as inputs and generates a table for each. There’s also an array that it generates on its own — it precomputes and stores a bunch of trigonometry. The output can be redirected as a .h file and used with the Arduino sketch.
Let’s look at the defaultEye images (included in the convert/defaultEye directory):
To recreate the defaultEye.h file, you’d go the “convert” directory and enter this command (as a single line):
python tablegen.py defaultEye/sclera.png defaultEye/iris.png defaultEye/lid-upper-symmetrical.png defaultEye/lid-lower-symmetrical.png defaultEye/lid-upper.png defaultEye/lid-lower.png 80 > defaultEye.h
The eye images must be specified in the order: sclera, iris, symmetrical upper lid, symmetrical lower lid, asymmetrical upper lid, asymmetrical lower lid. The iris diameter (80 pixels in this example) is specified next. Then the output is redirected to the file “defaultEye.h” (you’ll want to give your own eyes different names). Check the contents of this file after running the script…any error messages will be at the end.
The resulting file can then be moved to the “graphics” folder within the “uncannyEyes” directory.
Add an #include line for whatever name you’ve assigned it. Compile and upload to the Teensy board and see what you get!
A couple of eye designs (dragon and goat) have strange pupil shapes. In this case, one more argument can be added, the filename of a “pupil map” image that assists this code in generating certain tables. Images for these are located in the corresponding directories. For example:
python tablegen.py dragonEye/sclera.png dragonEye/iris.png dragonEye/lid-upper-symmetrical.png dragonEye/lid-lower-symmetrical.png dragonEye/lid-upper.png dragonEye/lid-lower.png 160 dragonEye/pupilMap.png > dragonEye.h
There are size limits to all these images. Sclera and iris images require two bytes per pixel. Eyelid images are one byte per pixel. Additionally, a lookup table equal to the iris size (80x80 pixels in the defaultEye case) requires two bytes per element.
160x160x2 + 256x64x2 + 128x128 + 128x128 + 80x80x2 = 129,536 bytes.
The code requires a little over 50K, so the resulting total compiled sketch size is about 182K, well within the 256K flash space of the Teensy. The dragon eye, with its large iris, pushes much closer to the limit. Do a little math before investing a lot of time in a new set of images, to make sure it’ll fit in the available space.