People have always been fascinated by visual illusions. Artists have been using them to trick our brain and question our perception of reality, vision scientists have been using them to study and reveal the fundamental mechanisms and limitations of the visual system. This unique position between art and science makes them particularly appealing and suitable as teaching tools. One can reverse-engineer a visual illusion using mathematics to describe its constituting parts like patterns, shapes and colors and how they combine to create the more complex geometric composition that fool the eye. Reverse-engineering an illusion can also provide invaluable insight about its inner working (its intrinsic nature and basic mechanisms) and the means to develop the scientific tools to study the factors that influence the strength of the illusory effect.

In this tutorial, we are going to illustrate this approach by showing how to reverse-engineer a striking visual illusion using basic math (no more than high school level, promise!) and build an iGLWidget to let you further explore how this illusion works.

Case study: motion induced by the peripheral drift illusion

As a case study we picked up the illusion shown below. It has everything a vision scientist likes: it is reasonably complex but tractable, gives a strong sense of illusory peripheral motion, and consists of strong visual cues like contrast, color and depth.

EbOJLbfWkAAL0JG

This image can be found on various stock image websites and is credited to Yurii Perepadia, a prolific Ukrainian illustrator and graphic designer who uses Adobe Suite to create his illustrations. He described this one as "Abstract turned frames with a rotating purple yellow wavy pattern". Like for many of his illustrations, Perepadia created the appearance of motion by using an effect studied by Akioshi Kitaoka, a professor of psychology at Ritsumeikan University in Osaka, Japan, and at the basis of his famous "Rotating snakes" illusion: the peripheral drift illusion (PDI). This class of illusions is characterized by the perception of illusory motion when an otherwise static pattern is presented in the peripheral vision while being perceived as motionless when presenting in the center of the visual field. You may notice that the induced illusory motion is particularly strong when exploring the stimulus through eye movements, while it will slow down or even disappear if you are able to stabilize your gaze for a few seconds (this can hard to do though).

Reverse-enginering the illusion

We are going to literally cut this illusion apart to describe its anatomy and try to understand how it works. But no worry, we are not going to use any dangerous tool like scalpel blade, forceps or scissors, but just plain math… and our Psykinematix software. As a reminder, custom stimuli created in Psykinematix can be expressed as a function of up to 4 spatial coordinates (in addition to time, which will not be used here since there is actually no moving part in this illusion):

z = f( x ,y, r, theta, time)


where (x, y) are the Cartesian coordinates and (r, theta) are the polar coordinates of each pixel P of the stimulus (x being its horizontal position relative to the center O, y its vertical position relative to O, r its distance to O, and theta the angle defining its counterclockwise direction relative to the x axis). z is simply the evaluation of the f () function as a 2D output between 0 and 1 to represent the normalized luminance of each pixel. For colored pixels, we will use outputs designated zr, zg and zb also between 0 and 1 to represent the normalized luminance of its red, green and blue chromatic components. For f (), we will only use a combination of basic mathematical functions like arithmetic operations, trigonometric functions, and comparison operations, as well as a number of intermediate variables. Note that while using both Cartesian and polar coordinate systems is redundant to express the pixel location, they can be handy to describe different components of this stimulus as we will see later. Coordinates Systems
Note that you may also use any other computational tool able to evaluate such 2D mathematical expressions (like Mathematica, Matlab or Python for example). However we will use here the Pro Edition of Psykinematix to automatically generate at the end of this tutorial an HTML5 widget (or iGLWidget ) so you can control the effect of various parameters on this illusion.

This complex pattern is made of various components whose contribution for the strong illusory motion may be difficult to discern at first. The pattern can be summarily described as yellowish "tentacles" on a purple background spreading in the radial direction and uniformly spaced in the angular direction, and split into 3 different depths seen through 2 central squarish windows rotated and increased in size. Let's describe mathematically each of those components.

Spatial pattern

First let's focus on the main spatial feature of this illusion: its 24 sprawling components uniformly spaced by 15 degrees (360/24). The simplest expression to create this basic distribution is a sinusoidal luminance grating in the angular direction as illustrated below:

5FE2983A-DD04-48A8-B961-BE7CD153E7E8 Math for sinusoidal luminance angular grating

where theta indicates the angular position and af expresses the number of wedges per circumference (or angular frequency). phi is an optional angular phase parameter to rotate the whole pattern by some arbitrary angle. With Psykinematix, you simply need to enter this expression in the custom stimulus section to see what the stimulus looks like and how its appearance is affected when changing the value of the parameters.

The curvature of these "tentacles" can be modulated by applying some clever value to the phi parameter. For example replacing phi with the radial position of each pixel (i.e. the variable r) produces an angular shift that grows linearly with the radial direction (i.e. away from the pattern center) hence forming a spiral distortion of the tentacles as illustrated below.

