Function Evolution

11:16 p.m. Wednesday, September 30th 2009.

Is it possible to automatically generate images out of the functions in Image Functions? The answer is yes! It is possible with genetic programming. Let's explore this.

Suppose the image we're trying to match is this picture of Charles Darwin:

Here's how it works: We first create a population of randomly-generated functions. Then we evaluate each of these functions and see how close they match the image above. We take the best ones out of this population, and create a bunch of replicas of them with a few differences (mutations) to create a new population. This process is repeated for each generation of the population until one finally matches close enough to the original image, or until we give up. I'm glossing over a lot of details, but there are plenty of tutorials on genetic programming to get a better understanding of how it works.

Unfortunately, trying to match a single function to try to generate the entire image doesn't work so well, so we had to give up. Here's the best result achieved so far, on a smaller version of the image:

The function for this failure of an image can be seen here. It's rather large (too big to put into the web app, so don't even try).

If we split the image into a 10x10 grid, however, and try to match each piece of the grid to their respective piece of the original image, we get a much better result.

The functions that produce this image can be seen here. If you implemented the same version of the renderer (or download mine, when I release it), you should be able to plug these functions in to generate the exact same image, at arbitrary resolution.

Here's a video of the algorithm's progress with one frame per generation. It gets pretty close fairly early, and slowly refines itself.

You may wonder why we would want to do this. Well, take this image for example. Consider the fact that the image, in .jpg format, is almost 40,000 bytes in size. However, look at its representation on the bottom - 223 characters long. That's just 223 bytes, and that's not even counting the fact that you can compress the text itself. Probably down to about 40 bytes. There is great potential for compression here, if we could just figure out how to do it for general images!

What's next? Well, the grid thing seems to work fairly well, but the image still lacks some detail. We probably want to implement a quad-tree algorithm that will cut the image into a 4x4 grid, try to match the pieces, and for those that didn't match well enough cut them down even further. This should allow the algorithm to automatically focus in on noisy parts of the image.

Oh, and yes. Eventually we will get this going with video. And audio. That will be pretty awesome.

Comments
By lorg, 1:19 a.m. Thursday, October 1st 2009:
Well, this also happens every time you use jpeg, but with a less roundabout algorithm :) Consider - jpeg basically does some kind of an fft, which is an algorithm to convert a signal to a sum of various sine functions. And another point: Theoretically speaking, you have a specific vector u, and a list of 'spanning vectors' V = {v0.. vn}. You would like to approximate the specific vector with the closest vector in V. What you are doing is searching the space of V for the closest vector.
By Stephane Grenier, 7:50 a.m. Thursday, October 1st 2009:
Have you thought of applying your GA technique to images that have functions within them, such as a shells, etc. As well, just think of the potential where you can find functions in forms that we don't already know about. Although a Mandelbrot image is probably too much, think of the patterns you could discover in nature!
By John Little, 7:57 a.m. Thursday, October 1st 2009:
Is it possible to use this as a fitting method? when the initial parameters are unknown? Say if you have a noisy 2-D image and want to fit a Gaussian to it? Would be interesting to compare to Levenberg–Marquardt when noise increases (quality of the fit, reproducibility, speed...)
By eicos, 8:02 a.m. Thursday, October 1st 2009:
It's nice work, but I'm afraid lorg has a point. It's cool to be able to produce certain images in a handful of bytes, but for a real-world use case, your algorithm takes seconds/minutes/hours to produce a low-fidelity image that takes up 48kB. Admittedly, using DEFLATE compression comparable to that used by PNG, we can reduce this to around 16kB, but considering that the source image is only 25kB with lossless compression, I'm not sure it's worth it, especially when Fourier-based lossy compression can squeeze a far-superior image into 1-3 kB. What do you see as the advantages of your algorithm over currently-accepted methods?
By Gregory Ray, 10:14 a.m. Thursday, October 1st 2009:
Seems like it would not work for compression since the target decompressor would already have to have the final image for comparison?
By Eric, 12:20 p.m. Thursday, October 1st 2009:
I think this has merit, but as eicos says, it needs some work to make it more valuable than jpeg. Have you considered letting the generated program do the splitting? Have you considered incorporating the length of the program in the fitness function?
By anon, 4:36 p.m. Wednesday, December 2nd 2009:
you want faster porn huh
    Posting comments is currently disabled.