imcflibs.imagej.labelimage

Functions to work with ImageJ label images.

  1"""Functions to work with ImageJ label images."""
  2
  3from ij import IJ, ImagePlus, Prefs
  4from ij.plugin import Duplicator, ImageCalculator
  5from ij.plugin.filter import ImageProcessor, ThresholdToSelection
  6from ij.process import FloatProcessor, ImageProcessor
  7from inra.ijpb.label import LabelImages as li
  8from inra.ijpb.plugins import AnalyzeRegions
  9
 10
 11def label_image_to_roi_list(label_image, low_thresh=None):
 12    """Convert a label image to a list of ROIs.
 13
 14    Parameters
 15    ----------
 16    label_image : ij.ImagePlus
 17        Label image to convert.
 18    low_thresh : int, optional
 19        Value under which the labels should be discarded, by default `None`.
 20
 21    Returns
 22    -------
 23    roi_list : list(ij.gui.Roi)
 24        List of all the ROIs converted from the label image.
 25    """
 26
 27    roi_list = []
 28    max_value = 0
 29
 30    for slice in range(1, label_image.getNSlices() + 1):
 31        label_image_slice = Duplicator().run(label_image, 1, 1, slice, slice, 1, 1)
 32
 33        image_processor = label_image_slice.getProcessor()
 34        pixels = image_processor.getFloatArray()
 35
 36        existing_pixel_values = set()
 37
 38        for x in range(0, image_processor.getWidth()):
 39            for y in range(0, image_processor.getHeight()):
 40                existing_pixel_values.add(pixels[x][y])
 41
 42        # Converts data in case it's RGB image
 43        float_processor = FloatProcessor(
 44            image_processor.getWidth(), image_processor.getHeight()
 45        )
 46        float_processor.setFloatArray(pixels)
 47        img_float_copy = ImagePlus("FloatLabel", float_processor)
 48
 49        # print(existing_pixel_values)
 50        for value in existing_pixel_values:
 51            if low_thresh is not None:
 52                if value < low_thresh:
 53                    continue
 54            elif value == 0:
 55                continue
 56            # print(value)
 57            float_processor.setThreshold(value, value, ImageProcessor.NO_LUT_UPDATE)
 58            roi = ThresholdToSelection.run(img_float_copy)
 59            roi.setName(str(value))
 60            roi.setPosition(slice)
 61            roi_list.append(roi)
 62            max_value = max(max_value, value)
 63
 64    return roi_list, max_value
 65
 66
 67def relate_label_images(label_image_ref, label_image_to_relate):
 68    """Relate label images, giving the same label to objects belonging together.
 69
 70    ❗ NOTE: Won't work with touching labels ❗
 71
 72    FIXME: explain with an example what the function is doing!
 73
 74    Parameters
 75    ----------
 76    label_image_ref : ij.ImagePlus
 77        Reference to use for the labels.
 78    label_image_to_relate : ij.ImagePlus
 79        Image to change for the labels.
 80
 81    Returns
 82    -------
 83    ij.ImagePlus
 84        New ImagePlus with modified labels matching the reference.
 85    """
 86
 87    imp_dup = label_image_to_relate.duplicate()
 88    IJ.setRawThreshold(imp_dup, 1, 65535)
 89    Prefs.blackBackground = True
 90    IJ.run(imp_dup, "Convert to Mask", "")
 91    IJ.run(imp_dup, "Divide...", "value=255")
 92    return ImageCalculator.run(label_image_ref, imp_dup, "Multimage_processorly create")
 93
 94
 95def filter_objects(label_image, table, string, min_val, max_val):
 96    """Filter labels based on specific min and max values.
 97
 98    Parameters
 99    ----------
100    label_image : ij.ImagePlus
101        Label image on which to filter.
102    table : ResultsTable
103        ResultsTable containing all the measurements on which to filter.
104    string : str
105        Measurement name on which to filter, e.g. `Area`, `Mean Intensity` etc.
106    min_val : float
107        Minimum value to keep.
108    max_val : float
109        Maximum value to keep
110
111    Returns
112    -------
113    ij.ImagePlus
114        Label image containing only the remaining labels.
115    """
116
117    keep_label_id = []
118    for row in range(table.size()):
119        current_value = table.getValue(string, row)
120        if current_value >= min_val and current_value <= max_val:
121            keep_label_id.append(int(table.getLabel(row)))
122
123    return li.keepLabels(label_image, keep_label_id)
124
125
126def measure_objects_size_shape_2d(label_image):
127    """Measure the shapes of the different labels.
128
129    Parameters
130    ----------
131    label_image : ij.ImagePlus
132        Label image on which to get the shapes.
133
134    Returns
135    -------
136    ResultsTable
137        ResultsTable with the shape measurements.
138    """
139    regions = AnalyzeRegions()
140    return regions.process(label_image)
def label_image_to_roi_list(label_image, low_thresh=None):
12def label_image_to_roi_list(label_image, low_thresh=None):
13    """Convert a label image to a list of ROIs.
14
15    Parameters
16    ----------
17    label_image : ij.ImagePlus
18        Label image to convert.
19    low_thresh : int, optional
20        Value under which the labels should be discarded, by default `None`.
21
22    Returns
23    -------
24    roi_list : list(ij.gui.Roi)
25        List of all the ROIs converted from the label image.
26    """
27
28    roi_list = []
29    max_value = 0
30
31    for slice in range(1, label_image.getNSlices() + 1):
32        label_image_slice = Duplicator().run(label_image, 1, 1, slice, slice, 1, 1)
33
34        image_processor = label_image_slice.getProcessor()
35        pixels = image_processor.getFloatArray()
36
37        existing_pixel_values = set()
38
39        for x in range(0, image_processor.getWidth()):
40            for y in range(0, image_processor.getHeight()):
41                existing_pixel_values.add(pixels[x][y])
42
43        # Converts data in case it's RGB image
44        float_processor = FloatProcessor(
45            image_processor.getWidth(), image_processor.getHeight()
46        )
47        float_processor.setFloatArray(pixels)
48        img_float_copy = ImagePlus("FloatLabel", float_processor)
49
50        # print(existing_pixel_values)
51        for value in existing_pixel_values:
52            if low_thresh is not None:
53                if value < low_thresh:
54                    continue
55            elif value == 0:
56                continue
57            # print(value)
58            float_processor.setThreshold(value, value, ImageProcessor.NO_LUT_UPDATE)
59            roi = ThresholdToSelection.run(img_float_copy)
60            roi.setName(str(value))
61            roi.setPosition(slice)
62            roi_list.append(roi)
63            max_value = max(max_value, value)
64
65    return roi_list, max_value