unknown Math for Spiral

Wiggles along the radial direction (i.e. with angular shifts alternating between positive and negative values, or left and right) can be created with a sinusoidal modulation of the angular shift as a function of the radial position r :

Wiggles Math for Wiggles

where sf is the spatial frequency of the wiggling along the radial direction (the higher this value the smaller the distance between 2 consecutive wiggles).

Color sequence

If one inspects carefully each tentacle, one would notice that the color modulation in the angular direction is not continuous but rather consists of 6 discrete colors that alternate in a cyclic manner with the following r,g,b coordinates: black (0, 0, 0), dark orange (0.8, 0.7, 0), light orange (1, 0.9, 0.3), almost white (1,1,0.9), light purple (0.6, 0.2, 0.7) and dark purple (0.4, 0, 0.6).

Color Sequence Zoom

While the sinusoidal luminance grating we used above provides a first approximation of the tentacles shape, it cannot account for the luminance and color variation in the pattern: a sinusoidal wave alternates smoothly from dark, grey, white, and grey again in a cyclic manner. To account for the original pattern, one needs to create 6 unique colors which cannot be obtained from a one-to-one mapping of a sinusoidal cycle. One should instead consider a sawtooth modulation function giving 6 discrete indices (0, 1, 2, 3, 4, and 5) which can then be used to specify each color (e.g. 0 for black, 1 for dark orange, 2 for light orange, 3 for white, 4 for light purple and 5 for dark purple).

As illustrated below, such a colorful sawtooth function can be simply produced by applying the modulo operation mod() along the direction of color change (the x axis in this example) and comparing the result of this operation to an index used to select the (r, g, b) components of the associated color:

Color Sequence Math for color sequence

where w is a parameter to set the width of each colored band. Note that for each given pixel, only one of the variables lev* takes a value of 1 and all other variables lev* take a value of 0, so the output variables zr, zg and zb will always be set to one of the 6 picked colors for each pixel. We will refer to this selection technique as the index-based color picking.

One can replace the sinusoidal function with a sawtooth function to produce a similar tentacular pattern which is more appropriate for the above color picking:

Polar Sawtooth Math for polar sawtooth

One could note that this is very similar to the basic pattern found in one of the first studies that discovered the peripheral drift illusion: the basic illusory motion can be simply generated with a sawtooth luminance grating presented in the visual periphery (Faubert and Herbert, 1999).

The wiggling can be produced similarly to above by incorporating a sinusoidal modulation of the angular shift as function of the radial position:

Polar Sawtooth Wiggling Math for Polar Sawtooth Wiggling

We finally obtain the colorful wiggling tentacles by applying a sampling with 6 levels on the luminance profile of this sawtooth modulation and the index-based color picking:

Colorful Polar Sawtooth Wiggling Pasted Graphic 9

Congratulations if you are still there, the most difficult part is done! Now let's move on to the square windows.

Spatial envelopes

In the original illustration, the above tentacular pattern appears to be replicated at different depths seen through 2 see-through square windows.

A square can be simply created by checking whether both x and y positions are within its border (where the variable winsize denotes here the length of its sides):

Simple Square Math for simple square

The smallest and deepest square in the original illustration is actually rotated by 45 deg (phi variable). This transformation can be obtained by applying the standard formulas for rotating the x-y axes:

Rotated Square Math for rotated square

The largest and closest square is about twice larger and rotated by about 20 deg (outphi variable). The middle depth plane is simply this larger window (outenv) minus the smaller one (inenv):

Windows Math for the windows

If you look closely at the borders of the see-through windows in the original image, you will notice that the order of the color sequences of the tentacles in the middle depth plane is inverted compared to the inner and outer ones which may further enhance the strength of the illusion through the creation of antagonism illusory motion:

black (0)black (0)
dark orange (1) dark purple (5)
light orange (2) light purple (4)
white (3)white (3)
light purple (4)light orange (2)
dark purple (5)dark orange (1)
Color Order Changes

Those index changes can be computed with the following sub-expression:

mod(nblevels-levels,nblevels)


This color order inversion is then only applied to the middle depth plane using the above mask when computing the color indices:

Windowed Colorful PolarS awtooth Wiggling Math for Windowed Colorful Polar Sawtooth Wiggling

We are almost there ! Something is however still missing: the perception of depth…

Depth

Depth perception can be typically enhanced by the presence of shadows. But shadows alone can also provide strong depth cues. Here one would expect the windows borders to cast some shadow (penumbra) on the patterns behind them. Shadows can be created simply by darkening the stimulus luminance inside the edges of the windows (for simplicity here, we are only assuming some ambient lightning and no directional light source). Realistic shadows should also smoothly attenuate with the distance from the edges.

