Source code for morphocut.contrib.zooprocess

"""
Feature calculation like in ZooProcess.

    `Zooprocess`_ is a suite of routines in ImageJ macro language
    for Plankton image analysis.

.. _Zooprocess: https://sites.google.com/view/piqv/zooprocess
"""

from typing import Optional

import numpy as np

from morphocut import Node, Output, RawOrVariable, ReturnOutputs


[docs]def regionprop2zooprocess(prop): """ Calculate zooprocess features from skimage regionprops. Notes: - date/time specify the time of the sampling, not of the processing. """ return { "label": prop.label, # width of the smallest rectangle enclosing the object "width": prop.bbox[3] - prop.bbox[1], # height of the smallest rectangle enclosing the object "height": prop.bbox[2] - prop.bbox[0], # X coordinates of the top left point of the smallest rectangle enclosing the object "bx": prop.bbox[1], # Y coordinates of the top left point of the smallest rectangle enclosing the object "by": prop.bbox[0], # circularity : (4∗π ∗Area)/Perim^2 a value of 1 indicates a perfect circle, a value approaching 0 indicates an increasingly elongated polygon "circ.": (4 * np.pi * prop.filled_area) / prop.perimeter ** 2, # Surface area of the object excluding holes, in square pixels (=Area*(1-(%area/100)) "area_exc": prop.area, # Surface area of the object in square pixels "area": prop.filled_area, # Percentage of object’s surface area that is comprised of holes, defined as the background grey level "%area": 1 - (prop.area / prop.filled_area), # Primary axis of the best fitting ellipse for the object "major": prop.major_axis_length, # Secondary axis of the best fitting ellipse for the object "minor": prop.minor_axis_length, # Y position of the center of gravity of the object "y": prop.centroid[0], # X position of the center of gravity of the object "x": prop.centroid[1], # The area of the smallest polygon within which all points in the objet fit "convex_area": prop.convex_area, # Minimum grey value within the object (0 = black) "min": prop.min_intensity, # Maximum grey value within the object (255 = white) "max": prop.max_intensity, # Average grey value within the object ; sum of the grey values of all pixels in the object divided by the number of pixels "mean": prop.mean_intensity, # Integrated density. The sum of the grey values of the pixels in the object (i.e. = Area*Mean) "intden": prop.filled_area * prop.mean_intensity, # The length of the outside boundary of the object "perim.": prop.perimeter, # major/minor "elongation": np.divide(prop.major_axis_length, prop.minor_axis_length), # max-min "range": prop.max_intensity - prop.min_intensity, # perim/area_exc "perimareaexc": prop.perimeter / prop.area, # perim/major "perimmajor": prop.perimeter / prop.major_axis_length, # (4 ∗ π ∗ Area_exc)/perim 2 "circex": np.divide(4 * np.pi * prop.area, prop.perimeter ** 2), # Angle between the primary axis and a line parallel to the x-axis of the image "angle": prop.orientation / np.pi * 180 + 90, # # X coordinate of the top left point of the image # 'xstart': data_object['raw_img']['meta']['xstart'], # # Y coordinate of the top left point of the image # 'ystart': data_object['raw_img']['meta']['ystart'], # Maximum feret diameter, i.e. the longest distance between any two points along the object boundary # 'feret': data_object['raw_img']['meta']['feret'], # feret/area_exc # 'feretareaexc': data_object['raw_img']['meta']['feret'] / property.area, # perim/feret # 'perimferet': property.perimeter / data_object['raw_img']['meta']['feret'], "bounding_box_area": prop.bbox_area, "eccentricity": prop.eccentricity, "equivalent_diameter": prop.equivalent_diameter, "euler_number": prop.euler_number, "extent": prop.extent, "local_centroid_col": prop.local_centroid[1], "local_centroid_row": prop.local_centroid[0], "solidity": prop.solidity, }
[docs]@ReturnOutputs @Output("meta") class CalculateZooProcessFeatures(Node): """ Calculate descriptive features similar to ZooProcess using :py:func:`skimage.measure.regionprops`. Args: regionprops (RegionProperties or Variable): :py:class:`~skimage.measure._regionprops.RegionProperties` instance returned by :py:class:`FindRegions`. meta (dict or Variable, optional): Meta-data dictionary to update. prefix (str or Variable, optional): Prefix for all keys. Example: .. code-block:: python with Pipeline() as p: image = ... mask = ... regionprops = FindRegions(mask, image) features = CalculateZooProcessFeatures(regionprops) """ def __init__( self, regionprops: RawOrVariable, meta: Optional[RawOrVariable[dict]] = None, prefix: Optional[RawOrVariable[str]] = None, ): super().__init__() self.regionprops = regionprops self.meta = meta self.prefix = prefix def transform(self, regionprops, meta, prefix): if meta is None: meta = {} features = regionprop2zooprocess(regionprops) if prefix is not None: features = {"{}{}".format(self.prefix, k): v for k, v in features.items()} return {**meta, **features}