upxo.charops.mchar module
mchar — Morphological characterisation of labelled feature images
Public interface for detecting and characterising connected features
(grains) in 2D and 3D labelled images. Delegates to the private
_mchar2d and _mchar3d sub-modules.
Functions
- detect_features(mcStateArray, connectivity=18, delta=0)
Detect and label connected features in a 3D state array using cc3d connectivity analysis.
- characterise_features_in_image_2d(labelled_image, Xgrid, Ygrid, …)
Characterise every labelled feature in a 2D image by building a binary mask per feature (supports padded bounding boxes, physical coordinates, and scikit-image region properties).
- characterise_features_in_image_v2(labelled_image, Xgrid=None, Ygrid=None, …)
Faster alternative to
characterise_features_in_image_2d. Uses a singleskimage.measure.regionpropspass over the full image and returns both tight and padded bounding boxes.
Usage
>>> import upxo.charops.mchar as mchar
>>> lfi, n_grains, conn = mchar.detect_features(state_array, connectivity=26)
>>> skp, bl, bl_ex, bx, bx_ex, coords = mchar.characterise_features_in_image_v2(lfi)
- upxo.charops.mchar.detect_features(mcStateArray, connectivity=18, delta=0)[source]
Detect features in 2D/3D image data using connectivity-based analysis. This function identifies and labels connected features in 3D image data based on specified connectivity criteria and a delta threshold parameter.
- Parameters:
mcStateArray (numpy.ndarray) – 3D array containing the image data to analyze for feature detection.
connectivity (int, optional) – Connectivity criterion for feature detection. Default is 18. Common values are 6 (face), 18 (face+edge), or 26 (face+edge+vertex).
delta (int or float, optional) – Threshold parameter for feature detection. Default is 0. Controls the sensitivity of feature detection.
- Returns:
lfi (numpy.ndarray) – Labeled feature image where each connected feature is assigned a unique integer label. Background is typically labeled as 0.
N (int) – Total number of features detected in the image data.
connectivity (int) – Connectivity provided by the user. Note: Use this to port value into the class attrtibute you are working with to maintain uniformity of connectivity in subsequent operations. In all subsequent operations make sure to pass the saved connectivity parameter value rather than having to create a new one. Think of tyhis output to force tyou to save this iff you are working through a class. Else, just ignore this output.
Notes
This function wraps the underlying _mchar3d.detect_features implementation for 3D morphological character analysis.
Usage
import upxo.charops.mchar as mchar Use as: mchar.detect_features
Examples
>>> import numpy as np >>> data = np.random.rand(10, 10, 10) >>> labeled_features, num_features = detect_features(data, connectivity=18) >>> print(f"Detected {num_features} features")
- upxo.charops.mchar.characterise_features_in_image_2d(labelled_image, Xgrid, Ygrid, make_skprops=True, extract_coords=True, throw_bounding_box=True)[source]
Characterise every labelled feature in a 2D image.
For each unique label in
labelled_imagethe function builds a binary mask, extracts an extended bounding-box crop (one pixel of padding on each open side), optionally computes scikit-image region properties on that crop, and optionally records the physical coordinates of every pixel.- Parameters:
labelled_image (numpy.ndarray of int, shape (R, C)) – Integer-labelled image where 0 is background and each positive integer identifies one feature (grain).
Xgrid (numpy.ndarray of float, shape (R, C)) – Physical X-coordinate at every pixel position.
Ygrid (numpy.ndarray of float, shape (R, C)) – Physical Y-coordinate at every pixel position.
make_skprops (bool, default True) – Compute
skimage.measure.regionpropson the extended bounding-box crop for each feature and store inskprops.extract_coords (bool, default True) – Record the physical (X, Y) coordinates of every pixel belonging to each feature in
coords_dict.throw_bounding_box (bool, default True) – Populate
bbox_limits_exandbboxes_exwith the extended bounding-box extents and binary crops.
- Returns:
skprops (dict[int, skimage.measure.RegionProperties or None]) – Feature ID → scikit-image region-properties object computed on the extended bounding-box crop. Values are
Nonewhenmake_skpropsis False.bbox_limits_ex (dict[int, list[int] or None]) – Feature ID →
[rmin_ex, rmax_ex, cmin_ex, cmax_ex]row/column slice indices of the one-pixel-padded bounding box. Values areNonewhenthrow_bounding_boxis False.bboxes_ex (dict[int, numpy.ndarray or None]) – Feature ID → binary uint8 crop of the extended bounding box. Values are
Nonewhenthrow_bounding_boxis False.coords_dict (dict[int, numpy.ndarray or None]) – Feature ID → array of shape (N_pixels, 2) containing the physical
[X, Y]coordinates of every pixel in the feature. Values areNonewhenextract_coordsis False.
Notes
This wrapper delegates to
upxo.charops._mchar2d.characterise_features_in_image_2d. For a faster alternative that also returns tight (non-padded) bounding boxes, usecharacterise_features_in_image_v2().Example
>>> import upxo.charops.mchar as mchar >>> skprops, bbox_limits_ex, bboxes_ex, coords = mchar.characterise_features_in_image_2d( ... labelled_image, Xgrid, Ygrid)
- upxo.charops.mchar.characterise_features_in_image_v2(labelled_image, Xgrid=None, Ygrid=None, make_skprops=True, extract_coords=True, throw_bounding_box=True)[source]
Characterise every labelled feature in a 2D image (faster, richer output).
An improved alternative to
characterise_features_in_image_2d()that callsskimage.measure.regionpropsonce on the full labelled image (avoiding per-feature mask construction) and returns both tight and one-pixel-padded bounding boxes.XgridandYgridare optional; if omitted, pixel-index grids are generated automatically.- Parameters:
labelled_image (numpy.ndarray of int, shape (R, C)) – Integer-labelled image where 0 is background and each positive integer identifies one feature (grain).
Xgrid (numpy.ndarray of float, shape (R, C) or None) – Physical X-coordinate at every pixel position. When
None, the column index is used as the X coordinate.Ygrid (numpy.ndarray of float, shape (R, C) or None) – Physical Y-coordinate at every pixel position. When
None, the row index is used as the Y coordinate.make_skprops (bool, default True) – Retain the
skimage.measure.RegionPropertiesobject for each feature inskprops.extract_coords (bool, default True) – Record the physical (X, Y) coordinates of every pixel belonging to each feature in
coords_dict.throw_bounding_box (bool, default True) – Populate both tight and extended bounding-box outputs.
- Returns:
skprops (dict[int, skimage.measure.RegionProperties or None]) – Feature ID → region-properties object from the full-image
regionpropscall. Values areNonewhenmake_skpropsis False.bbox_limits (dict[int, list[int] or None]) – Feature ID →
[rmin, rmax, cmin, cmax]tight bounding-box slice indices (clamped to image boundaries). Values areNonewhenthrow_bounding_boxis False.bbox_limits_ex (dict[int, list[int] or None]) – Feature ID →
[rmin_ex, rmax_ex, cmin_ex, cmax_ex]one-pixel-padded bounding-box slice indices. Values areNonewhenthrow_bounding_boxis False.bboxes (dict[int, numpy.ndarray or None]) – Feature ID → binary int32 crop of the tight bounding box. Values are
Nonewhenthrow_bounding_boxis False.bboxes_ex (dict[int, numpy.ndarray or None]) – Feature ID → binary int32 crop of the extended (padded) bounding box. Values are
Nonewhenthrow_bounding_boxis False.coords_dict (dict[int, numpy.ndarray or None]) – Feature ID → array of shape (N_pixels, 2) containing the physical
[X, Y]coordinates of every pixel in the feature. Values areNonewhenextract_coordsis False.
Notes
This wrapper delegates to
upxo.charops._mchar2d.characterise_features_in_image_v2. Unlike v1, this version usesregionpropson the whole image in a single pass, which is considerably faster for images with many features.Example
>>> import upxo.charops.mchar as mchar >>> skprops, bbox_lim, bbox_lim_ex, bboxes, bboxes_ex, coords = \ ... mchar.characterise_features_in_image_v2(labelled_image)
- upxo.charops.mchar.classify_grain_positions_2d(lgi, gid)[source]
Classify each grain as corner / edge / internal based on lgi pixel positions.
- Parameters:
lgi (numpy.ndarray of int, shape (R, C)) – Labelled grain image.
gid (array-like of int) – All grain IDs present in lgi.
- Returns:
positions – Position category → array of grain IDs. Categories: ‘top_left’, ‘top_right’, ‘bottom_left’, ‘bottom_right’, ‘pure_top’, ‘pure_bottom’, ‘pure_left’, ‘pure_right’, ‘top’, ‘bottom’, ‘left’, ‘right’, ‘boundary’, ‘corner’, ‘internal’.
- Return type:
- upxo.charops.mchar.build_grain_props(skprops, prop_flags, locs_list=None, gblocs_list=None, EPS=1e-10)[source]
Extract all flagged grain properties from skimage RegionProperties.
- Parameters:
skprops (dict[int, skimage.measure.RegionProperties]) – Mapping of grain ID → skimage RegionProperties object.
prop_flags (dict[str, bool]) – Which properties to compute (same keys as
self.prop_flag).locs_list (list[numpy.ndarray] or None) – Per-grain pixel-location arrays (needed when prop_flags[‘npixels’] is True).
gblocs_list (list[numpy.ndarray] or None) – Per-grain boundary location arrays (needed for npixels_gb / gb_length_px).
EPS (float) – Numerical guard for zero-denominator properties.
- Returns:
props – Extracted property lists keyed by property name.
- Return type: