Created
December 13, 2016 22:17
-
-
Save adrianseeley/c36c8c8bc5319426152b7737f0642ec5 to your computer and use it in GitHub Desktop.
image GA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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