Convert a label image to a list of ROIs.

Parameters
  • label_image (ij.ImagePlus): Label image to convert.
  • low_thresh (int, optional): Value under which the labels should be discarded, by default None.
Returns
  • roi_list (list(ij.gui.Roi)): List of all the ROIs converted from the label image.
def relate_label_images(label_image_ref, label_image_to_relate):
68def relate_label_images(label_image_ref, label_image_to_relate):
69    """Relate label images, giving the same label to objects belonging together.
70
71    ❗ NOTE: Won't work with touching labels ❗
72
73    FIXME: explain with an example what the function is doing!
74
75    Parameters
76    ----------
77    label_image_ref : ij.ImagePlus
78        Reference to use for the labels.
79    label_image_to_relate : ij.ImagePlus
80        Image to change for the labels.
81
82    Returns
83    -------
84    ij.ImagePlus
85        New ImagePlus with modified labels matching the reference.
86    """
87
88    imp_dup = label_image_to_relate.duplicate()
89    IJ.setRawThreshold(imp_dup, 1, 65535)
90    Prefs.blackBackground = True
91    IJ.run(imp_dup, "Convert to Mask", "")
92    IJ.run(imp_dup, "Divide...", "value=255")
93    return ImageCalculator.run(label_image_ref, imp_dup, "Multimage_processorly create")

Relate label images, giving the same label to objects belonging together.

❗ NOTE: Won't work with touching labels ❗

FIXME: explain with an example what the function is doing!

Parameters
  • label_image_ref (ij.ImagePlus): Reference to use for the labels.
  • label_image_to_relate (ij.ImagePlus): Image to change for the labels.
Returns
  • ij.ImagePlus: New ImagePlus with modified labels matching the reference.
def filter_objects(label_image, table, string, min_val, max_val):
 96def filter_objects(label_image, table, string, min_val, max_val):
 97    """Filter labels based on specific min and max values.
 98
 99    Parameters
100    ----------
101    label_image : ij.ImagePlus
102        Label image on which to filter.
103    table : ResultsTable
104        ResultsTable containing all the measurements on which to filter.
105    string : str
106        Measurement name on which to filter, e.g. `Area`, `Mean Intensity` etc.
107    min_val : float
108        Minimum value to keep.
109    max_val : float
110        Maximum value to keep
111
112    Returns
113    -------
114    ij.ImagePlus
115        Label image containing only the remaining labels.
116    """
117
118    keep_label_id = []
119    for row in range(table.size()):
120        current_value = table.getValue(string, row)
121        if current_value >= min_val and current_value <= max_val:
122            keep_label_id.append(int(table.getLabel(row)))
123
124    return li.keepLabels(label_image, keep_label_id)

Filter labels based on specific min and max values.

Parameters
  • label_image (ij.ImagePlus): Label image on which to filter.
  • table (ResultsTable): ResultsTable containing all the measurements on which to filter.
  • string (str): Measurement name on which to filter, e.g. Area, Mean Intensity etc.
  • min_val (float): Minimum value to keep.
  • max_val (float): Maximum value to keep
Returns
  • ij.ImagePlus: Label image containing only the remaining labels.
def measure_objects_size_shape_2d(label_image):
127def measure_objects_size_shape_2d(label_image):
128    """Measure the shapes of the different labels.
129
130    Parameters
131    ----------
132    label_image : ij.ImagePlus
133        Label image on which to get the shapes.
134
135    Returns
136    -------
137    ResultsTable
138        ResultsTable with the shape measurements.
139    """
140    regions = AnalyzeRegions()
141    return regions.process(label_image)

Measure the shapes of the different labels.

Parameters
  • label_image (ij.ImagePlus): Label image on which to get the shapes.
Returns
  • ResultsTable: ResultsTable with the shape measurements.