package fr.unistra.pelican.algorithms.morphology.binary; import java.awt.Point; import java.util.Stack; import java.util.Vector; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.BooleanImage; import fr.unistra.pelican.Image; /** * Filters 8-connected background components from a boolean image with a size criterion * (number of pixels) * * @author Lefevre * */ public class BinaryAreaClosing extends Algorithm { /** * Input image */ public Image inputImage; /** * Threshold for connected component size */ public int thresh; /** * Mask image to remember what has been explored */ private BooleanImage mask; /** * X dimension of input image */ private int dimX; /** * Y dimension of input image */ private int dimY; /** * Output Image */ public Image outputImage; /** * Constructor * */ public BinaryAreaClosing() { super.inputs = "inputImage,thresh"; super.outputs = "outputImage"; } /** * Erase the connected component containing s if its size if lower than the * threshold * * @param s * Seed of connected component */ private void filter(Stack<Point> s) { Vector<Point> vp = new Vector<Point>(); int size = 0; /** * Build a vector of every points of the connected component */ while (!s.isEmpty()) { Point p = s.pop(); if (p.x >= 0 && p.x < dimX && p.y >= 0 && p.y < dimY && inputImage.isPresentXY( p.x,p.y ) && !mask.getPixelXYBoolean(p.x, p.y))// && // inputImage.getPixelXYBoolean(p.x,p.y) // ) { mask.setPixelXYBoolean(p.x, p.y, true); vp.add(p); size++; s.push(new Point(p.x + 1, p.y - 1)); s.push(new Point(p.x + 1, p.y)); s.push(new Point(p.x + 1, p.y + 1)); s.push(new Point(p.x - 1, p.y + 1)); s.push(new Point(p.x - 1, p.y)); s.push(new Point(p.x - 1, p.y - 1)); s.push(new Point(p.x, p.y - 1)); s.push(new Point(p.x, p.y + 1)); } } /** * Erase it if under threshold */ if (size < thresh) for (Point p : vp) outputImage.setPixelXYBoolean(p.x, p.y, true); } /* * (non-Javadoc) * * @see fr.unistra.pelican.Algorithm#launch() */ public void launch() throws AlgorithmException { outputImage = inputImage.copyImage(true); mask = new BooleanImage(inputImage,true); //inputImage.copyImage(true); // mask.fill(1.0); dimX = inputImage.getXDim(); dimY = inputImage.getYDim(); for (int i = 0; i < dimX; i++) for (int j = 0; j < dimY; j++) { if ( inputImage.isPresentXY(i,j) && !mask.getPixelXYBoolean(i, j)) { Stack<Point> s = new Stack<Point>(); s.push(new Point(i, j)); filter(s); } } } /** * This method filters 8-connected background component from a boolean image with a size criterion * (number of pixels) * @param inputImage image to be processed * @param thresh Threshold for connected component size * @return filtered picture */ @SuppressWarnings("unchecked") public static <T extends Image> T exec(T inputImage, Integer thresh) { return (T) new BinaryAreaClosing().process(inputImage, thresh); } }