Authors: Julien Gachadoat and Guillaume Lagarde.
A companion paper is available here.
Generative art systems often involve high-dimensional and complex parameter spaces in which aesthetically compelling outputs occupy only small, fragmented regions. Because of this combinatorial explosion, artists typically rely on extensive manual trial-and-error, leaving many potentially interesting configurations undiscovered.
We introduce ParamExplorer, an interactive and modular framework inspired by reinforcement learning that helps the exploration of parameter spaces in generative art algorithms, guided by human-in-the-loop or even automated feedback.
ParamExplorer requires Python installed on your computer and a web browser to run the tool.
ParamExplorer is built around two components :
- A client interface that is built with HTML / CSS / JavasScript using p5js and a custom UI library.
- A python server that takes requests from the client for various tasks :
- serving webpage for the client interface.
- computing parameters for your algorithm using various strategies in the field of reinforcement learning.
You can clone or directly download a zipped folder of the project.
First we are going to create a virtual environment for the server. In a terminal type the following commands :
# Replace [path] with the appropriate location on your system
cd [path]/param-explorer python -m venv .venvThen activate the virtual environment :
MacOS / Linux
source .venv/bin/activateWindows
.\.venv\Scripts\Activate.ps1Once the virtual environment is activated, install the project’s dependencies listed in the requirements.txt file:
pip install -r requirements.txtThat's it ! You should be able to run the server now.
python ./server.pyIf everything went fine, you should be able to open http://127.0.0.1:3001 on your browser and navigate into the examples.
The first step is to duplicate the examples/__template__folder, that contains only two files ìndex.html and sketch.js in a typical p5js file architecture.
sketch.js is the main script that contains one variable to change and a few mandatory functions to be implemented.
First of all, you have to change the value USER_SKETCH_ID variable that will be used by ParamExplorer to save some informations on client side through localStorage API of the browser.
const USER_SKETCH_ID = 'your_project_id';The ParamExplorer framework is going to call setupArtwork() and drawArtwork() functions each time it generates a new set of parameters. This is where you are going to put the logic that is usually set in the setup()and draw() functions.
// if newSeed if set to true, user has to generate a new seed
function setupArtwork(newSeed=false)
{
if (!p5RandomSeed || newSeed)
p5RandomSeed = int(Math.random(100000));
randomSeed(p5RandomSeed);
}
// sketch is an instance of p5
function drawArtwork(sketch)
{
sketch.background("#000");
// ...
}Once this is done, you will have to implement the variables you want to expose in the paramExplorer instance declared in the setup() function. For the moment ParamExplorer handles three parameters types : float, ìnteger and choice.
Each parameter should be declared with some additional properties :
float,integerrangeis anArraydescribing the minimum and maximum values the parameter can take.objis optionnal and refers to the object holding the variable. If not set, it will be default to globalThis.
choicechoicesis anArrayof integers holding possible values for the parameter, typically an enumeration.obj(optionnal) refers to the object holding the variable. If not set, it will be default to globalThis.labels(optionnal) is anObjectof key-values holding the labels for the integer values ofchoices.
Let's say your algorithm has a global float variable named diameter that drives a key feature of your visuals. You can declare a parameter like this :
paramExplorer = (new ParamExplorer(USER_SKETCH_ID))
.setParameters({
'diameter' : {'type' : 'float', 'range' : [100,200], 'obj' : globalThis}
}).finalize();It's very important that the key of the object given to setParameters() function match the name of your variable.
It is possible to recall a drawing from the gallery for editing it. Thus, you have to save some data that allowed the generation of a particular drawing, especially the seed for initializing the sequence of random numbers. Other useful data can be saved in the object returned to the ParamExplorer framework.
// Returns the current seed
function getArtworkData()
{
return {'p5RandomSeed' : p5RandomSeed};
}
// Sets the current seed
// before setupArtwork() & drawArtwork() are called
// Useful for editing a drawing from the gallery
function setArtworkData(data={})
{
if ('p5RandomSeed' in data)
p5RandomSeed = data['p5RandomSeed'];
}A session identifier helps the ParamExplorer framework to keep track of your experimentations. For a given sketch, it is possible to handle multiples sessions to explore the parameters space differently.
This tab exposes an interface that was automatically generated from the parameters definition.
The Generate button allows you to create a new drawing after having randomly sampled the parameters values in their respective range.
Once generated, you can attribute a score between 0 and 100 to the drawing to make the framework 'learn' about what you estimate to be a nice drawing.

This tab is the heart of the ParamExplorer framework. It allows to generate multiple images according to different computational strategies embedded in the agents.
An agent is an entity that tries to optimize and discover new sets of parameters depending on what it has been learning thanks to scores users gave to previous images.
The tool proposes four agents for the moment :
Agent Randomsamples randomly in the parameters space, same strategy as in manual exploration.Agent CMA-ESlearns how parameters influence each other, number of visual groups is fixed for the moment in the code (n_agentsinagent_cmaes.pyon backend ).Agent Gaussianimproves visuals by making slight variations around previously liked images, adjusting each parameter independently, the number of clusters (groups) is also fixed (population_sizeinagent_gaussian.pyin the backend).Agent Open-endedsimilar in spirit to Agent Gaussian but can continuously create new clusters (groups) over time with no fixed limit.
Each time a batch is generated, the images and their parameters are saved in the gallery where you can set a score or delete them to train the agents.

A grid of images is displayed according to different filters.
If the filter Images by agent is selected, images that were generated by that agent are grouped into clusters with some "parameters similarity" (except of the Agent Random)
You can select an image by clicking on it. Selecting multiple images id done by pressing Command(MacOS) or Control(Windows / Linux) while clicking on images.
Several "hot keys" were defined to help setting score or deleting groups of images quickly :
'a'selects all the images.'d'deletes the selected images with a prior validation popup.'s'sets the score to 100 to the selected images.
- You may want to explore manually the set of parameters for your algorithm :
- either in the
Manual Explorationtab by clicking on theGeneratebutton. - either in the
Agent Explorationtab by running batches with theAgent Random.
- In the
Gallerytab, give score to the generated images you like, around 30~40 images is a good starting point to train agents. - In the
Agent Explorationtab, start generating images using an agent (except theAgent Random). The ParamExplorer framework should start creating images with learnt parameters but also should try to find new directions in this parameters space to propose new series of drawings ... and surprises you ! - If you find some new drawings not seen before, you can edit the sets of parameters in
Manual Explorationin step 1. so agents can learn from this point in parameters space and explores further in this direction.

