/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.RTNpjlThZ45/rev.54
*
* authors:
* Keith O'Hara
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
/*
* Keith O'Hara <[email protected]>
*
* K-Means Image Segmentation
*
*
*/
/* @pjs preload="/static/uploaded_resources/p.1049/thedress.png"; */
PImage video;
float L = 2;
int numClusters = 2;
int[] classified;
float[][] clusters;
void assignClosest() {
for (int i = 0; i < video.width*video.height; i++) {
int closest_k = 0;
float closest_dist = 1000000000;
for (int j = 0; j < numClusters; j++) {
color c = video.pixels[i];
float r = (c >> 16) & 0xFF;
float g = (c >> 8) & 0xFF;
float b = c & 0xFF;
float[] p = clusters[j];
float cr = p[0];
float cg = p[1];
float cb = p[2];
float d = pow(0
+ pow(abs(cr - r) / 255.0, L)
+ pow(abs(cb - b) / 255.0, L)
+ pow(abs(cg - g) / 255.0, L)
, 1.0 / L);
if (d < closest_dist) {
closest_dist = d;
closest_k = j;
}
}
classified[i] = closest_k;
}
}
void computeCentroids()
{
int[] count = new int[numClusters];
// clear cluster means
for (int i = 0; i < numClusters; i++) {
count[i] = 0;
for (int j = 0; j < clusters[i].length; j++) {
clusters[i][j] = 0;
}
}
for (int i = 0; i < video.width*video.height; i++) {
color c = video.pixels[i];
int r = (c >> 16) & 0xFF;
int g = (c >> 8) & 0xFF;
int b = c & 0xFF;
float v[] = {
r, g, b
};
int clusterCenter = classified[i];
count[clusterCenter]++;
for (int z = 0; z < clusters[clusterCenter].length; z++) {
clusters[clusterCenter][z] += v[z];
}
}
for (int j = 0; j < numClusters; j++) {
for (int z = 0; z < clusters[j].length; z++) {
clusters[j][z] /= count[j];
}
}
}
void setup() {
size(782, 490);
video = loadImage("/static/uploaded_resources/p.1049/thedress.png");
reset();
}
void reset() {
clusters = new float[numClusters][3];
classified = new int[video.width * video.height];
for (int i = 0; i < numClusters; i++) {
int z = (int)(random(video.height*video.width));
color c = video.pixels[z];
int r = (c >> 16) & 0xFF;
int g = (c >> 8) & 0xFF;
int b = c & 0xFF;
float v[] = {
r, g, b
};
clusters[i] = v;
}
}
void mousePressed() {
reset();
}
void draw() {
video.loadPixels();
image(video, width/2, 0);
// Create a new image to store the resulting clustered image
PImage cImg = createImage(video.width, video.height, RGB);
cImg.loadPixels();
assignClosest();
computeCentroids();
// Loop through every pixel in the image.
for (int i = 0; i < cImg.height*cImg.width; i++) {
float []v =clusters[classified[i]];
color c = color(v[0], v[1], v[2]);
cImg.pixels[i] = c;
}
cImg.updatePixels();
image(cImg, 0, 0, video.width, video.height);
}