Source code for cyto_dl.image.io.polygon_loader

from typing import Union

import numpy as np
from monai.transforms import Transform
from skimage.draw import polygon2mask


[docs]class PolygonLoaderd(Transform): """Convert numpy array of polygon vertices to a torch tensor.""" def __init__( self, keys: Union[list, str], shape_reference_key: str, propagate_3d: bool = True, missing_key_mode: str = "raise", ): """ Parameters ---------- keys: Union[list, str] keys containing polygon paths shape_reference_key: str key to base mask shape on propagate_3d: bool=True Whether to propagate 2D mask to 3D. Currently, only True is supported. missing_key_mode: str='raise' How to handle missing keys. Options are 'raise', 'ignore', and 'create'. Raise will raise a KeyError, ignore will do nothing, and create will create a new key with a blank mask. """ super().__init__() self.keys = keys self.shape_reference_key = shape_reference_key assert missing_key_mode in ("ignore", "raise", "create") self.missing_key_mode = missing_key_mode self.propagate_3d = propagate_3d if not self.propagate_3d: raise NotImplementedError("propagate_3d=False not implemented") def __call__(self, input_dict): """ Parameters ---------- input_dict: Dict[str, torch.Tensor] dict of CZYX tensors/metadata/paths """ for key in self.keys: if key in input_dict.keys() and input_dict[key] is not None: poly = np.load(input_dict[key], allow_pickle=True) mask_shape = input_dict[self.shape_reference_key].shape[-2:] mask = np.zeros(mask_shape) for p in poly: mask = np.logical_or(mask, polygon2mask(mask_shape, p)) if self.propagate_3d: mask = np.stack([mask] * input_dict[self.shape_reference_key].shape[1]) # all ones except for regions in polygon mask = ~mask input_dict[key] = np.expand_dims(mask > 0, 0) elif self.missing_key_mode == "raise": raise KeyError( f"key `{key}` not available. Available keys are {input_dict.keys()}" ) elif self.missing_key_mode == "create": input_dict[key] = np.ones_like(input_dict[self.shape_reference_key]) return input_dict