My genetic drawing program Drarwing has been optimized and streamlined so that it runs better and is easier to use, and is now served on the web via Google Cloud Functions, making it accessible directly from any web browser.
The code can be found here on GitHub.
Please make sure the image is not larger than 5MB and has the jpeg or png format. I recommend you use Drarwing from a Desktop device.
The server has limited capacity, so if you encounter issues it might help to simply try again later. Also note that the processing time depends on many factors, among which; the level of detail in the image, and the selected brush set. Using the Canvas brush set is typically faster, while Sketch is slower because the brush strokes are smaller. Wait-time is usually around ~3 minutes, but can go up to 15+ minutes. You can read about how Drarwing works at the bottom.
Brush Set:
Some examples of results. All input images are from unsplash.com
While the performance of Drarwing has drastically improved, I did an interesting experiment for potentially improving it even further. Drarwing uses an evolutionary algorithm, which includes a "selection" phase to select which "specimen" get to live in the next "generation" of the "population". Drarwing simply starts with a single specimen, copies it, mutates the copy, and then checks if the copy is an improvement over the last version - effectively using a population size of 2. I wondered what would happen if we used a population size of 1.
Since the mutations are guided in a way that should improve the result, we could try skipping the check whether the new version is an improvement. However, in reality, not every mutation is an improvement. We use single pixel values to determine candidate locations for new brush strokes. However, when placing the brush stroke, not only that particular pixel is affected, but also many pixels around it. As a result, placing a new brush stroke might make a specimen worse than its predecessor. This is not always a problem; it's okay if the fitness score temporarily becomes worse again, as long is it generally improves. And this happens for many images, but not all.
Especially for images with a lot of fine grained details, or small highlights, the evolutionary algorithm can get stuck in a loop, where in for example 20 generations it keeps circling around the same area, continuously overdrawing it's previous changes. When using a population size of just 1, the algorithm was not able to generate this beauty:
You could try to detect such loops, but it's just way simpler to use a population size larger than 1, and simply check for improvement. By not making the population size bigger than 2 we also limit the memory and compute requirements for our program. Initially, I created copies of the best specimen of the previous generation in a way that was quite expensive. This made the process as a whole roughly 5 times slower, even though I only increased the population size from 1 to 2, and added a single check. This was really unfortunate but still worth it to prevent getting stuck. Until Jayke Meijer opened up a PR for Drarwing, that is. He pointed out that by using numpy.copy(), instead of copy.deepcopy(), the previous performance loss would be won back. Drarwing now runs 5 times faster again, while still using a population size of 2!
The code for this iteration of Drarwing can be found here on GitHub.
The initial post on Drarwing can be found here!
More details about a pointillism-based prototype for Drarwing can be found here!