📄 neuquant.java
字号:
// Constructors:// public NeuQuant (Image im, ImageObserver obs) throws IOException -- default sample = 1// public NeuQuant (int sample, Image im, ImageObserver obs) throws IOException// public NeuQuant (Image im, int w, int h) throws IOException -- default sample = 1// public NeuQuant (int sample, Image im, int w, int h) throws IOException// Initialisation method: call this first// public void init ()// Methods to look up pixels (use in a loop)// public int convert (int pixel)// public int lookup (int pixel)// public int lookup (Color c)// public int lookup (boolean rgb, int x, int g, int y)// Method to write out colour map (used for GIFs, with "true" parameter)// public int writeColourMap (boolean rgb, OutputStream out) throws IOException// Other methods to interrogate colour map// public int getColorCount ()// public Color getColor (int i)package OCG.image;import java.util.*;import java.io.*;import java.awt.Image;import java.awt.Color;import java.awt.image.*;/* 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. */public class NeuQuant { public static final int ncycles = 100; // no. of learning cycles public static final int netsize = 256; // number of colours used public static final int specials = 3; // number of reserved colours used public static final int bgColour = specials-1; // reserved background colour public static final int cutnetsize = netsize - specials; public static final int maxnetpos = netsize-1; public static final int initrad = netsize/8; // for 256 cols, radius starts at 32 public static final int radiusbiasshift = 6; public static final int radiusbias = 1 << radiusbiasshift; public static final int initBiasRadius = initrad*radiusbias; public static final int radiusdec = 30; // factor of 1/30 each cycle public static final int alphabiasshift = 10; // alpha starts at 1 public static final int initalpha = 1<<alphabiasshift; // biased by 10 bits public static final double gamma = 1024.0; public static final double beta = 1.0/1024.0; public static final double betagamma = beta * gamma; private double [] [] network = new double [netsize] [3]; // the network itself protected int [] [] colormap = new int [netsize] [4]; // the network itself private int [] netindex = new int [256]; // for network lookup - really 256 private double [] bias = new double [netsize]; // bias and freq arrays for learning private double [] freq = new double [netsize]; // four primes near 500 - assume no image has a length so large // that it is divisible by all four primes public static final int prime1 = 499; public static final int prime2 = 491; public static final int prime3 = 487; public static final int prime4 = 503; public static final int maxprime= prime4; protected int [] pixels = null; private int samplefac = 0; public NeuQuant (Image im, int w, int h) throws IOException { this (1); setPixels (im, w, h); setUpArrays (); } public NeuQuant (int sample, Image im, int w, int h) throws IOException { this (sample); setPixels (im, w, h); setUpArrays (); } public NeuQuant (Image im, ImageObserver obs) throws IOException { this (1); setPixels (im, obs); setUpArrays (); } private NeuQuant (int sample) throws IOException { if (sample < 1) throw new IOException ("Sample must be 1..30"); if (sample > 30) throw new IOException ("Sample must be 1..30"); samplefac = sample; // rest later } public NeuQuant (int sample, Image im, ImageObserver obs) throws IOException { this (sample); setPixels (im, obs); setUpArrays (); } public int getColorCount () { return netsize; } public Color getColor (int i) { if (i < 0 || i >= netsize) return null; int bb = colormap[i][0]; int gg = colormap[i][1]; int rr = colormap[i][2]; return new Color (rr, gg, bb); } public int writeColourMap (boolean rgb, OutputStream out) throws IOException { for (int i=0; i<netsize; i++) { int bb = colormap[i][0]; int gg = colormap[i][1]; int rr = colormap[i][2]; out.write (rgb ? rr : bb); out.write (gg); out.write (rgb ? bb : rr); } return netsize; } protected void setUpArrays () { network [0] [0] = 0.0; // black network [0] [1] = 0.0; network [0] [2] = 0.0; network [1] [0] = 1.0; // white network [1] [1] = 1.0; network [1] [2] = 1.0; // RESERVED bgColour // background for (int i=0; i<specials; i++) { freq[i] = 1.0 / netsize; bias[i] = 0.0; } for (int i=specials; i<netsize; i++) { double [] p = network [i]; p[0] = (256.0 * (i-specials)) / cutnetsize; p[1] = (256.0 * (i-specials)) / cutnetsize; p[2] = (256.0 * (i-specials)) / cutnetsize; freq[i] = 1.0 / netsize; bias[i] = 0.0; } } private void setPixels (Image im, ImageObserver obs) throws IOException { if (im == null) throw new IOException ("Image is null"); int w = im.getWidth(obs); int h = im.getHeight(obs); setPixels (im, w, h); } private void setPixels (Image im, int w, int h) throws IOException { if (w*h < maxprime) throw new IOException ("Image is too small"); pixels = new int [w * h]; java.awt.image.PixelGrabber pg = new java.awt.image.PixelGrabber(im, 0, 0, w, h, pixels, 0, w); try { pg.grabPixels(); } catch (InterruptedException e) { } if ((pg.getStatus() & java.awt.image.ImageObserver.ABORT) != 0) { throw new IOException ("Image pixel grab aborted or errored"); } } public void init () { learn (); fix (); inxbuild (); } private void altersingle(double alpha, int i, double b, double g, double r) { // Move neuron i towards biased (b,g,r) by factor alpha double [] n = network[i]; // alter hit neuron n[0] -= (alpha*(n[0] - b)); n[1] -= (alpha*(n[1] - g)); n[2] -= (alpha*(n[2] - r)); } private void alterneigh(double alpha, int rad, int i, double b, double g, double r) { int lo = i-rad; if (lo<specials-1) lo=specials-1; int hi = i+rad; if (hi>netsize) hi=netsize; int j = i+1; int k = i-1; int q = 0; while ((j<hi) || (k>lo)) { double a = (alpha * (rad*rad - q*q)) / (rad*rad); q ++; if (j<hi) { double [] p = network[j]; p[0] -= (a*(p[0] - b)); p[1] -= (a*(p[1] - g)); p[2] -= (a*(p[2] - r)); j++; } if (k>lo) { double [] p = network[k]; p[0] -= (a*(p[0] - b)); p[1] -= (a*(p[1] - g)); p[2] -= (a*(p[2] - r)); k--; } } } private 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])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -