package fr.unistra.pelican.algorithms.morphology.binary; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.Image; import fr.unistra.pelican.BooleanImage; import fr.unistra.pelican.util.morphology.FlatStructuringElement2D; /** * Performs a binary granulometry with a square shaped flat structuring element. * Optional flag allow the use of line structuring elements. * * @author Aptoula, Lefevre */ public class BinarySquareGranulometry extends Algorithm { /** * Image to be processed */ public Image input; /** * Size of the square structuring element */ public Integer length; /** * Indicates if structuring element is convex or not */ public Boolean flag; /** * Indicates if horizontal line structuring element should be used */ public boolean horizontalOnly = false; /** * Indicates if vertical line structuring element should be used */ public boolean verticalOnly = false; /** * Indicates if pattern spectrum should be computed instead of standard * granulometry */ public boolean diff = false; /** * Resulting granulometry */ public Double[] output; /** * Constructor * */ public BinarySquareGranulometry() { super.inputs = "input,length,flag"; super.outputs = "output"; super.options = "diff,horizontalOnly,verticalOnly"; } /* * (non-Javadoc) * * @see fr.unistra.pelican.Algorithm#launch() */ public void launch() throws AlgorithmException { int size = length * input.getBDim(); // size of SEs increases in // steps of 2 output = new Double[size]; int MOMENTX = 0; int MOMENTY = 0; double original2 = input.volume(); // every size for (int i = 0; i < length; i++) { int side = i * 2 + 1; BooleanImage seHor = FlatStructuringElement2D .createHorizontalLineFlatStructuringElement(side); BooleanImage seVer = FlatStructuringElement2D .createVerticalLineFlatStructuringElement(side); // schnell Hans, schnell!!! Image tmp = input; if (!verticalOnly) tmp = BinaryErosion.exec(tmp, seHor, flag); if (!horizontalOnly) tmp = BinaryErosion.exec(tmp, seVer, flag); if (!verticalOnly) tmp = BinaryDilation.exec(tmp, seHor, flag); if (!horizontalOnly) tmp = BinaryDilation.exec(tmp, seVer, flag); for (int b = 0; b < input.getBDim(); b++) output[b * length + i] = moment(tmp, b, MOMENTX, MOMENTY, 0) / original2; } if (diff) { Double[] output2 = new Double[output.length]; for (int i = 0; i < length; i++) for (int b = 0; b < input.getBDim(); b++) { if (i == 0) output2[b * length + i] = 1.0 - output[b * length + i]; else output2[b * length + i] = output[b * length + i - 1] - output[b * length + i]; } output = output2; } } private double moment(Image img, int channel, int i, int j, int radius) { double d = 0.0; for (int x = radius; x < img.getXDim() - radius; x++) { for (int y = radius; y < img.getYDim() - radius; y++) { if ( img.isPresentXYB( x,y, channel ) ) d += ( img.getPixelXYBBoolean( x,y, channel ) ) ? 1 : 0; } } return d; } /** * This method performs a binary granulometry with a square shaped flat * structuring element. * * @param image * image to be processed * @param length * size of the square struturing element * @return granulometry array */ public static Double[] exec(Image input, Integer length, Boolean flag) { return (Double[]) new BinarySquareGranulometry().process(input, length, flag); } public static Double[] exec(Image input, Integer length, Boolean flag, boolean diff, boolean horizontalOnly, boolean verticalOnly) { return (Double[]) new BinarySquareGranulometry().process(input, length, flag, diff, horizontalOnly, verticalOnly); } }