xxxxxxxxxx
149
// Coding Train / Daniel Shiffman
// Weighted Voronoi Stippling
// https://thecodingtrain.com/challenges/181-image-stippling
let points = [];
let grid = [];
let seed_count = 500;
let centroids, weights, counts;
let delaunay, voronoi;
let eric, felix;
let current_image;
function preload() {
eric = loadImage("eric_clapton.jpeg");
felix = loadImage("felix.jpeg");
}
function loadThePixels(img) {
img.loadPixels();
let delaunayIndex = 0;
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
let index = (i + j * width) * 4;
let r = img.pixels[index + 0];
let g = img.pixels[index + 1];
let b = img.pixels[index + 2];
let bright = (r + g + b) / 3;
let weight = 1 - bright / 255;
delaunayIndex = delaunay.find(i, j, delaunayIndex);
centroids[delaunayIndex].x += i * weight;
centroids[delaunayIndex].y += j * weight;
weights[delaunayIndex] += weight;
counts[delaunayIndex]++;
}
}
}
function gridPoints() {
let x_max = round(sqrt(width / height * seed_count));
let y_max = round(seed_count / x_max);
seed_count = x_max * y_max;
for(let i = 0, y = 0; y < y_max; y++) {
for(let x = 0; x < x_max; x++, i++) {
let px = map(x, 0, x_max, 0, width);
let py = map(y, 0, y_max, 0, height);
grid[i] = createVector(px, py);
}
}
}
function setup() {
current_image = felix;
createCanvas(current_image.width, current_image.height);
gridPoints();
for (let i = 0; i < seed_count; i++) {
let x = grid[i].x;
let y = grid[i].y;
let col = current_image.get(x, y);
if(brightness(col) < 100) {
points.push(createVector(x, y));
}
/*
let col = current_image.get(x, y);
if (random(100) > brightness(col)) {
points.push(createVector(x, y));
} else {
i--;
}
*/
}
}
function draw() {
background(255);
delaunay = d3.Delaunay.from(points.map(p=>[p.x, p.y]));
voronoi = delaunay.voronoi([0, 0, width, height]);
let polygons = voronoi.cellPolygons();
let cells = Array.from(polygons);
centroids = new Array(cells.length);
weights = new Array(cells.length).fill(0);
counts = new Array(cells.length).fill(0);
let avgWeights = new Array(cells.length).fill(0);
for (let i = 0; i < centroids.length; i++) {
centroids[i] = createVector(0, 0);
}
if(frameCount < 500) {
loadThePixels(current_image);
} else if(frameCount < 1000) {
current_image = eric;
loadThePixels(eric);
} else {
noLoop();
print("done");
}
let maxWeight = 0;
for (let i = 0; i < centroids.length; i++) {
if (weights[i] > 0) {
centroids[i].div(weights[i]);
avgWeights[i] = weights[i] / (counts[i] || 1);
if (avgWeights[i] > maxWeight) {
maxWeight = avgWeights[i];
}
} else {
centroids[i] = points[i].copy();
}
}
for (let i = 0; i < points.length; i++) {
points[i].lerp(centroids[i], 0.1);
}
/*
for (let i = 0; i < cells.length; i++) {
let poly = cells[i];
let centroid = centroids[i];
let col =current_image.get(centroid.x, centroid.y)
stroke(0);
strokeWeight(0.5);
// fill(col);
noFill();
beginShape();
for (let i = 0; i < poly.length; i++) {
vertex(poly[i][0], poly[i][1]);
}
endShape();
}
*/
for (let i = 0; i < points.length; i++) {
let v = points[i];
let col = current_image.get(v.x, v.y);
let sw = map(avgWeights[i], 0, maxWeight, 0, 3, true);
stroke(0);
strokeWeight(sw);
point(v.x, v.y);
}
}