All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mianalysis.mia.module.images.process.binary.DilateErode Maven / Gradle / Ivy

Go to download

ModularImageAnalysis (MIA) is an ImageJ plugin which provides a modular framework for assembling image and object analysis workflows. Detected objects can be transformed, filtered, measured and related. Analysis workflows are batch-enabled by default, allowing easy processing of high-content datasets.

There is a newer version: 1.7.0
Show newest version
package io.github.mianalysis.mia.module.images.process.binary;

import org.scijava.Priority;
import org.scijava.plugin.Plugin;

import ij.ImagePlus;
import ij.ImageStack;
import ij.plugin.Duplicator;
import ij.plugin.SubHyperstackMaker;
import ij.process.ImageProcessor;
import inra.ijpb.morphology.Morphology;
import inra.ijpb.morphology.Strel;
import inra.ijpb.morphology.Strel3D;
import io.github.mianalysis.mia.module.Categories;
import io.github.mianalysis.mia.module.Category;
import io.github.mianalysis.mia.module.Module;
import io.github.mianalysis.mia.module.Modules;
import io.github.mianalysis.mia.module.images.process.InvertIntensity;
import io.github.mianalysis.mia.object.Workspace;
import io.github.mianalysis.mia.object.image.Image;
import io.github.mianalysis.mia.object.image.ImageFactory;
import io.github.mianalysis.mia.object.parameters.BooleanP;
import io.github.mianalysis.mia.object.parameters.ChoiceP;
import io.github.mianalysis.mia.object.parameters.InputImageP;
import io.github.mianalysis.mia.object.parameters.OutputImageP;
import io.github.mianalysis.mia.object.parameters.Parameters;
import io.github.mianalysis.mia.object.parameters.SeparatorP;
import io.github.mianalysis.mia.object.parameters.choiceinterfaces.BinaryLogicInterface;
import io.github.mianalysis.mia.object.parameters.text.IntegerP;
import io.github.mianalysis.mia.object.refs.collections.ImageMeasurementRefs;
import io.github.mianalysis.mia.object.refs.collections.MetadataRefs;
import io.github.mianalysis.mia.object.refs.collections.ObjMeasurementRefs;
import io.github.mianalysis.mia.object.refs.collections.ObjMetadataRefs;
import io.github.mianalysis.mia.object.refs.collections.ParentChildRefs;
import io.github.mianalysis.mia.object.refs.collections.PartnerRefs;
import io.github.mianalysis.mia.object.system.Status;


