package fr.unistra.pelican.algorithms.segmentation;
import java.util.Vector;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.IntegerImage;
import fr.unistra.pelican.algorithms.histogram.Histogram;
/**
* HistogramBasedClustering
*
* @author weber,lefevre
*
*/
public class HistogramBasedClustering extends Algorithm {
// Inputs
/**
* Image to cluster
*/
public Image inputImage;
/**
* Threshold
*/
public double thresh;
/**
* Flag to ignore black pixels
*/
public boolean ignore=false;
// Outputs
/**
* Resulting Clusters
*/
public Image outputImage;
/**
* Resulting number of clusters
*/
public int nbClusters;
/**
* Constructor
*
*/
public HistogramBasedClustering() {
super.inputs = "inputImage,thresh";
super.options="ignore";
super.outputs = "outputImage,nbClusters";
}
public static Image exec(Image inputImage, double thr) {
return (Image) new HistogramBasedClustering().process(inputImage,thr);
}
public void launch() throws AlgorithmException {
// Histogram computing
double[] histo = (double[]) new Histogram().process(inputImage);
if (ignore)
histo[0] = 0;
// Histogram smoothing
// histo=smoothMax(histo);
histo = average(histo);
// equivalent to opening 3
histo = smoothMin(histo);
histo = smoothMax(histo);
// equivalent to closing 5
histo = smoothMax(histo);
histo = smoothMax(histo);
histo = smoothMin(histo);
histo = smoothMin(histo);
// Clustering 1st step
Image clusterImage = new IntegerImage(inputImage, false);
Vector<Object> cluster = new Vector<Object>();
double max = 0;
double total = 0;
double pointsAffectes = 0, pointsCluster;
for (int i = 0; i < histo.length; i++)
total = total + histo[i];
System.out.println("total:" + total+ "\t thresh: "+thresh+" => "+(thresh*total));
int centroide = -1, borneInf, borneSup;
while (pointsAffectes < thresh * total) {
for (int i = 0; i < histo.length; i++)
if (histo[i] > max) {
max = histo[i];
centroide = i;
}
cluster.add(centroide);
borneInf = centroide;
borneSup = centroide;
for (int i = centroide + 1; i < 255 && histo[i] <= histo[i - 1]
&& histo[i] > 0; i++)
borneSup = i;
for (int i = centroide - 1; i > 0 && histo[i] <= histo[i + 1]
&& histo[i] > 0; i--)
borneInf = i;
pointsCluster = 0;
for (int i = borneInf; i <= borneSup; i++) {
pointsCluster = pointsCluster + histo[i];
histo[i] = 0.;
}
pointsAffectes = pointsAffectes + pointsCluster;
System.out.println("indice = " + cluster.size() + " inf = "
+ borneInf + " sup = " + borneSup + " taille = "
+ pointsCluster + " total = " + pointsAffectes);
for (int i = 0; i < inputImage.size(); i++)
if (inputImage.getPixelByte(i) >= borneInf
&& inputImage.getPixelByte(i) <= borneSup)
clusterImage.setPixelInt(i, cluster.size());
max = 0;
}
outputImage = clusterImage;
nbClusters = cluster.size();
}
double[] average(double[] histo) {
double histo2[] = new double[histo.length];
for (int h = 1; h < histo2.length - 1; h++)
histo2[h] = Math
.ceil((histo[h - 1] + histo[h] + histo[h + 1]) / 3.0);
histo2[0] = Math.ceil((histo[0] + histo[1]) / 2.0);
histo2[histo2.length - 1] = Math
.ceil((histo[histo.length - 2] + histo[histo.length - 1]) / 2.0);
return histo2;
}
double[] smoothMax(double[] histo) {
double histo2[] = new double[histo.length];
for (int h = 1; h < histo2.length - 1; h++)
histo2[h] = Math
.max(histo[h - 1], Math.max(histo[h], histo[h + 1]));
histo2[0] = Math.max(histo[0], histo[1]);
histo2[histo2.length - 1] = Math.max(histo[histo.length - 2],
histo[histo.length - 1]);
return histo2;
}
double[] smoothMin(double[] histo) {
double histo2[] = new double[histo.length];
for (int h = 1; h < histo2.length - 1; h++)
histo2[h] = Math
.min(histo[h - 1], Math.min(histo[h], histo[h + 1]));
histo2[0] = Math.min(histo[0], histo[1]);
histo2[histo2.length - 1] = Math.min(histo[histo.length - 2],
histo[histo.length - 1]);
return histo2;
}
}