def __init__( self, keys: KeysCollection, meta_keys: Optional[KeysCollection] = None, meta_key_postfix: str = "meta_dict", ) -> None: """ Args: keys: keys of the corresponding items to be transformed. See also: :py:class:`monai.transforms.compose.MapTransform` meta_keys: explicitly indicate the key of the corresponding meta data dictionary. for example, for data with key `image`, the metadata by default is in `image_meta_dict`. the meta data is a dictionary object which contains: filename, original_shape, etc. it can be a sequence of string, map to the `keys`. if None, will try to construct meta_keys by `key_{meta_key_postfix}`. meta_key_postfix: if meta_keys is None and `key_{postfix}` was used to store the metadata in `LoadImaged`. So need the key to extract metadata for channel dim information, default is `meta_dict`. For example, for data with key `image`, metadata by default is in `image_meta_dict`. """ super().__init__(keys) self.adjuster = EnsureChannelFirst() self.meta_keys = ensure_tuple_rep(meta_keys, len(self.keys)) self.meta_key_postfix = ensure_tuple_rep(meta_key_postfix, len(self.keys))
def get_data( self, img, location: Tuple[int, int] = (0, 0), size: Optional[Tuple[int, int]] = None, level: int = 0, dtype: DtypeLike = np.uint8, grid_shape: Tuple[int, int] = (1, 1), patch_size: Optional[int] = None, ): """ Extract regions as numpy array from WSI image and return them. Args: img: a WSIReader image object loaded from a file, or list of CuImage objects location: (x_min, y_min) tuple giving the top left pixel in the level 0 reference frame, or list of tuples (default=(0, 0)) size: (height, width) tuple giving the region size, or list of tuples (default to full image size) This is the size of image at the given level (`level`) level: the level number, or list of level numbers (default=0) dtype: the data type of output image grid_shape: (row, columns) tuple define a grid to extract patches on that patch_size: (heigsht, width) the size of extracted patches at the given level """ if size is None: if location == (0, 0): # the maximum size is set to WxH size = (img.shape[0] // (2**level), img.shape[1] // (2**level)) print( f"Reading the whole image at level={level} with shape={size}" ) else: raise ValueError( "Size need to be provided to extract the region!") region = self._extract_region(img, location=location, size=size, level=level, dtype=dtype) metadata: Dict = {} metadata["spatial_shape"] = size metadata["original_channel_dim"] = -1 region = EnsureChannelFirst()(region, metadata) if patch_size is None: patches = region else: patches = self._extract_patches(region, patch_size=(patch_size, patch_size), grid_shape=grid_shape, dtype=dtype) return patches, metadata
def get_data( self, img, location: Tuple[int, int] = (0, 0), size: Optional[Tuple[int, int]] = None, level: int = 0, dtype: DtypeLike = np.uint8, grid_shape: Tuple[int, int] = (1, 1), patch_size: Optional[Union[int, Tuple[int, int]]] = None, ): """ Extract regions as numpy array from WSI image and return them. Args: img: a WSIReader image object loaded from a file, or list of CuImage objects location: (x_min, y_min) tuple giving the top left pixel in the level 0 reference frame, or list of tuples (default=(0, 0)) size: (height, width) tuple giving the region size, or list of tuples (default to full image size) This is the size of image at the given level (`level`) level: the level number, or list of level numbers (default=0) dtype: the data type of output image grid_shape: (row, columns) tuple define a grid to extract patches on that patch_size: (height, width) the size of extracted patches at the given level """ if self.reader_lib == "openslide" and size is None: # the maximum size is set to WxH size = ( img.shape[0] // (2**level) - location[0], img.shape[1] // (2**level) - location[1], ) region = self._extract_region(img, location=location, size=size, level=level, dtype=dtype) metadata: Dict = {} metadata["spatial_shape"] = size metadata["original_channel_dim"] = -1 region = EnsureChannelFirst()(region, metadata) if patch_size is None: patches = region else: tuple_patch_size = ensure_tuple_rep(patch_size, 2) patches = self._extract_patches( region, patch_size=tuple_patch_size, # type: ignore grid_shape=grid_shape, dtype=dtype, ) return patches, metadata
def __init__(self, keys: KeysCollection, meta_key_postfix: str = "meta_dict") -> None: """ Args: keys: keys of the corresponding items to be transformed. See also: :py:class:`monai.transforms.compose.MapTransform` meta_key_postfix: `key_{postfix}` was used to store the metadata in `LoadImaged`. So need the key to extract metadata for channel dim information, default is `meta_dict`. For example, for data with key `image`, metadata by default is in `image_meta_dict`. """ super().__init__(keys) self.adjuster = EnsureChannelFirst() self.meta_key_postfix = meta_key_postfix
def __call__(self, filename: Union[Sequence[PathLike], PathLike], reader: Optional[ImageReader] = None): """ Load image file and meta data from the given filename(s). If `reader` is not specified, this class automatically chooses readers based on the reversed order of registered readers `self.readers`. Args: filename: path file or file-like object or a list of files. will save the filename to meta_data with key `filename_or_obj`. if provided a list of files, use the filename of first file to save, and will stack them together as multi-channels data. if provided directory path instead of file path, will treat it as DICOM images series and read. reader: runtime reader to load image file and meta data. """ filename = tuple(f"{Path(s).expanduser()}" for s in ensure_tuple(filename)) # allow Path objects img, err = None, [] if reader is not None: img = reader.read(filename) # runtime specified reader else: for reader in self.readers[::-1]: if self.auto_select: # rely on the filename extension to choose the reader if reader.verify_suffix(filename): img = reader.read(filename) break else: # try the user designated readers try: img = reader.read(filename) except Exception as e: err.append(traceback.format_exc()) logging.getLogger(self.__class__.__name__).debug(e, exc_info=True) logging.getLogger(self.__class__.__name__).info( f"{reader.__class__.__name__}: unable to load {filename}.\n" ) else: err = [] break if img is None or reader is None: if isinstance(filename, tuple) and len(filename) == 1: filename = filename[0] msg = "\n".join([f"{e}" for e in err]) raise RuntimeError( f"{self.__class__.__name__} cannot find a suitable reader for file: {filename}.\n" " Please install the reader libraries, see also the installation instructions:\n" " https://docs.monai.io/en/latest/installation.html#installing-the-recommended-dependencies.\n" f" The current registered: {self.readers}.\n{msg}" ) img_array: NdarrayOrTensor img_array, meta_data = reader.get_data(img) img_array = img_array.astype(self.dtype, copy=False) if not isinstance(meta_data, dict): raise ValueError("`meta_data` must be a dict.") # make sure all elements in metadata are little endian meta_data = switch_endianness(meta_data, "<") if self.ensure_channel_first: img_array = EnsureChannelFirst()(img_array, meta_data) if self.image_only: return img_array meta_data[Key.FILENAME_OR_OBJ] = f"{ensure_tuple(filename)[0]}" # Path obj should be strings for data loader return img_array, meta_data