/**
* Applies binary dilate or erode operations to an image in the workspace.  Dilate will expand all foreground-labelled regions by a specified number of pixels, while erode will shrink all foreground-labelled regions by the same ammount.

This image will be 8-bit with binary logic determined by the "Binary logic" parameter. If 2D operations are applied on higher dimensionality images the operations will be performed in a slice-by-slice manner. All operations (both 2D and 3D) use the plugin "MorphoLibJ". */ @Plugin(type = Module.class, priority=Priority.LOW, visible=true) public class DilateErode extends Module { /** * */ public static final String INPUT_SEPARATOR = "Image input/output"; /** * Image from workspace to apply dilate or erode operation to. */ public static final String INPUT_IMAGE = "Input image"; /** * When selected, the post-operation image will overwrite the input image in the workspace. Otherwise, the image will be saved to the workspace with the name specified by the "Output image" parameter. */ public static final String APPLY_TO_INPUT = "Apply to input image"; /** * If "Apply to input image" is not selected, the post-operation image will be saved to the workspace with this name. This image will be 8-bit with binary logic determined by the "Binary logic" parameter. */ public static final String OUTPUT_IMAGE = "Output image"; /** * */ public static final String OPERATION_SEPARATOR = "Operation controls"; /** * Controls what sort of dilate or erode operation is performed on the input image:
  • "Dilate 2D" Change any foreground-connected background pixels to foreground. This effectively expands objects by one pixel. Uses ImageJ implementation.
  • "Dilate 3D" Change any foreground-connected background pixels to foreground. This effectively expands objects by one pixel. Uses MorphoLibJ implementation.
  • "Erode 2D" Change any background-connected foreground pixels to background. This effectively shrinks objects by one pixel. Uses ImageJ implementation.
  • "Erode 3D" Change any background-connected foreground pixels to background. This effectively shrinks objects by one pixel. Uses MorphoLibJ implementation.
*/ public static final String OPERATION_MODE = "Filter mode"; /** * Number of times the operation will be run on a single image. Effectively, this allows objects to be dilated or eroded by a specific number of pixels. */ public static final String NUM_ITERATIONS = "Number of iterations"; /** * Controls whether objects are considered to be white (255 intensity) on a black (0 intensity) background, or black on a white background. */ public static final String BINARY_LOGIC = "Binary logic"; public DilateErode(Modules modules) { super("Dilate and erode", modules); } public interface OperationModes { String DILATE_2D = "Dilate 2D"; String DILATE_3D = "Dilate 3D"; String ERODE_2D = "Erode 2D"; String ERODE_3D = "Erode 3D"; String[] ALL = new String[] { DILATE_2D, DILATE_3D, ERODE_2D, ERODE_3D }; } public interface BinaryLogic extends BinaryLogicInterface { } public static void process(ImagePlus ipl, String operationMode, boolean blackBackground, int numIterations) { process(ipl, operationMode, blackBackground, numIterations, false); } public static void process(ImagePlus ipl, String operationMode, boolean blackBackground, int numIterations, boolean verbose) { String moduleName = new DilateErode(null).getName(); if (!blackBackground) InvertIntensity.process(ipl); int width = ipl.getWidth(); int height = ipl.getHeight(); int nChannels = ipl.getNChannels(); int nSlices = ipl.getNSlices(); int nFrames = ipl.getNFrames(); double dppXY = ipl.getCalibration().pixelWidth; double dppZ = ipl.getCalibration().pixelDepth; double ratio = dppXY / dppZ; Strel3D ballStrel = null; Strel diskStrel = null; int count = 0; int total = nChannels * nFrames; switch (operationMode) { case OperationModes.DILATE_2D: case OperationModes.ERODE_2D: diskStrel = Strel.Shape.DISK.fromRadius(numIterations); break; case OperationModes.DILATE_3D: case OperationModes.ERODE_3D: ballStrel = Strel3D.Shape.BALL.fromRadiusList(numIterations, numIterations, (int) Math.round(numIterations * ratio)); break; } for (int c = 1; c <= nChannels; c++) { for (int t = 1; t <= nFrames; t++) { ImagePlus iplOrig = SubHyperstackMaker.makeSubhyperstack(ipl, c + "-" + c, "1-" + nSlices, t + "-" + t); ImageStack istFilt = null; switch (operationMode) { case OperationModes.DILATE_2D: istFilt = Morphology.dilation(iplOrig.getImageStack(), diskStrel); break; case OperationModes.DILATE_3D: istFilt = Morphology.dilation(iplOrig.getImageStack(), ballStrel); break; case OperationModes.ERODE_2D: istFilt = Morphology.erosion(iplOrig.getImageStack(), diskStrel); break; case OperationModes.ERODE_3D: istFilt = Morphology.erosion(iplOrig.getImageStack(), ballStrel); break; } for (int z = 1; z <= istFilt.getSize(); z++) { ipl.setPosition(c, z, t); ImageProcessor iprOrig = ipl.getProcessor(); ImageProcessor iprFilt = istFilt.getProcessor(z); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { iprOrig.setf(x, y, iprFilt.getf(x, y)); } } } if (verbose) writeProgressStatus(count++, total, "images", moduleName); } } if (!blackBackground) InvertIntensity.process(ipl); } @Override public Category getCategory() { return Categories.IMAGES_PROCESS_BINARY; } @Override public String getVersionNumber() { return "1.0.0"; } @Override public String getDescription() { return "Applies binary dilate or erode operations to an image in the workspace. Dilate will expand all foreground-labelled regions by a specified number of pixels, while erode will shrink all foreground-labelled regions by the same ammount." + "

This image will be 8-bit with binary logic determined by the \"" + BINARY_LOGIC + "\" parameter. If 2D operations are applied on higher dimensionality images the operations will be performed in a slice-by-slice manner. All operations (both 2D and 3D) use the plugin \"MorphoLibJ\"."; } @Override public Status process(Workspace workspace) { // Getting input image String inputImageName = parameters.getValue(INPUT_IMAGE,workspace); Image inputImage = workspace.getImages().get(inputImageName); ImagePlus inputImagePlus = inputImage.getImagePlus(); // Getting parameters boolean applyToInput = parameters.getValue(APPLY_TO_INPUT,workspace); String outputImageName = parameters.getValue(OUTPUT_IMAGE,workspace); String operationMode = parameters.getValue(OPERATION_MODE,workspace); int numIterations = parameters.getValue(NUM_ITERATIONS,workspace); String binaryLogic = parameters.getValue(BINARY_LOGIC,workspace); boolean blackBackground = binaryLogic.equals(BinaryLogic.BLACK_BACKGROUND); // If applying to a new image, the input image is duplicated if (!applyToInput) inputImagePlus = new Duplicator().run(inputImagePlus); process(inputImagePlus, operationMode, blackBackground, numIterations); // If the image is being saved as a new image, adding it to the workspace if (!applyToInput) { Image outputImage = ImageFactory.createImage(outputImageName, inputImagePlus); workspace.addImage(outputImage); if (showOutput) outputImage.show(); } else { if (showOutput) inputImage.show(); } return Status.PASS; } @Override protected void initialiseParameters() { parameters.add(new SeparatorP(INPUT_SEPARATOR, this)); parameters.add(new InputImageP(INPUT_IMAGE, this)); parameters.add(new BooleanP(APPLY_TO_INPUT, this, true)); parameters.add(new OutputImageP(OUTPUT_IMAGE, this)); parameters.add(new SeparatorP(OPERATION_SEPARATOR, this)); parameters.add(new ChoiceP(OPERATION_MODE, this, OperationModes.DILATE_3D, OperationModes.ALL)); parameters.add(new IntegerP(NUM_ITERATIONS, this, 1)); parameters.add(new ChoiceP(BINARY_LOGIC, this, BinaryLogic.BLACK_BACKGROUND, BinaryLogic.ALL)); addParameterDescriptions(); } @Override public Parameters updateAndGetParameters() { Workspace workspace = null; Parameters returnedParameters = new Parameters(); returnedParameters.add(parameters.getParameter(INPUT_SEPARATOR)); returnedParameters.add(parameters.getParameter(INPUT_IMAGE)); returnedParameters.add(parameters.getParameter(APPLY_TO_INPUT)); if (!(boolean) parameters.getValue(APPLY_TO_INPUT,workspace)) returnedParameters.add(parameters.getParameter(OUTPUT_IMAGE)); returnedParameters.add(parameters.getParameter(OPERATION_SEPARATOR)); returnedParameters.add(parameters.getParameter(OPERATION_MODE)); returnedParameters.add(parameters.getParameter(NUM_ITERATIONS)); returnedParameters.add(parameters.getParameter(BINARY_LOGIC)); return returnedParameters; } @Override public ImageMeasurementRefs updateAndGetImageMeasurementRefs() { return null; } @Override public ObjMeasurementRefs updateAndGetObjectMeasurementRefs() { return null; } @Override public ObjMetadataRefs updateAndGetObjectMetadataRefs() { return null; } @Override public MetadataRefs updateAndGetMetadataReferences() { return null; } @Override public ParentChildRefs updateAndGetParentChildRefs() { return null; } @Override public PartnerRefs updateAndGetPartnerRefs() { return null; } @Override public boolean verify() { return true; } void addParameterDescriptions() { parameters.get(INPUT_IMAGE).setDescription( "Image from workspace to apply dilate or erode operation to."); parameters.get(APPLY_TO_INPUT).setDescription( "When selected, the post-operation image will overwrite the input image in the workspace. Otherwise, the image will be saved to the workspace with the name specified by the \"" + OUTPUT_IMAGE + "\" parameter."); parameters.get(OUTPUT_IMAGE).setDescription("If \"" + APPLY_TO_INPUT + "\" is not selected, the post-operation image will be saved to the workspace with this name. This image will be 8-bit with binary logic determined by the \"" + BINARY_LOGIC + "\" parameter."); parameters.get(OPERATION_MODE).setDescription( "Controls what sort of dilate or erode operation is performed on the input image:
    " + "
  • \"" + OperationModes.DILATE_2D + "\" Change any foreground-connected background pixels to foreground. This effectively expands objects by one pixel. Uses ImageJ implementation.
  • " + "
  • \"" + OperationModes.DILATE_3D + "\" Change any foreground-connected background pixels to foreground. This effectively expands objects by one pixel. Uses MorphoLibJ implementation.
  • " + "
  • \"" + OperationModes.ERODE_2D + "\" Change any background-connected foreground pixels to background. This effectively shrinks objects by one pixel. Uses ImageJ implementation.
  • " + "
  • \"" + OperationModes.ERODE_3D + "\" Change any background-connected foreground pixels to background. This effectively shrinks objects by one pixel. Uses MorphoLibJ implementation.
"); parameters.get(NUM_ITERATIONS).setDescription( "Number of times the operation will be run on a single image. Effectively, this allows objects to be dilated or eroded by a specific number of pixels."); parameters.get(BINARY_LOGIC).setDescription(BinaryLogicInterface.getDescription()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy