package fr.unistra.pelican.algorithms.arithmetic; import java.util.TreeSet; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.BooleanImage; import fr.unistra.pelican.Image; import fr.unistra.pelican.IntegerImage; /** * Computes a new multiband binary image from a combination of the different * labels in the input image * * @author Lefevre */ public class LabelCombination extends Algorithm { /** * Input image */ public IntegerImage inputImage; /** * Number of combinations */ public int combinations; /** * Flag to consider background as label */ public boolean background = true; /** * Output image */ public BooleanImage outputImage; /** * Constructor */ public LabelCombination() { super.inputs = "inputImage,combinations"; super.outputs = "outputImage"; super.options = "background"; } private int binomial(int n, int k) { if (n < k) return 0; int max = Math.max(k, n - k); int min = Math.min(k, n - k); int result = 1; int div = 1; for (int i = max + 1; i <= n; i++) result *= i; for (int i = 2; i <= min; i++) div *= i; return result / div; } public void launch() throws AlgorithmException { // Count the number of labels TreeSet<Integer> set = new TreeSet<Integer>(); for (int p = 0; p < inputImage.size(); p++) if (background || inputImage.getPixelInt(p) != 0) set.add(inputImage.getPixelInt(p)); int labels = set.size(); Integer[] tab = new Integer[labels]; tab = set.toArray(tab); // FIXME: accept combinations > 5 int s = 0; int comb = Math.min(combinations, 5); int size = 0; for (int i = 1; i <= comb; i++) size += binomial(labels, i); outputImage = new BooleanImage(inputImage.getXDim(), inputImage.getYDim(), inputImage.getZDim(), inputImage.getTDim(), size); outputImage.setMask( inputImage.getMask() ); // Build the combinations Image temp = null; // Images with one cluster if (comb >= 1) for (int c1 = 0; c1 < labels; c1++) { temp = new BooleanImage(inputImage.getXDim(), inputImage.getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1); // System.out.println("cluster " + c1); for (int j = 0; j < inputImage.size(); j++) { if ( inputImage.isPresent(j) ) if (background || inputImage.getPixelInt(j) != 0) if (inputImage.getPixelInt(j) == tab[c1])// c1+start) temp.setPixelBoolean(j, true); else temp.setPixelBoolean(j, false); } outputImage.setImage4D(temp, s++, Image.B); } // Images with two clusters if (comb >= 2) for (int c1 = 0; c1 < labels; c1++) for (int c2 = c1 + 1; c2 < labels; c2++) { temp = new BooleanImage(inputImage.getXDim(), inputImage.getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1); // System.out.println("cluster " + c1 + ":" + c2); for (int j = 0; j < inputImage.size(); j++) { if ( inputImage.isPresent(j) ) if (background || inputImage.getPixelInt(j) != 0) if (inputImage.getPixelInt(j) == tab[c1]// c1 + start || inputImage.getPixelInt(j) == tab[c2])// c2 + start) temp.setPixelBoolean(j, true); else temp.setPixelBoolean(j, false); } outputImage.setImage4D(temp, s++, Image.B); } // Images with three clusters if (comb >= 3) for (int c1 = 0; c1 < labels; c1++) for (int c2 = c1 + 1; c2 < labels; c2++) for (int c3 = c2 + 1; c3 < labels; c3++) { temp = new BooleanImage(inputImage.getXDim(), inputImage.getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1); // System.out.println("cluster " + c1 + ":" + c2 + ":" + c3); for (int j = 0; j < inputImage.size(); j++) { if ( inputImage.isPresent(j) ) if (background || inputImage.getPixelInt(j) != 0) if (inputImage.getPixelInt(j) == tab[c1]// c1 + start || inputImage.getPixelInt(j) == tab[c2]// c2 + start || inputImage.getPixelInt(j) == tab[c3])// c3 + start) temp.setPixelBoolean(j, true); else temp.setPixelBoolean(j, false); } outputImage.setImage4D(temp, s++, Image.B); } // Images with four clusters if (comb >= 4) for (int c1 = 0; c1 < labels; c1++) for (int c2 = c1 + 1; c2 < labels; c2++) for (int c3 = c2 + 1; c3 < labels; c3++) for (int c4 = c3 + 1; c4 < labels; c4++) { temp = new BooleanImage(inputImage.getXDim(), inputImage .getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1); // System.out.println("cluster " + c1 + ":" + c2 + ":" + c3 + ":"+ // c4); for (int j = 0; j < inputImage.size(); j++) { if ( inputImage.isPresent(j) ) if (background || inputImage.getPixelInt(j) != 0) if (inputImage.getPixelInt(j) == tab[c1]// c1 + start || inputImage.getPixelInt(j) == tab[c2]// c2 + start || inputImage.getPixelInt(j) == tab[c3]// c3 + start || inputImage.getPixelInt(j) == tab[c4])// c4 + start) temp.setPixelBoolean(j, true); else temp.setPixelBoolean(j, false); } outputImage.setImage4D(temp, s++, Image.B); } // Images with five clusters if (comb >= 5) for (int c1 = 0; c1 < labels; c1++) for (int c2 = c1 + 1; c2 < labels; c2++) for (int c3 = c2 + 1; c3 < labels; c3++) for (int c4 = c3 + 1; c4 < labels; c4++) for (int c5 = c4 + 1; c5 < labels; c5++) { temp = new BooleanImage(inputImage.getXDim(), inputImage .getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1); // System.out.println("cluster " + c1 + ":" + c2 + ":" + c3 + // ":"+ c4 + ":" + c5); for (int j = 0; j < inputImage.size(); j++) { if ( inputImage.isPresent(j) ) if (background || inputImage.getPixelInt(j) != 0) if (inputImage.getPixelInt(j) == tab[c1]// c1 + start || inputImage.getPixelInt(j) == tab[c2]// c2 + start || inputImage.getPixelInt(j) == tab[c3]// c3 + start || inputImage.getPixelInt(j) == tab[c4]// c4 + start || inputImage.getPixelInt(j) == tab[c5])// c5 + start) temp.setPixelBoolean(j, true); else temp.setPixelBoolean(j, false); } outputImage.setImage4D(temp, s++, Image.B); } } /** * Computes a new boolean image from a combination of the different labels in * the input image * * @param inputImage * Input Image * @param combinations * Number of combinations * @return outputImage Output image */ public static BooleanImage exec(IntegerImage inputImage, int combinations) { return (BooleanImage) new LabelCombination().process(inputImage, combinations); } /** * Computes a new boolean image from a combination of the different labels in * the input image * * @param inputImage * Input Image * @param combinations * Number of combinations * @param background * Consider also the background * @return outputImage Output image */ public static BooleanImage exec(IntegerImage inputImage, int combinations, boolean background) { return (BooleanImage) new LabelCombination().process(inputImage, combinations, background); } }