package de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram;

import de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedDistanceFunction;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;

/**
 * Distance function for RGB color histograms based on a quadratic form and color similarity.
 * 
 * This is (unverified) attributed to
 * <p>
 * James Hafner, Harpreet S.Sawhney, Will Equits, Myron Flickner and Wayne Niblack<br />
 * Efficient Color Histogram Indexing for Quadratic Form Distance Functions<br />
 * IEEE Trans. on Pattern Analysis and Machine Intelligence, Vol. 17, No. 7, July 1995
 * </p>
 * 
 * @author Erich Schubert
 */
@Reference(authors="J. Hafner, H. S.Sawhney, W. Equits, M. Flickner, W. Niblack", title="Efficient Color Histogram Indexing for Quadratic Form Distance Functions", booktitle="IEEE Trans. on Pattern Analysis and Machine Intelligence, Vol. 17, No. 7, July 1995")
public class RGBHistogramQuadraticDistanceFunction extends WeightedDistanceFunction {
  /**
   * OptionID for {@link #BPP_PARAM}
   */
  public static final OptionID BPP_ID = OptionID.getOrCreateOptionID("rgbhist.bpp", "The dimensionality of the histogram in each color");

  /**
   * Parameter for the kernel dimensionality.
   */
  IntParameter BPP_PARAM = new IntParameter(BPP_ID);

  /**
   * Stores the (full = to the power of three) dimensionality
   */
  int dim;

  /**
   * Constructor, adhering to
   * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
   * 
   * @param config Parameterization
   */
  public RGBHistogramQuadraticDistanceFunction(Parameterization config) {
    super(null);
    if (config.grab(BPP_PARAM)) {
      int bpp = BPP_PARAM.getValue();
      dim = bpp * bpp * bpp;

      Matrix m = new Matrix(dim, dim);
      // maximum occurring distance in manhattan between bins:
      final double max = 3. * (bpp - 1.);
      for(int x = 0; x < dim; x++) {
        final int rx = (x / bpp) / bpp;
        final int gx = (x / bpp) % bpp;
        final int bx = x % bpp;
        for(int y = 0; y < dim; y++) {
          final int ry = (y / bpp) / bpp;
          final int gy = (y / bpp) % bpp;
          final int by = y % bpp;

          final double dr = Math.abs(rx - ry);
          final double dg = Math.abs(gx - gy);
          final double db = Math.abs(bx - by);

          final double val = 1 - (dr+dg+db)/max;
          m.set(x, y, val);
        }
      }
      weightMatrix = m;
    }
  }
}

@@ -565,16 +565,19 @@
 form and
+%0A *
  color s
@@ -710,16 +710,19 @@
 nd Wayne
+%0A *
  Niblack
@@ -878,32 +878,35 @@
  Vol. 17, No. 7,
+%0A *
  July 1995%0A * %3C/
@@ -960,17 +960,19 @@
 (authors
-=
+ = 
 %22J. Hafn
@@ -1031,17 +1031,19 @@
 %22, title
-=
+ = 
 %22Efficie
@@ -1119,17 +1119,19 @@
 ooktitle
-=
+ = 
 %22IEEE Tr
@@ -1207,16 +1207,61 @@
 ly 1995%22
+, url = %22http://dx.doi.org/10.1109/34.391417%22
 )%0Apublic
@@ -1981,17 +1981,16 @@
 ;%0A    if
- 
 (config.
@@ -2709,16 +2709,22 @@
  (dr
-+dg+db)/
+ + dg + db) / 
 max;

Add DOI