package fr.unistra.pelican.algorithms.segmentation.flatzones; import java.util.ArrayList; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.Image; import fr.unistra.pelican.IntegerImage; import fr.unistra.pelican.util.Point4D; /** * Only deal with Gray Level Image. X,Y,Z,T dimensions are taken into account. * * Algorithm is mine and quick made, probably better implementation exists but this one is quite fast. * * @author Jonathan Weber * */ public class GrayFlatZones extends Algorithm { /** * Image to process */ public Image inputImage; /** * Connectivity used to determine the flat zones */ public Point4D[] neighbourhood;; /** * Flat Zones labels */ public IntegerImage outputImage; private static final int INITVALUE = -2; private static final int INQUEUE = -1; private ArrayList<Point4D> neighboursToExpand; private int xDim; private int yDim; private int zDim; private int tDim; private int pixelValue; private int locX; private int locY; private int locZ; private int locT; private int pixelIndex; private int outputIndex; private int i; private int currentLabel; private Point4D currentPoint; /** * Constructor * */ public GrayFlatZones() { super(); super.inputs = "inputImage,neighbourhood"; super.outputs = "outputImage"; } @Override public void launch() throws AlgorithmException { if(inputImage.getBDim()==1) { xDim = inputImage.getXDim(); yDim = inputImage.getYDim(); zDim = inputImage.getZDim(); tDim = inputImage.getTDim(); neighboursToExpand = new ArrayList<Point4D>(); outputImage = inputImage.newIntegerImage(); outputImage.fill(INITVALUE); currentLabel=-1; pixelIndex=outputImage.size(); for(int t=tDim;--t>=0;) for(int z=zDim;--z>=0;) for(int y=yDim;--y>=0;) for(int x=xDim;--x>=0;) if(outputImage.getPixelInt(--pixelIndex)==INITVALUE) { outputImage.setPixelInt(pixelIndex, ++currentLabel); addUnlabelledNeighboursRespectToKValueToQueue(x, y, z, t); while(neighboursToExpand.size()!=0) { expandCurrentLabelTo(neighboursToExpand.remove(0)); } } } else { throw new AlgorithmException("inputImage must be a gray level image"); } } private final void expandCurrentLabelTo(Point4D pixel) { outputImage.setPixelXYZTInt(pixel.x, pixel.y, pixel.z, pixel.t, currentLabel); addUnlabelledNeighboursRespectToKValueToQueue(pixel.x, pixel.y, pixel.z, pixel.t); } private final void addUnlabelledNeighboursRespectToKValueToQueue(int x, int y, int z, int t) { pixelValue = inputImage.getPixelXYZTByte(x, y, z, t); for(i=neighbourhood.length;--i>=0;) { currentPoint = neighbourhood[i]; locX = x + currentPoint.x; locY = y + currentPoint.y; locZ = z + currentPoint.z; locT = t + currentPoint.t; if(locX>=0&&locY>=0&&locZ>=0&&locT>=0&&locX<xDim&&locY<yDim&&locZ<zDim&&locT<tDim) { outputIndex = outputImage.getLinearIndexXYZT_(locX, locY, locZ, locT); if(outputImage.getPixelInt(outputIndex)==INITVALUE) { if(pixelValue==inputImage.getPixelByte(outputIndex)) { neighboursToExpand.add(new Point4D(locX, locY, locZ, locT)); outputImage.setPixelInt(outputIndex,INQUEUE); } } } } } public static IntegerImage exec(Image inputImage, Point4D[] neighbourhood) { return (IntegerImage)new GrayFlatZones().process(inputImage,neighbourhood); } }