package fr.unistra.pelican.util.vectorial.orders; import java.util.Arrays; import java.util.Comparator; /** * This class represents a hue ordering * based on a saturation weighting as proposed by Hanbury. * * @author E.A. * */ public class HanburyHueOrdering implements VectorialOrdering,Comparator { private double[] d = null; private double refHue; public HanburyHueOrdering(double ref) { this.refHue = ref; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[][]) */ public double[] min(double[][] p) { // the result of erosion must not favor the reference colour.. // hence the min computes the max distance and vice versa preprocess(p); int max = 0; for(int i = 1; i < p.length; i++){ if(d[max] < d[i]) max = i; } return p[max]; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#min(double[][]) */ public double[] max(double[][] p) { preprocess(p); int min = 0; for(int i = 1; i < p.length; i++){ if(d[min] > d[i]) min = i; } return p[min]; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#rank(double[][], int) */ public double[] rank(double[][] p,int r) { preprocess(p); // it might seem like trouble // to go into using subclasses // for a simple indexed sorting // but when the channel number goes up.. // quicksort will pay off. IndexedDouble[] id = new IndexedDouble[d.length]; for(int i = 0; i < d.length; i++) id[i] = new IndexedDouble(d[i],i); Arrays.sort(id); return p[id[r].i]; } private void preprocess(double[][] p) { d = new double[p.length]; for(int i = 0; i < p.length; i++){ double h = p[i][0]; if(p[i][0] - refHue >= 0.0) h = p[i][0] - refHue; else h = 1.0 + p[i][0] - refHue; if(0.0 <= h && h <= 0.25) h = Math.max(h,0.25 * (1.0 - p[i][1])); else if(0.25 < h && h <= 0.5) h = Math.min(h,0.25 * (1.0 + p[i][1])); else if(0.5 < h && h <= 0.75) h = Math.max(h,0.25 * (3.0 - p[i][1])); else if(0.75 < h && h < 1.0) h = Math.min(h,0.25 * (3.0 + p[i][1])); double abs = Math.abs(refHue - h); if(abs <= 0.5) d[i] = 0.5 - abs; else d[i] = 0.5 - 1.0 + abs; } } private class IndexedDouble implements Comparable { double d; int i; IndexedDouble(double d,int i) { this.d = d; this.i = i; } public int compareTo(Object o){ IndexedDouble d = (IndexedDouble)o; if(this.d < d.d) return -1; else if(this.d > d.d) return 1; else return 0; } } /** * Compares the given arguments according to this ordering * * @param o1 first double valued array or vector pixel * @param o2 second double valued array or vector pixel * @return 1,-1 or 0 if o1 is respectively superior, inferior or equal to o2 */ public int compare(Object o1,Object o2) { double[][] v = new double[2][]; v[0] = (double[])o1; v[1] = (double[])o2; preprocess(v); if(d[0] < d[1]) return -1; else if(d[0] > d[1]) return 1; else return 0; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[], double[]) */ public double[] max(double[] p,double[] r) { if(compare(p,r) == 1) return p; else return r; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#min(double[], double[]) */ public double[] min(double[] p,double[] r) { if(compare(p,r) == 1) return r; else return p; } }