package fr.unistra.pelican.util.vectorial.orders;
import java.util.Arrays;
import java.util.Comparator;
import fr.unistra.pelican.util.Tools;
import fr.unistra.pelican.util.vectorial.VectorPixel;
/**
* This class represents a vector ordering designed for Hue Saturation Luminance/Lightness type spaces.
* It consists of a weighted sum of its components. The dimension order is assumed as H-> S-> L.
*
* @author E.A.
*
*/
public class AdaptiveWeightedOrdering4 implements VectorialOrdering,Comparator
{
private double[] d = null;
// weights for each dimension.
private double a;
private double b;
private double c;
// hue slope
private double slope;
// hue offset
private double offset;
// sat slope
private double slope2;
// sat offset
private double offset2;
public double syc = 0;
public double esitlik = 0;
public double esitlik2 = 0;
private double refHue;
public AdaptiveWeightedOrdering4(double refHue)
{
this.refHue = refHue;
slope = 5.0;
offset = 0.5;
slope2 = 5.0;
offset2 = 0.5;
a = b = c = 1.0;
}
public AdaptiveWeightedOrdering4(double offset,double slope,double refHue)
{
this.refHue = refHue;
this.slope = slope;
this.offset = offset;
slope2 = 5.0;
offset2 = 0.5;
a = b = c = 1.0;
}
public AdaptiveWeightedOrdering4(double offset,double slope,double refHue,double offset2,double slope2)
{
this.refHue = refHue;
this.slope = slope;
this.offset = offset;
this.slope2 = slope2;
this.offset2 = offset2;
a = b = c = 1.0;
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[][])
*/
public double[] max(double[][] p)
{
double[] max = p[0];
for(int i = 1; i < p.length; i++){
if(this.compare(max,p[i]) < 0) max = p[i];
}
return max;
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#min(double[][])
*/
public double[] min(double[][] p)
{
double[] min = p[0];
for(int i = 1; i < p.length; i++){
if(this.compare(min,p[i]) > 0) min = p[i];
}
return 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];
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#order(fr.unistra.pelican.util.vectorial.VectorPixel[])
*/
public VectorPixel[] order(VectorPixel[] v)
{
double[][] p = new double[v.length][];
VectorPixel[] result = new VectorPixel[v.length];
for(int i = 0; i < v.length; i++)
p[i] = v[i].getVector();
preprocess(p);
IndexedDouble[] id = new IndexedDouble[d.length];
for(int i = 0; i < d.length; i++)
id[i] = new IndexedDouble(d[i],i);
Arrays.sort(id);
for(int i = 0; i < v.length; i++)
result[i] = v[id[i].i];
return result;
}
// scalarize every vector independently
private void preprocess(double[][] p)
{
d = new double[p.length];
for(int i = 0; i < d.length; i++)
d[i] = scalarize(p[i]);
}
double difference(double[] p1,double[] p2)
{
double h1,s1,y1;
double h2,s2,y2;
// luminances
y1 = c * p1[2];
y2 = c * p2[2];
double ydiff = y1 - y2;
// saturations
s1 = b * p1[1] * 1 / (( 1 + Math.exp(1.0 * slope2 * (y1 - offset2)))/* * ( 1 + Math.exp(-1.0 * slope * (p1[1] - offset)))*/);
s2 = b * p2[1] * 1 / (( 1 + Math.exp(1.0 * slope2 * (y2 - offset2)))/* * ( 1 + Math.exp(-1.0 * slope * (p2[1] - offset)))*/);
double sdiff = s1 - s2;
// hues
double tmp1 = 1;// / ( 1 + Math.exp(-1.0 * slope * (s1 - offset)));
double tmp2 = 1; /// ( 1 + Math.exp(-1.0 * slope * (s2 - offset)));
double abs1 = Math.abs(refHue - p1[0]); // \in [0,1[
double abs2 = Math.abs(refHue - p2[0]); // \in [0,1[
if(abs1 <= 0.5) h1 = 2 * a * tmp1 * (0.5 - abs1); // all 3 components must be in the [0,1] interval
else h1 = 2 * a * tmp1 * (0.5 - 1.0 + abs1);
if(abs2 <= 0.5) h2 = 2 * a * tmp2 * (0.5 - abs2); // all 3 components must be in the [0,1] interval
else h2 = 2 * a * tmp2 * (0.5 - 1.0 + abs2);
double hdiff = h1 - h2;
return Math.sqrt(ydiff * ydiff + sdiff * sdiff + 0.0 * hdiff * hdiff);
}
double scalarize(double[] z)
{
double h,s,y;
// luminance
y = c * z[2];
// saturation
s = b * z[1] * y;//1 / (( 1 + Math.exp(-1.0 * slope2 * (y - offset2))) * ( 1 + Math.exp(-1.0 * slope * (z[1] - offset))));
// hue
double tmp = 1 / ( 1 + Math.exp(-1.0 * slope * (s - offset)));
double abs = Math.abs(refHue - z[0]); // \in [0,1[
// ref e olan mesafe if den sonra..\in [0,0.5]
// dilation un en uzaktakini degil de en yakindakini vermesi icin
// mesafeyi tersine almali...yani 0.5 i ondan cikarmali.
// ayrica 2 ile carpmali ki toplam deger \in [0,1] olsun
if(abs <= 0.5) h = 2 * a * tmp *(0.5 - abs); // all 3 components must be in the [0,1] interval
else h = 2 * a * tmp * (0.5 - 1.0 + abs);
return Math.sqrt(y * y + s * s + h * h);
}
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(Math.abs(this.d - d.d) < Tools.epsilon) return 0;
else if(this.d < d.d) return -1;
else return 1;
}
}
/**
* 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);
syc++;
if(Math.abs(d[0] - d[1]) < Tools.epsilon) return 0;
else if(d[0] < d[1]) return -1;
else return 1;
/*
else{
esitlik++;
if(v[0][0] == v[1][0] && v[0][1] == v[1][1] && v[0][2] == v[1][2]) esitlik2++;
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;
}
}