This can be simulated through a linear increase of the luminance modulation as function of the distance to each edge as illustrated below, where the amount of shadowing is controlled by a single parameter sw that specifies the spatial extent of this modulation (i.e. how far from the edges it spreads):

Single Shadow Math for single shadow

Let's apply this shadow on a single windowed view of our wiggling stimulus:

Single Shadow Windowed Stimulus Math for Single Shadow Windowed Wiggling

We have now a much more convincing perception of depth !

The same technique can apply to the 2 inner and outer rotated windows:

Shadowed Windows Math for Shadowed Windows

Then we finally obtain a stimulus very similar to the illustration created by Yurii Perepadia:

Shadowing Windowed Colorful Polar Sawtooth Wiggling Math for Shadowing Windowed Colorful Polar Sawtooth Wiggling


Widget

Here is the final mathematical expression:
		# Useful pre-computation for some parameters
inphi = 45*pi/180
sw = shadow/100
w = 2*pi/af
# Spatial pattern: wiggling tentacles
wiggling = nblevels*(theta+cos(2*pi*sqrt(sf*r))*w/4)
# Rotated inner and outer square windows
xroti = (x*cos(inphi)+y*sin(inphi))/winsize
yroti = (-x*sin(inphi)+y*cos(inphi))/winsize
inenv = abs(xroti)<1/2 & abs(yroti)<1/2
xroto = (x*cos(outphi)+y*sin(outphi))/winsize
yroto = (-x*sin(outphi)+y*cos(outphi))/winsize
outenv = abs(xroto)<1 & abs(yroto)<1
# Luminance discretization
levels = mod(floor(wiggling/w),nblevels)
# Selection of middle depth plan
window = outenv - inenv
# Color picking with inversion for middle depth plan
lev = levels*window + mod(nblevels-levels,nblevels)*(1-window)
lev0 = lev==0; lev1 = lev==1; lev2 = lev==2 ; lev3 = lev==3; lev4 = lev==4; lev5 = lev==5
zr = 0.0*lev0 + 0.8*lev1 + 1.0*lev2 + 1.0*lev3 + 0.6*lev4 + 0.4*lev5
zg = 0.0*lev0 + 0.7*lev1 + 0.9*lev2 + 1.0*lev3 + 0.2*lev4 + 0.0*lev5
zb = 0.0*lev0 + 0.0*lev1 + 0.3*lev2 + 0.9*lev3 + 0.7*lev4 + 0.6*lev5
# Shadows
inshadow = inenv*0.5*(clip(abs(abs(xroti)-0.5)/sw,0,1)+clip(abs(abs(yroti)-0.5)/sw,0,1))
outshadow = outenv*0.5*(clip(abs(abs(xroto)-1)/sw,0,1)+clip(abs(abs(yroto)-1)/sw,0,1))
shadowmod = inshadow + (1-inenv)*outshadow + (1-outenv)
# Final result
zr = zr*shadowmod
zg = zg*shadowmod
zb = zb*shadowmod
Now that we have a complete mathematical description of the illusion, we can create an HTML5 widget. With Psykinematix Pro Edition, creating a widget is easy and can be done in 4 simple steps:

1) you specify which parameters should be controllable, their labels, the range of the values available from their slider controls and their units. This can be specify by adding some metadata after the default value of each parameter (following the # symbol) as highlighted below:

CustomParametersHighlightedMetadata

2) then control-click on the preview and select the GLSL export option "HTML5 Widget",

WidgetExport

3) finally you enter in the widget configurator panel the optional detailed information to appear in the back side of the widget,

Widget Configurator

4) and click the "Export" button to produce a ready-to-use HTML5 widget that can be shared with others either online or offline on any platform.

And here it is the iGLWidget for this illusion exported from Psykinematix Pro Edition that lets you play in real-time with some of its parameters. You will notice that we added 2 parameters, saturation and contrast. We leave their implementation as an exercise, but you can find the solution somewhere in the back side of the widget below… Enjoy !


This widget will be part of our second set of iGLWidgets to be released soon, which will be dedicated to some classical visual illusions. To learn more, feel free to explore our public iGLWidgets Collection for Vision Science.

If you have any comment or question about this tutorial, please post them in the comments section on our Psykinematix Twitter account or Facebook group or private message us from there !

William H.A. Beaudot
KyberVision Japan LLC (Sendai, Miyagi)

References

Fraser & Wilcox (1979) Perception of illusory movement. Nature 281:565–566


Faubert & Herbert (1999) The peripheral drift illusion: A motion illusion in the visual periphery. Perception 28:617–621


Kitaoka & Ashida (2003) Phenomenal characteristics of the peripheral drift illusion. Vision (15):261–262



Publish Date: 31 August 2020

UA-20124358-1