Evolution of Mona Lisa in JavaScript & Canvas
alteredqualia.com
alteredqualia.com
It's far from perfect, but it seems to work. So far I'm at around 1/30th of the original iterations (took ~1 hour) and it already looks a bit like Mona Lisa :).
I'll be updating the page with more evolved images.
Note: it works only in few browsers: so far I'm aware of Firefox 3.0.4 and Opera 9.61. Firefox is significantly faster.
You may try to run it on different images, I just added new experimental feature: you can set your own target image.
This does crash JavaScript sometimes on some images (for unknown reasons). If this happens, just reload the page.
Anyway, I will now try with your set-your-own-image version.
That's how I work on it (XAMPP).
A polygon overlaps another polygon and improves fitness by N. It gets mutated and fitness goes down, so that is not kept. The polygon stays in a local maxima position, when one mutation lowering fitness might allow much better fitness in future.
Yet the images look like that doesn't happen - have you deliberately avoided it, or isn't it a problem in practise?
The only parameter tuning I did was to try several numbers of vertices per polygon for about 15 minutes and from there on I just used the one (6 vertices) that produced image I liked the most.
10 vertices produced too much noise, 4 vertices was kind of rough.
I started coding with possible variable number of vertices (that seems to be the case in the original algorithm), but it was just too slow in JavaScript.
Anyway, optimization can eventually collapse vertices, so basically I just hardcoded an upper bound.
And mutations are kind of soft, always just one element (R,G,B,A,X,Y).
I guess there is some place for improvement, for example by using HSV comparision for fitness. Though this may be slow. Raw canvas image data are RGBA.
Ah yes, I remember also that at the beginning it didn't want to converge at all when starting with random colors. It works when it can gradually build up from a blank slate.
I tried with HSB. It didn't produce good results. The image was always too dark.
In HSB, colors that are far apart in our perception can have close distance. For example two colors with the same Brightness, Saturation but a different Hue.
Using HSB in the DNA was perfect. It's hard to mutate a RGB color in the right direction. You have to get 3 composants right. In HSB a single modification can change everything.
BTW, I coded a Java version after seeing the original. It works, but first, it doesn't converge very fast, second, it's stuck at: http://i33.tinypic.com/2yycdc8.jpg
On the bright side, I can easily switch the population size to 50. Java is very good at this. I piggy back on automatic hardware acceleration for rendering.
How did you get yours to converge sooo fast?!
http://rogeralsing.com/2008/12/11/genetic-programming-mona-l...
From what I have seen, he is doing extra type of mutations that I was too lazy to implement: move polygons in the stack (in addition to changing colors and moving points around).
Also how you do mutations matters: it seems smaller deltas are better, though they shouldn't be too small.
I've created a number of variations on this, including a black&white one which does a good job of Darwin.
The biggest improvement I've made is in limiting the size of the mutation. Now I have a 1 in 50 chance of executing your mutation code, else the changes are limited to within about 10% of their existing value. This gave me a very nice Velociraptor.
I'm also playing with triangles instead of polygons, but I'm impatient and trying to run them all simultaneously. Time to upgrade...
abs(r1-r2) + abs(g1-g2) + abs(b1-b2)"Someone."
Create a rendering algorithm such as this but with the fitness function calculated by presenting a set of the output images to web visitors and having them choose the one(s) that they like the most.
My thesis is that with enough iterations/visitors you'd eventually generate a load of highly tuned pornography.
Gags about hot-or-not go here... :-)
I just added MIT License [1] to the source.
Everything is in one self-contained HTML file (sans images). Feel free to improve it :).
Martin
The new value becomes either (MAX - current) * P or current * P (50% chance on each), where P is the product of two random variables between [-1, 1]. I'm not sure how that is distributed (been a while since that statistics course), but it obviously favors numbers closer to 0.
This optimization looks rather efficient, as the same image seems to get about 67% more beneficient mutations in the same interval of generations.
Another change I would like to implement (but haven't yet) is a low chance of changing multiple values at once, which may eventually escape from a "dead end".
The best improvement of all would be to allow users to airbrush "priority" onto different regions, which then get weighted in the fitness score. If I'm generating a portrait, I care a lot more about the eyes than the background, for example.
I also tried randomly replacing a poly with a new random shape and color poly 5% of the time to get away from local minima... didn't seem to help. I'm still doing a bit on this in my spare time if anyone is interested.
Later.
Is this the case with this "Mona Lisa" problem? Is there an alternative algorithm for finding the polygons that would be more efficient and give better results?
None that I've found on Flickr have worked.
I googled for "200x200" and found the Firefox logo in that size, and it's evolving that... fitness has just crossed under 1,000,000 after about 15 minutes, but it isn't recognisable yet...
That is, it looks nothing like it. It has, for example, no dark blue, orange, yellow or white - and only a smidgen of pale blue in completely the wrong place. The whole square is shades of hessian brown/pale green/caucasian artificial limb with a blotch of pink.
The first velociraptor I tried was a stop sign from XKCD and it failed miserably.
Though you never know, I also thought black&white Darwin image was hopeless, and it did managed to start converging eventually.
If it does something weird, just reset it by forced reload (Ctrl-F5).
Stay tuned tomorrow for DNA import/export, it's like 80% done.
[Edit] DNA import/export is done. Just please be gentle with it, for the moment it's very fragile (e.g. whitespace matters).
If somebody wants to play with it, DNA format is very simple (all INTs except for ALPHA which is FLOAT):
NUMBER_OF_VERTICES NUMBER_OF_POLYGONS R G B ALPHA X0 Y0 X1 Y1 ... XN YN ... R G B ALPHA X0 Y0 X1 Y1 ... XN YN ...