/* NeuQuant Neural-Net Quantization Algorithm * ------------------------------------------ * * Copyright (c) 1994 Anthony Dekker * * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. * See "Kohonen neural networks for optimal colour quantization" * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367. * for a discussion of the algorithm. * See also http://www.acm.org/~dekker/NEUQUANT.HTML * * Any party obtaining a copy of these files from the author, directly or * indirectly, is granted, free of charge, a full and unrestricted irrevocable, * world-wide, paid up, royalty-free, nonexclusive right and license to deal * in this software and documentation files (the "Software"), including without * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons who receive * copies from any such party to do so, with the only requirement being * that this copyright notice remain intact. */ // Adapted for Processing by Mario Klingemann // http://www.incubator.quasimondo.com BImage pic; NeuQuant nq; void setup(){ noStroke(); pic=loadImage("jesus.jpg"); size(pic.width,pic.height); } void loop(){ int colorCount=max(2,mouseX/4); image(pic,0,0); nq=new NeuQuant(colorCount,false); nq.init(); for (int i=0;inetsize) hi=netsize; int j = i+1; int k = i-1; int q = 0; while ((jlo)) { double a = (alpha * (rad*rad - q*q)) / (rad*rad); q ++; if (jlo) { double [] p = network[k]; p[0] -= (a*(p[0] - b)); p[1] -= (a*(p[1] - g)); p[2] -= (a*(p[2] - r)); k--; } } } int contest (double b, double g, double r) { // Search for biased BGR values // finds closest neuron (min dist) and updates freq // finds best neuron (min dist-bias) and returns position // for frequently chosen neurons, freq[i] is high and bias[i] is negative // bias[i] = gamma*((1/netsize)-freq[i]) double bestd = Float.MAX_VALUE; double bestbiasd = bestd; int bestpos = -1; int bestbiaspos = bestpos; for (int i=0; i> radiusbiasshift; if (rad <= 1) rad = 0; //System.err.println("beginning 1D learning: samplepixels=" + samplepixels + " rad=" + rad); int step = 0; int pos = 0; if ((lengthcount%prime1) != 0) step = prime1; else { if ((lengthcount%prime2) !=0) step = prime2; else { if ((lengthcount%prime3) !=0) step = prime3; else step = prime4; } } i = 0; while (i < samplepixels) { int p = pixels [pos]; int red = (p >> 16) & 0xff; int green = (p >> 8) & 0xff; int blue = (p ) & 0xff; double b = blue; double g = green; double r = red; /* if (i == 0) { // remember background colour network [2] [0] = b; network [2] [1] = g; network [2] [2] = r; } */ int j = specialFind (b, g, r); j = j < 0 ? contest (b, g, r) : j; if (j >= specials) { // don't learn for specials double a = (1.0 * alpha) / initalpha; altersingle (a, j, b, g, r); if (rad > 0) alterneigh (a, rad, j, b, g, r); // alter neighbours } pos += step; while (pos >= lengthcount) pos -= lengthcount; i++; if (i%delta == 0) { alpha -= alpha / alphadec; biasRadius -= biasRadius / radiusdec; rad = biasRadius >> radiusbiasshift; if (rad <= 1) rad = 0; } } //System.err.println("finished 1D learning: final alpha=" + (1.0 * alpha)/initalpha + "!"); } void fix() { for (int i=0; i 255) x = 255; colormap[i][j] = x; } colormap[i][3] = i; } } void inxbuild() { // Insertion sort of network and building of netindex[0..255] int previouscol = 0; int startpos = 0; for (int i=0; i>1; for (int j=previouscol+1; j>1; for (int j=previouscol+1; j<256; j++) netindex[j] = maxnetpos; // really 256 } int convert (int pixel) { int alfa = (pixel >> 24) & 0xff; int r = (pixel >> 16) & 0xff; int g = (pixel >> 8) & 0xff; int b = (pixel ) & 0xff; int i = inxsearch(b, g, r); int bb = colormap[i][0]; int gg = colormap[i][1]; int rr = colormap[i][2]; return (alfa << 24) | (rr << 16) | (gg << 8) | (bb); } int lookup (int pixel) { int r = (pixel >> 16) & 0xff; int g = (pixel >> 8) & 0xff; int b = (pixel ) & 0xff; int i = inxsearch(b, g, r); return i; } int lookup (boolean rgb, int x, int g, int y) { int i = rgb ? inxsearch (y, g, x) : inxsearch (x, g, y); return i; } int inxsearch(int b, int g, int r) { // Search for BGR values 0..255 and return colour index int bestd = 1000; // biggest possible dist is 256*3 int best = -1; int i = netindex[g]; // index on g int j = i-1; // start at netindex[g] and work outwards while ((i=0)) { if (i= bestd) i = netsize; // stop iter else { if (dist<0) dist = -dist; int a = p[0] - b; if (a<0) a = -a; dist += a; if (dist=0) { int [] p = colormap[j]; int dist = g - p[1]; // inx key - reverse dif if (dist >= bestd) j = -1; // stop iter else { if (dist<0) dist = -dist; int a = p[0] - b; if (a<0) a = -a; dist += a; if (dist