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

io.github.mianalysis.mia.module.objects.convert.ConvertImageToObjects 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.6.12
Show newest version
package io.github.mianalysis.mia.module.objects.convert;

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

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.objects.detect.IdentifyObjects;
import io.github.mianalysis.mia.module.objects.measure.intensity.MeasureObjectIntensity;
import io.github.mianalysis.mia.module.objects.track.TrackObjects;
import io.github.mianalysis.mia.object.Obj;
import io.github.mianalysis.mia.object.Objs;
import io.github.mianalysis.mia.object.VolumeTypesInterface;
import io.github.mianalysis.mia.object.Workspace;
import io.github.mianalysis.mia.object.coordinates.volume.VolumeType;
import io.github.mianalysis.mia.object.image.Image;
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.Parameters;
import io.github.mianalysis.mia.object.parameters.SeparatorP;
import io.github.mianalysis.mia.object.parameters.objects.OutputObjectsP;
import io.github.mianalysis.mia.object.parameters.objects.OutputTrackObjectsP;
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;
import io.github.mianalysis.mia.process.exceptions.IntegerOverflowException;
import io.github.mianalysis.mia.process.math.CumStat;

/**
 * Created by sc13967 on 04/05/2017.
 */

/**
* Converts objects encoded in a labelled image stack back into objects.  Each output object is comprised of all pixels in a single timepoint with the same pixel intensity.  As such, pixels need not be in direct contact to be assigned the same object.  For objects tracked through time, the image intensity can be interpreted as the ID of a parent track object.

Note: This module has different behaviour to the "Identify objects" module, which takes a binary image, identifies contiguous foreground regions and assigns new object IDs. */ @Plugin(type = Module.class, priority=Priority.LOW, visible=true) public class ConvertImageToObjects extends Module { /** * */ public static final String INPUT_SEPARATOR = "Image input"; /** * Labelled image to convert to objects. The background (non-object region) of this image should be black (0 intensity) and all pixels corresponding to the same object should have the same value. Objects can only exist in a single timepoint, so pixels of the same intensity but in different timepoints will be assigned to different objects. */ public static final String INPUT_IMAGE = "Input image"; /** * */ public static final String OUTPUT_SEPARATOR = "Object output"; /** * Output objects created by the conversion process. These will be stored in the workspace and be accessible via this name. */ public static final String OUTPUT_OBJECTS = "Output objects"; /** * The method used to store pixel coordinates. This only affects performance and memory usage, there is no difference in results obtained using difference storage methods.
  • "Pointlist" (default) stores object coordinates as a list of XYZ coordinates. This is most efficient for small objects, very thin objects or objects with lots of holes.
  • "Octree" stores objects in an octree format. Here, the coordinate space is broken down into cubes of different sizes, each of which is marked as foreground (i.e. an object) or background. Octrees are most efficient when there are lots of large cubic regions of the same label, as the space can be represented by larger (and thus fewer) cubes. This is best used when there are large, completely solid objects. If z-axis sampling is much larger than xy-axis sampling, it's typically best to opt for the quadtree method.
  • "Quadtree" stores objects in a quadtree format. Here, each Z-plane of the object is broken down into squares of different sizes, each of which is marked as foreground (i.e. an object) or background. Quadtrees are most efficient when there are lots of large square regions of the same label, as the space can be represented by larger (and thus fewer) squares. This is best used when there are large, completely solid objects.
*/ public static final String VOLUME_TYPE = "Volume type"; /** * When selected, the intensity of the image for each object will be assumed as corresponding to the ID of a parent track object. This allows track relationships for objects present in multiple timepoints to be loaded back into MIA. */ public static final String CREATE_TRACKS = "Create track objects"; /** * If creating track objects ("Create track objects" is selected), this is the name of the output tracks. These will be parents of the output objects. */ public static final String TRACK_OBJECTS_NAME = "Output track objects name"; public ConvertImageToObjects(Modules modules) { super("Convert image to objects", modules); } public interface VolumeTypes extends VolumeTypesInterface { } @Override public Category getCategory() { return Categories.OBJECTS_CONVERT; } @Override public String getVersionNumber() { return "1.0.0"; } @Override public String getDescription() { return "Converts objects encoded in a labelled image stack back into objects. Each output object is comprised of all pixels in a single timepoint with the same pixel intensity. As such, pixels need not be in direct contact to be assigned the same object. For objects tracked through time, the image intensity can be interpreted as the ID of a parent track object." + "

Note: This module has different behaviour to the \"" + new IdentifyObjects(null).getName() + "\" module, which takes a binary image, identifies contiguous foreground regions and assigns new object IDs."; } public static Objs createParents(Objs inputObjects, Image image, String parentsName) { Objs parentObjects = new Objs(parentsName, inputObjects); for (Obj inputObject : inputObjects.values()) { // Taking parent ID as the largest intensity within the object CumStat cs = MeasureObjectIntensity.measureIntensity(inputObject, image, false, false); int ID = (int) Math.round(cs.getMax()); // Getting corresponding parent object parentObjects.putIfAbsent(ID, new Obj(parentObjects, VolumeType.POINTLIST, ID)); Obj parentObject = parentObjects.get(ID); // Assigning relationships inputObject.addParent(parentObject); parentObject.addChild(inputObject); } return parentObjects; } @Override public Status process(Workspace workspace) { String inputImageName = parameters.getValue(INPUT_IMAGE,workspace); Image inputImage = workspace.getImages().get(inputImageName); String outputObjectsName = parameters.getValue(OUTPUT_OBJECTS,workspace); String volumeType = parameters.getValue(VOLUME_TYPE,workspace); boolean createParents = parameters.getValue(CREATE_TRACKS,workspace); String parentObjectsName = parameters.getValue(TRACK_OBJECTS_NAME,workspace); Objs objects = null; try { objects = inputImage.convertImageToObjects(VolumeTypesInterface.getVolumeType(volumeType), outputObjectsName); } catch (IntegerOverflowException e) { return Status.FAIL; } if (createParents) workspace.addObjects(createParents(objects, inputImage, parentObjectsName)); if (showOutput) if (createParents) TrackObjects.showObjects(objects, parentObjectsName); else objects.convertToImageIDColours().show(false); workspace.addObjects(objects); return Status.PASS; } @Override protected void initialiseParameters() { parameters.add(new SeparatorP(INPUT_SEPARATOR, this)); parameters.add(new InputImageP(INPUT_IMAGE, this)); parameters.add(new SeparatorP(OUTPUT_SEPARATOR, this)); parameters.add(new OutputObjectsP(OUTPUT_OBJECTS, this)); parameters.add(new ChoiceP(VOLUME_TYPE, this, VolumeTypes.POINTLIST, VolumeTypes.ALL)); parameters.add(new BooleanP(CREATE_TRACKS, this, false)); parameters.add(new OutputTrackObjectsP(TRACK_OBJECTS_NAME, this)); addParameterDescriptions(); } @Override public Parameters updateAndGetParameters() { Workspace workspace = null; Parameters returnedParameters = new Parameters(); returnedParameters.add(parameters.get(INPUT_SEPARATOR)); returnedParameters.add(parameters.get(INPUT_IMAGE)); returnedParameters.add(parameters.get(OUTPUT_SEPARATOR)); returnedParameters.add(parameters.get(OUTPUT_OBJECTS)); returnedParameters.add(parameters.get(VOLUME_TYPE)); returnedParameters.add(parameters.get(CREATE_TRACKS)); if ((boolean) parameters.getValue(CREATE_TRACKS,workspace)) returnedParameters.add(parameters.get(TRACK_OBJECTS_NAME)); 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() { Workspace workspace = null; ParentChildRefs returnedRelationships = new ParentChildRefs(); if ((boolean) parameters.getValue(CREATE_TRACKS,workspace)) { String childObjectsName = parameters.getValue(OUTPUT_OBJECTS,workspace); String parentObjectsName = parameters.getValue(TRACK_OBJECTS_NAME,workspace); returnedRelationships.add(parentChildRefs.getOrPut(parentObjectsName, childObjectsName)); } return returnedRelationships; } @Override public PartnerRefs updateAndGetPartnerRefs() { return null; } @Override public boolean verify() { return true; } void addParameterDescriptions() { parameters.get(INPUT_IMAGE).setDescription( "Labelled image to convert to objects. The background (non-object region) of this image should be black (0 intensity) and all pixels corresponding to the same object should have the same value. Objects can only exist in a single timepoint, so pixels of the same intensity but in different timepoints will be assigned to different objects."); parameters.get(OUTPUT_OBJECTS).setDescription( "Output objects created by the conversion process. These will be stored in the workspace and be accessible via this name."); parameters.get(VOLUME_TYPE).setDescription( "The method used to store pixel coordinates. This only affects performance and memory usage, there is no difference in results obtained using difference storage methods.
    " + "
  • \"" + VolumeTypes.POINTLIST + "\" (default) stores object coordinates as a list of XYZ coordinates. This is most efficient for small objects, very thin objects or objects with lots of holes.
  • " + "
  • \"" + VolumeTypes.OCTREE + "\" stores objects in an octree format. Here, the coordinate space is broken down into cubes of different sizes, each of which is marked as foreground (i.e. an object) or background. Octrees are most efficient when there are lots of large cubic regions of the same label, as the space can be represented by larger (and thus fewer) cubes. This is best used when there are large, completely solid objects. If z-axis sampling is much larger than xy-axis sampling, it's typically best to opt for the quadtree method.
  • " + "
  • \"" + VolumeTypes.QUADTREE + "\" stores objects in a quadtree format. Here, each Z-plane of the object is broken down into squares of different sizes, each of which is marked as foreground (i.e. an object) or background. Quadtrees are most efficient when there are lots of large square regions of the same label, as the space can be represented by larger (and thus fewer) squares. This is best used when there are large, completely solid objects.
"); parameters.get(CREATE_TRACKS).setDescription( "When selected, the intensity of the image for each object will be assumed as corresponding to the ID of a parent track object. This allows track relationships for objects present in multiple timepoints to be loaded back into MIA."); parameters.get(TRACK_OBJECTS_NAME).setDescription("If creating track objects (\"" + CREATE_TRACKS + "\" is selected), this is the name of the output tracks. These will be parents of the output objects."); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy