Skip to content

Instantly share code, notes, and snippets.

@adrianseeley
Created December 13, 2016 22:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adrianseeley/c36c8c8bc5319426152b7737f0642ec5 to your computer and use it in GitHub Desktop.
Save adrianseeley/c36c8c8bc5319426152b7737f0642ec5 to your computer and use it in GitHub Desktop.
image GA
<html>
<body>
Max Iterations: <input id="max_iterations" type="text" value="1500"><br>
Max Shapes: <input id="max_shapes" type="text" value="100"><br>
Annealing Rate: <input id="annealing_rate" type="text" value="0.999"><br>
Starting Temperature: <input id="starting_temperature" type="text" value="0.04"><br>
<input id="input" type="file" onchange="return load_image();"><br>
<canvas id="original"></canvas>
<canvas id="rendered"></canvas><br>
<span id="status"></span>
</body>
<script>
var canvas_original = document.getElementById('original');
var canvas_rendered = document.getElementById('rendered');
var status_div = document.getElementById('status');
var ctx_original = canvas_original.getContext('2d');
var ctx_rendered = canvas_rendered.getContext('2d');
var max_iterations = null;
var max_shapes = null;
var annealing_rate = null;
var starting_temperature = null;
var shapes = null;
var current_iteration = null;
var current_shape = null;
var temperature = null;
var last_shape = null;
var last_fitness = null;
var pixels_original = null;
function load_image () {
var input = document.getElementById('input');
var file = input.files[0];
var fr = new FileReader();
fr.onload = function () {
var img = new Image();
img.onload = function () {
canvas_original.width = img.width;
canvas_original.height = img.height;
canvas_rendered.width = img.width;
canvas_rendered.height = img.height;
ctx_original.drawImage(img, 0, 0);
pixels_original = ctx_original.getImageData(0, 0, canvas_original.width, canvas_original.height).data;
max_iterations = parseInt(document.getElementById('max_iterations').value);
max_shapes = parseInt(document.getElementById('max_shapes').value);
annealing_rate = parseFloat(document.getElementById('annealing_rate').value);
starting_temperature = parseFloat(document.getElementById('starting_temperature').value);
shapes = [];
current_iteration = 0;
current_shape = 0;
temperature = starting_temperature;
last_shape = null;
last_fitness = null;
return iterate();
};
img.src = fr.result;
};
fr.readAsDataURL(file);
return false;
};
function iterate () {
if (current_iteration >= max_iterations) {
current_iteration = 0;
current_shape += 1;
temperature = starting_temperature;
return iterate();
}
if (current_shape >= max_shapes) {
return; // done!
}
if (shapes.length <= current_shape) {
shapes.push([0, 0, 1, 1, 0, 0, 0]);
last_shape = null;
last_fitness = null;
} else {
var two_temperature = temperature * 2;
var random_idx = Math.floor(Math.random() * 7);
shapes[shapes.length - 1][random_idx] = Math.min(1, Math.max(0, shapes[shapes.length - 1][random_idx] + ((Math.random() * two_temperature) - temperature)));
/* walk all
for (var i = 0; i < 7; i++) {
shapes[shapes.length - 1][i] = Math.min(1, Math.max(0, shapes[shapes.length - 1][i] + ((Math.random() * two_temperature) - temperature)));
}
*/
}
function draw (canvas, ctx, shapes) {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < shapes.length; i++) {
ctx.fillStyle = 'rgb(' + Math.floor(shapes[i][4] * 255) + ',' + Math.floor(shapes[i][5] * 255) + ',' + Math.floor(shapes[i][6] * 255) + ')';
ctx.fillRect(shapes[i][0] * canvas.width, shapes[i][1] * canvas.height, shapes[i][2] * canvas.width, shapes[i][3] * canvas.height);
}
};
draw(canvas_rendered, ctx_rendered, shapes);
function calculate_fitness (pixels_original, ctx, canvas) {
var fitness = 0;
var pixels_rendered = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0; i < pixels_original.length; i++) {
if ((i + 1) % 4 != 0) {
fitness += Math.abs(pixels_rendered[i] - pixels_original[i]);
}
}
return fitness;
};
var fitness = calculate_fitness(pixels_original, ctx_rendered, canvas_rendered);
// if this wasnt the first iteration
if (last_fitness != null) {
// if current fitness is worse than last fitness
if (fitness > last_fitness) {
// set last shape back to previous iteration version
for (var i = 0; i < 7; i++) {
shapes[shapes.length - 1][i] = last_shape[i];
}
// else current fitness is better than last fitness
} else {
// set the last shape and fitness
last_shape = [];
for (var i = 0; i < 7; i++) {
last_shape.push(shapes[shapes.length - 1][i]);
}
last_fitness = fitness;
}
// otherwise this was the first iterations
} else {
// set the last shape and fitness
last_shape = [];
for (var i = 0; i < 7; i++) {
last_shape.push(shapes[shapes.length - 1][i]);
}
last_fitness = fitness;
}
current_iteration += 1;
temperature *= annealing_rate;
var percent_done = Math.floor((((shapes.length - 1) + (current_iteration / max_iterations)) / max_shapes) * 10000) / 100;
status_div.innerText = percent_done + '%';
setTimeout(iterate, 1);
};
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment