Repository: Project-MONAI/MONAI
File: monai/transforms/utils.py (Python)

Code before:
            Accepted values are ranging from  1 to input.ndim. If ``None``, a full
            connectivity of ``input.ndim`` is used. For more details refer to linked scikit-image
            documentation.
        independent_channels: Whether to consider each channel independently.
        physical_scale: Whether or not to consider min_size at physical scale, default is false. If true,
            min_size will be multiplied by pixdim.
        pixdim: the pixdim of the input image. if a single number, this is used for all axes.
            If a sequence of numbers, the length of the sequence must be equal to the image dimensions.
    """
    # if all equal to one value, no need to call skimage
    if len(unique(img)) == 1:
        return img

    if not has_morphology:
        raise RuntimeError("Skimage required.")

    if physical_scale:
        sr = len(img.shape[1:])
        if isinstance(img, monai.data.MetaTensor):
            _pixdim = img.pixdim
        elif pixdim is not None:
            _pixdim = ensure_tuple_rep(pixdim, sr)
        else:
            warnings.warn("`img` is not of type MetaTensor and `pixdim` is None, assuming affine to be identity.")
            _pixdim = (1.0,) * sr
        min_size = int(np.prod(np.array(_pixdim)) * min_size)

    img_np: np.ndarray
    img_np, *_ = convert_data_type(img, np.ndarray)

    # morphology.remove_small_objects assumes them to be independent by default
    # else, convert to foreground vs background, remove small objects, then convert
    # back by multiplying the output by the input
    if not independent_channels:
        img_np = img_np > 0
    else:
        # if binary, convert to boolean, else int
        img_np = img_np.astype(bool if img_np.max() <= 1 else np.int32)

    out_np = morphology.remove_small_objects(img_np, min_size, connectivity)
    out, *_ = convert_to_dst_type(out_np, img)

    # convert back by multiplying
    if not independent_channels:
        out = img * out  # type: ignore
    return out


def get_unique_labels(img: NdarrayOrTensor, is_onehot: bool, discard: int | Iterable[int] | None = None) -> set[int]:
    """Get list of non-background labels in an image.


Review comment (suggestion):
```suggestion
        min_size = int(np.prod(np.array(_pixdim)) * min_size)
    elif pixdim is not None:
        warnings.warn(`pixdim is specified by not in use when computing the volume.`)
```

Code after:
            Accepted values are ranging from  1 to input.ndim. If ``None``, a full
            connectivity of ``input.ndim`` is used. For more details refer to linked scikit-image
            documentation.
        independent_channels: Whether to consider each channel independently.
        by_measure: Whether the specified min_size is in number of voxels. if this is True then min_size
            represents a surface area or volume value of whatever units your image is in (mm^3, cm^2, etc.)
            default is False.
        pixdim: the pixdim of the input image. if a single number, this is used for all axes.
            If a sequence of numbers, the length of the sequence must be equal to the image dimensions.
    """
    # if all equal to one value, no need to call skimage
    if len(unique(img)) == 1:
        return img

    if not has_morphology:
        raise RuntimeError("Skimage required.")

    if by_measure:
        sr = len(img.shape[1:])
        if isinstance(img, monai.data.MetaTensor):
            _pixdim = img.pixdim
        elif pixdim is not None:
            _pixdim = ensure_tuple_rep(pixdim, sr)
        else:
            warnings.warn("`img` is not of type MetaTensor and `pixdim` is None, assuming affine to be identity.")
            _pixdim = (1.0,) * sr
        voxel_volume = np.prod(np.array(_pixdim))
        if voxel_volume == 0:
            warnings.warn("Invalid `pixdim` value detected, set it to 1. Please verify the pixdim settings.")
            voxel_volume = 1
        min_size = np.ceil(min_size / voxel_volume)
    elif pixdim is not None:
        warnings.warn("`pixdim` is specified but not in use when computing the volume.")

    img_np: np.ndarray
    img_np, *_ = convert_data_type(img, np.ndarray)

    # morphology.remove_small_objects assumes them to be independent by default
    # else, convert to foreground vs background, remove small objects, then convert
    # back by multiplying the output by the input
    if not independent_channels:
        img_np = img_np > 0
    else:
        # if binary, convert to boolean, else int
        img_np = img_np.astype(bool if img_np.max() <= 1 else np.int32)

    out_np = morphology.remove_small_objects(img_np, min_size, connectivity)
    out, *_ = convert_to_dst_type(out_np, img)

    # convert back by multiplying
    if not independent_channels: