LabyrinthMaker - You Go, You Get The Story, You Come Back
This work draws a single continuous path around an arrangement of objects, filling the environment around the objects completely, and binding them together into something sacred.
produced by: Isaac Clarke
I this work I have been exploring how wayfaring, pathfinding, and knowledge of an environment can be reimagined in the digitally rearranged and calculative landscapes we live in. I have been considering how objects are transformed into songs, and how symbols and objects teach us alternative ways of seeing, and alternative ways of living.
The work consists of an interactive table which calculates a single path which completely fills the space around an arrangement of objects, which can be removed and added to. This “watching” surface draws you in and then stops with you, presenting you with stillness and a journey that can be undertaken, to follow the path around these objects as they transform into something sacred and special. Through holding, seeing and creating journeys, I hope to show how we can reimagine our connection to the natural world.
Full source code: https://github.com/isaac-art/LabyrinthMaker
Photo and Video Documentation: https://www.dropbox.com/sh/x1ir01t795r16l6/AAAknGpLe3jFAxue-ewCb3xia?dl=0
Concept and background research
Labyrinths are not the same as mazes. In English the two are regularly muddled up together, but they present significantly different stories. In a maze there are dead ends and loops, you don’t know if you will end up lost forever, there is no clear direction and you left with confusion. A Labyrinth is almost the opposite. A labyrinth (or uni-cursal maze) has only one possibility, you follow the path and it leads you through the environment, safely to the end. You are bound to a particular story, to follow a path laid out before you. It is a lesson to be learned. You can’t go wrong in a labyrinth, and you will end up exactly where you are meant to be.
“knotting is the fundamental principle of coherence” – Tim Ingold
In past projects I have looked at braids and knots [https://github.com/isaac-art/BraidLab], and how they can hold information and tell stories [https://github.com/isaac-art/quipuMaker]. I am interested in Labyrinths for a similar reason, like knots, they are direct and self-explanatory. They appear confusing at a glance, but they are instead clear and coherent. They explain their own process in their form. They are programmes, they are calculative and computational. They are, like this world we live in, winding, textural, and ever-unspooling.
Earlier in the year I presented a research project on Esoteric Programming Languages [https://isaac-art.github.io//2017-11-11/Linguistic_Relativity]. The variety of dialects and designs allow us alternative ways of understanding computation. There have been studies that have shown a strong correlation between linguistic diversity and natural diversity, and I am interested in how variety of language allows us to see more of the world around us, to care for our environment as wholly as we can. The esoteric programming languages present to me the possibility of extending this diversity of knowing into a computational space, and through the 'calculative ambience' (Clough, P. (2015) Computational Aesthetics) of our world we can bridge that seeing and holding into a knowledge that can help us reimagine our connections to the natural world.
The need for art comes from a need to create new ways to explain to others what we know, or at least the knowledge we hold even if we don’t quite know it. There are ideas that can’t be said in one language that another communicates easily. Visual language, interaction, and calculation offer different ways into an idea. Recently I have been reading the poet Moya Cannon’s collection Hands [2011, Carcanet Press] in which her attentiveness to objects or situations transform them into something else. The last line of her poem Crater really captured this for me and was something I wanted the objects on my table to be doing too.
This is what apples are for,
to be turned into song.
Considering this, and the presence of the labyrinth iconography that would be in the work, I began to look into what Cannon calls “carrying the songs”. How the things around us carry their songs of being, and how we carry the songs of others how have been here before us.
In his PhD Thesis titled “Latin Labyrinths, Celtic Knots: Modernism and the dead in Irish and Latin American Literature” [2017, University of Iowa] Jacob Bender explores writers like James Joyce and Jorges Luis Borges and how their writing holds onto the voices of the dead as a political force, an idea that empowers and creates anxiety in the work. Joyce spoke about how his work was written in the form of the Celtic knot, an endless entanglement. In a similar way Borges took the form of the Labyrinth to explore death and infinity. Both writers absorbed those who had written before them and absorbed the forms themselves, meshes and woven tales, winding paths and corridors, and these forms held the stories in some kind of holographic totality.
A writer who I came across during this project who ties together my interested in all these multiple strands is Máirtín Ó Cadhain, whose book Cré Na Cille (Graveyard Clay) [1949, Sáirséal agus Dill] explores this labyrinthine-knotting of the voices of the dead as a “imagined political community” [Anderson, B (1983) Imagined Communities], Irish as a language that could see and say a different world being lived in and to be lived in (the presence of the dead undermining economic utility as social value), and the carrying of songs through language, behaviour, and iconography.
Labyrinths have been used to tell stories both as a setting and structure. Our story telling follows a repeated path, we begin, we journey to the underworld, we come back, we write it down, and the next person reads our words and they are taken on the same journey there and back again.
One last note on my desire to draw labyrinths would be my own coming into an awareness of knowing another in love and remembrance. In bereavement I have found a closeness and an entanglement that is endless, warm, and caring.
What’s true of labyrinths is true of course
Of love and memory. When you start remembering.
- Jack Spicer 2008
For this project I decided to use python so that I could develop my graphics programming skills in a different environment to openframeworks or processing. I wanted to push what I had already learned in other languages and really get a good understanding on opengl and opencv without all the addons provided in openframeworks.
The main set up was the camera processed into the labyrinth and draw on the screen each frame.
|Kinect Depth Camera -> opencv -> labyrinth mask -> recursive backtracker -> opengl -> glfw
|Kinect RGB Camera -> opencv -> opengl -> glfw
The Labyrinth Algorithm
I began searching for maze generation algorithms online, to generate a single path through a space. led me to a few different solutions.
The first possibility was using morphogenesis, replicating natural phenomena of reaction-diffusion to create paths. I was unsure about how well I could mask, the speed of the algorithm, and also not having straight lines. I think having straight lines in the labyrinth pushes us towards seeing it as calculated and digital, I wanted that break from something natural, although on reflection I would now be very interested to see my work using this algorithm.
The second was space-filling curves. These use a formula to draw a line through a space. My concern here was if I could mask an image, it seems that formula required would be very difficult to develop.
After looking into variations of path-finding algorithm, often used in robotics to navigate a space, I came across a book called Mazes for Programmers by Jamis Buck [2015, Pragmatic Bookshelf], a core developer of Ruby on Rails. This book explains maze generation algorithms, and importantly masked maze creation. It explains the difference in algorithms showing how they vary in speed and aesthetics. The book does not cover uni-cursal labyrinth generation, but it seemed a good place to start. I began porting the Ruby examples into Python, with occasional help from reading others who had already done this. The github user Kartones had code that was particularly helpful in translating the trickier parts on the edge of my Python knowledge and led me to a better understanding of the Python yield and generator expressions, as well as overriding the default functions of getting and setting lists. I found the type checking a little excessive so did without in my version.
Briefly, this algorithm works by building a grid of cells, we toggle cells active or inactive with the mask, and then run a recursive backtracker which travels across the cells joining them to neighbouring cells, this the gives us a list of connections we can draw. The recursive backtracker is important to use instead of another algorithm as is creates orthogonal “perfect” mazes, mazes in which there are no loops only dead ends.
My main contribution to this is creating the unicursal labyrinth. By adding in extra points to each cell, essentially splitting them down the middle, we can adapt an orthogonal maze into one continuous path (think how people say to find your way out of a maze keep your hand against one wall and follow it). I was very pleased that I was able to solve this in a way that still allowed me to make use of the masking.
From here I went on to convert the algorithm from taking one static image for a maze, and instead use a camera feed to constantly update the labyrinth. The immediate problem I faced was speed. The maze algorithm could take up to 10 seconds per frame, for a smooth interaction I would like it to be at least 20fps. By playing with image resolution and labyrinth cell size I could get this down to 1 frame per second, but I was hitting the limitation of the python image library drawing function. This is where I really saw the power of opengl, I converted the drawing function to instead return a list of pairs of points and then used opengl to draw and successfully had it running at an acceptable speed. I use the GLFW window manager to create a full screen window on the correct monitor on start up. I also wanted the drawing to pause when the interaction stopped, so I would store the last frame and compare it to the current one to see if the change was large enough and if not would not update the labyrinth just draw the same thing again. This also helped the frame rate as it would cut the incoming feed down to a lower refresh rate.
The next technical issue was stopping the image feeding back into itself. The camera would be pointed at a screen, so the objects sit on their own masked areas in the labyrinth. After attempting background subtraction I decided to move away from the pseyecam and instead use a Kinect, with which I could use the depth camera for masking at a set depth then use the rgb camera to fill in the colours of the selected areas. This worked very well.
My last issue was with homography, getting the image on the monitor to align with the camera. I used opencv to create a program to capture chessboard images and then calculate the distortion in the lenses of the Kinect cameras. I also added a gui for controlling the distortion of the image and mapping it into the dimensions required.
I was unable to solve the main kinect issue with the depth camera not mapping correctly to the 2d surface, so tall objects do not correctly align. Due to the relatively small interaction area it isn’t a big problem. There are c fixes for this available in openframeworks Kinect addon via the c version of libfreenect, but I haven’t been able to find a python version for the earlier model Kinect.
Design and Interaction
I decided quite early on that I would like something that looked museological, but also throwing that off a little. My design was of a white plinth, with the monitor facing upwards like a table top, a sheet of acrylic to protect the monitor and the camera overhead.
I also added wheels to the plinth as I wanted to try break up the monotony, adding the potential for it to be pushed around the space – even if it was just the suggestion of movement – would make it feel more approachable, under human control. I had an idea to hang the cables from the ceiling which would allow for some movement, but when it actually came to install I realised this would be visually confusing and overpowering, the cable would be very present. In the end you couldn’t really tell it was on wheels. Perhaps finding a lower power monitor and battery set up would be nice, then it could be portable.
More thought should have been made to the air flow for the monitor, as it trapped the hot air underneath I had to add holes around the edge of the plinth to keep it cool which disrupted the clean appearance.
Although I needed the depth camera for this to work I think it would look better without the mount on the side, I looked at potentials for other ways of finding the shadows of an object, in future versions I could instead use infrared leds around the edge of the monitor and then measure the changes in light to calculate the positions of objects on the surface, this would create a touch-screen-like surface that would look much cleaner.
I added some colourful shaped under the acrylic which had undergone various boolean operations, so they had a feel of some kind of language or instructions but also mirrored the light coming through the stained-glass windows of the church exhibition space. I also added a switch to the colouring of the labyrinth so it would change every 1500 seconds, I found after testing a few speeds this was a good moment to catch people and draw them in once again as the would not expect it.
The main consideration of the interaction for me is that it should firstly draw people in by being visually interesting, and then as they stop it should pause with them, prompting them to reflect on the objects, stepping and stopping.
Self evaluation and Future Development
Overall, I was pleased with the installation of the work, and it technically functioned as planned. I was disappointed that the interaction didn’t go quite as expected, people enjoyed the work and were willing to manipulate the arrangement of the objects but would often walk away before they realised it had stopped with them. This could be just the setting of this exhibition, but maybe adding other sensory triggering could be captivating. If there was an audio element to the work which also paused, then perhaps that jolt would feel more present.
Another key problem is that people find it difficult to see that it is one single path being drawn, and just see confusion of a maze. In some ways I like this, that upon closer inspection you discover the clarity, but I also think if that isn’t ever seen then there is a very different reading of the work. I added a line to the accompanying work information that mentioned the single path so hopefully that helped to reveal this important element of the work.
Having played with the straight lines quite extensively I would now like to go back to the reaction diffusion option and see if I can develop masking for that too. Animating the growth of the labyrinth may help clarify the single path.
I am also going to try static images. I think prints, or perhaps coil bound books, of a single arrangement of objects and the path around them would have the stillness in them already so people will approach with that stillness themselves.
Another possibility would be going the opposite way and scaling up. There are definitely architectural possibilities. This could be used on maps or floorplans to generate a path to be followed that is human size, with human sized or larger objects being masked. Using LED strips I could create also mimic the moving walls as on the screen. Perhaps a path that is created around all the other items in a museum or gallery or forest or ocean. That would be how I would like to exhibit this in the future.
My next big programming task I would like to attempt is to create my own programming language, that uses these woven/knotted/labyrinthine forms.
Even with those elements of the work that felt unsuccessful I feel I achieved what I set out to do. I feel very confident in using python, opencv, and opengl which I couldn’t say three months ago. The research into the structures and forms of storytelling, the dead as political allies, and the act of carrying the songs, has been very valuable to me and I believe it will be a continued subject in my work for some time.
Ingold, T (2007) Lines. Routledge.
Ingold, T (2015) The Life of Lines. Routledge.
Miller, A (2013) Speculative Grace. Fordham University Press.
Cadhin, M (1949) Graveyard Clay. Yale University. (Translated: Robinson, T. Mac Con Iomaire, L (2016) )
Cannon, M (2011) Hands. Carcanet Press.
Borges, J.L. (1962) Labyrinths. New Directions.
Joyce, J (1914) The Dead. Grant Richards Ltd.
The Labyrinth Society (1998) The Labyrinth Society - About Labyrinths. URL: https://labyrinthsociety.org/about-labyrinths Accessed: 17/09/18
Gorenflo, L.J. Romaine, S. Mittermeier, R.A. Walker-Painemill, K (2012) Co-occurrence of linguistic and biological diversity in biodiversity hotspots and high biodiversity wilderness areas. Proceedings of the National Academy of Sciences of the United States of America (PNAS).
Clough, P.T. (2015) Computational Aesthetics in the Practices of Art as Politics. The Routledge Companion to Art and Politics. Routledge.
Spicer, J. (2008) "Any fool can get into an ocean...". Poetry Foundation. URL: https://www.poetryfoundation.org/poetrymagazine/poems/51258/any-fool-can-get-into-an-ocean- Accessed: 17/09/18
Anderson, B (1983) Imagined Communities: reflections on the origin and spread of nationalism. Verso.
Bloom, H (1997) The Anxiety of Influence: A Theory of Poetry (2nd Edition). Oxford University Press.
Wan, L. Liu, X. Wong, T. Leung, C. (2007) Evolving Mazes from Images. IEEE Transactions On Visualization and Computer Graphics.
Buck, J (2015) Mazes For Programmers. Pragmatic Bookshelf.
Kartones (2017) mazes-for-programmers-python-src. [Python Code] URL: https://github.com/Kartones/mazes-for-programmers-python-src Accessed: 17/09/18
OpenCV (2014) OpenCV-Python Tutorials. URL: https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_tutorials.html Accessed: 17/09/18
Bradski, G (2000) The OpenCV Library. [Version 3.4.3] URL: https://docs.opencv.org/3.4.3/ Accessed: 17/09/18
skvark (2017) opencv-python. URL: https://github.com/skvark/opencv-python Accessed: 17/09/18
OpenKinect (2010) libfreenect. URL: https://github.com/OpenKinect/libfreenect Accessed: 17/09/18
GLFW (2006) Graphics Library Framework. URL: http://glfw.org Accessed: 17/09/18
Khronos Group (2006) OpenGL. URL: https://opengl.org Accessed: 17/09/18
bensondaled (2017) pseyepy. URL: https://github.com/bensondaled/pseyepy Accessed: 17/09/18
Secret Labs AB (2009) Python Imaging Library (PIL). URL: http://www.pythonware.com/products/pil/ Accessed: 17/09/18
Numpy Developers (2006) Numpy. URL: http://www.numpy.org/ Accessed: 17/09/18