anopara / genetic-drawing

A genetic algorithm toy project for drawing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Algorithm explanation

empireshades opened this issue · comments

Hi @anopara. Thank you for sharing this awesome toy exercise. I was wondering if you or someone else could explain how the algorithm works? Despite repeated review of the code, my python fu is limited.

@empireshades roughly speaking, a GA is random search guided by a target function. In this case, the target function is how much differs the image proposed by the algorithm and a greyscale version of the original image.

The algorithm codes the brush strokes in six values: (x,y) position, brush size, type of brush (there are 4), color and rotation. At every step, it generates a random combination of those and tests how good that stroke is. If it is better than the previous ones, it keeps it. Otherwise, it drops it and try again. Of course, there are a ton of details that I'm skipping :)

In the notebook you can see that the algorithm is called twice. The first call draws a sketch, the second call draws the details (using a mask if you provide one).

Hope it helps!

@sgmoratilla Thank you for the explanation. This was my general understanding of the algorithm as well. It’s those mini details that I’m not really understanding ;) I feel like it’s the type of thing I won’t truly get unless I coded it from scratch myself.

@empireshades I'd love to write a more in-depth explanation at some point, but atm cannot allocate a lot of headspace to this project atm. Hopefully, one day!

Quick'n'dirty expansion on @sgmoratilla 's very nice explanation of the genetic algorithm part:

  • The sampling mask is used to better guide the random XY positions. So the probability of placing a stroke in whiter areas is higher. The algorithm automatically generates the sampling masks based on detected edges (unless you provide your own mask). The intuition being that the areas of high frequency of edges are the areas where most details are needed. The algorithm starts with a blurred out version of the edge mask (to not start with details rightaway; as it progresses to the next stages, it focuses more and more on the high freq edge areas). You can see this process clearly in the gif in the readme
  • The rotations are also guided with an auto-generated image gradient mask. The intuition is that if there is a big gradient (aka change in color), that is very likely to be a high contrast edge. Then we don't want to place a stroke of random rotation, we want a stroke perpendicular to the gradient (aka, a stroke following the edge). The stronger the gradient, the more likely the algorithm will pick a direction along the edge.

Thanks all. This def helps clarify the logic, especially the directions of the strokes against the edges.