torch_em.data.datasets.medical.bus_uclm

The BUS-UCLM dataset contains annotations for breast lesion segmentation in ultrasound images.

The dataset comprises breast ultrasound images from 38 patients, acquired at the Ciudad Real General University Hospital with a Siemens ACUSON S2000 Ultrasound System between 2022 and 2023. The ground-truth is provided as RGB masks where green denotes benign lesions, red denotes malignant lesions and black denotes background (including normal images without any lesion). The label ids are: 0 = background, 1 = benign, 2 = malignant.

This dataset is located at https://data.mendeley.com/datasets/7fvgj4jsp7/3 (CC BY 4.0). We use the mirror at https://www.kaggle.com/datasets/orvile/bus-uclm-breast-ultrasound-dataset for the download, as the Mendeley download links are unreliable.

This dataset is from the publication https://doi.org/10.1038/s41597-025-04562-3. Please cite it if you use this dataset for your research.

  1"""The BUS-UCLM dataset contains annotations for breast lesion segmentation in ultrasound images.
  2
  3The dataset comprises breast ultrasound images from 38 patients, acquired at the Ciudad Real
  4General University Hospital with a Siemens ACUSON S2000 Ultrasound System between 2022 and 2023.
  5The ground-truth is provided as RGB masks where green denotes benign lesions, red denotes
  6malignant lesions and black denotes background (including normal images without any lesion).
  7The label ids are: 0 = background, 1 = benign, 2 = malignant.
  8
  9This dataset is located at https://data.mendeley.com/datasets/7fvgj4jsp7/3 (CC BY 4.0). We use the
 10mirror at https://www.kaggle.com/datasets/orvile/bus-uclm-breast-ultrasound-dataset for the download,
 11as the Mendeley download links are unreliable.
 12
 13This dataset is from the publication https://doi.org/10.1038/s41597-025-04562-3.
 14Please cite it if you use this dataset for your research.
 15"""
 16
 17import os
 18from glob import glob
 19from tqdm import tqdm
 20from pathlib import Path
 21from natsort import natsorted
 22from typing import Union, Tuple, List
 23
 24import numpy as np
 25import imageio.v3 as imageio
 26
 27from torch.utils.data import Dataset, DataLoader
 28
 29import torch_em
 30
 31from .. import util
 32
 33
 34KAGGLE_DATASET_NAME = "orvile/bus-uclm-breast-ultrasound-dataset"
 35
 36LABEL_COLORS = {
 37    0: (0, 0, 0),  # background / normal
 38    1: (0, 255, 0),  # benign
 39    2: (255, 0, 0),  # malignant
 40}
 41
 42
 43def get_bus_uclm_data(path: Union[os.PathLike, str], download: bool = False) -> str:
 44    """Download the BUS-UCLM dataset.
 45
 46    Args:
 47        path: Filepath to a folder where the data is downloaded for further processing.
 48        download: Whether to download the data if it is not present.
 49
 50    Returns:
 51        Filepath where the data is downloaded.
 52    """
 53    data_dirs = glob(os.path.join(path, "**", "BUS-UCLM"), recursive=True)
 54    if data_dirs:
 55        return data_dirs[0]
 56
 57    os.makedirs(path, exist_ok=True)
 58
 59    util.download_source_kaggle(path=path, dataset_name=KAGGLE_DATASET_NAME, download=download)
 60
 61    zip_path = os.path.join(path, "bus-uclm-breast-ultrasound-dataset.zip")
 62    util.unzip(zip_path=zip_path, dst=path)
 63
 64    data_dirs = glob(os.path.join(path, "**", "BUS-UCLM"), recursive=True)
 65    if not data_dirs:
 66        raise RuntimeError(f"The dataset could not be found at '{path}' after extraction.")
 67
 68    return data_dirs[0]
 69
 70
 71def get_bus_uclm_paths(path: Union[os.PathLike, str], download: bool = False) -> Tuple[List[str], List[str]]:
 72    """Get paths to the BUS-UCLM data.
 73
 74    Args:
 75        path: Filepath to a folder where the data is downloaded for further processing.
 76        download: Whether to download the data if it is not present.
 77
 78    Returns:
 79        List of filepaths for the image data.
 80        List of filepaths for the label data.
 81    """
 82    data_dir = get_bus_uclm_data(path=path, download=download)
 83
 84    image_paths = natsorted(glob(os.path.join(data_dir, "images", "*.png")))
 85    mask_paths = natsorted(glob(os.path.join(data_dir, "masks", "*.png")))
 86
 87    if len(image_paths) == 0 or len(image_paths) != len(mask_paths):
 88        raise RuntimeError("Something went wrong with fetching the image and label paths.")
 89
 90    neu_gt_dir = os.path.join(data_dir, "masks", "preprocessed")
 91    os.makedirs(neu_gt_dir, exist_ok=True)
 92
 93    reference_colors = np.array(list(LABEL_COLORS.values()))
 94
 95    gt_paths = []
 96    for mask_path in tqdm(mask_paths, desc="Preprocessing labels"):
 97        gt_path = os.path.join(neu_gt_dir, f"{Path(mask_path).stem}.tif")
 98        gt_paths.append(gt_path)
 99        if os.path.exists(gt_path):
100            continue
101
102        mask = imageio.imread(mask_path)[..., :3].astype("float32")
103        distances = np.linalg.norm(mask[..., None, :] - reference_colors[None, None, :, :], axis=-1)
104        semantic_gt = np.argmin(distances, axis=-1).astype("uint8")
105        imageio.imwrite(gt_path, semantic_gt, compression="zlib")
106
107    return image_paths, gt_paths
108
109
110def get_bus_uclm_dataset(
111    path: Union[os.PathLike, str],
112    patch_shape: Tuple[int, int],
113    resize_inputs: bool = False,
114    download: bool = False,
115    **kwargs
116) -> Dataset:
117    """Get the BUS-UCLM dataset for breast lesion segmentation.
118
119    Args:
120        path: Filepath to a folder where the data is downloaded for further processing.
121        patch_shape: The patch shape to use for training.
122        resize_inputs: Whether to resize the inputs.
123        download: Whether to download the data if it is not present.
124        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
125
126    Returns:
127        The segmentation dataset.
128    """
129    image_paths, gt_paths = get_bus_uclm_paths(path, download)
130
131    if resize_inputs:
132        resize_kwargs = {"patch_shape": patch_shape, "is_rgb": True}
133        kwargs, patch_shape = util.update_kwargs_for_resize_trafo(
134            kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs
135        )
136
137    return torch_em.default_segmentation_dataset(
138        raw_paths=image_paths,
139        raw_key=None,
140        label_paths=gt_paths,
141        label_key=None,
142        patch_shape=patch_shape,
143        is_seg_dataset=False,
144        **kwargs
145    )
146
147
148def get_bus_uclm_loader(
149    path: Union[os.PathLike, str],
150    batch_size: int,
151    patch_shape: Tuple[int, int],
152    resize_inputs: bool = False,
153    download: bool = False,
154    **kwargs
155) -> DataLoader:
156    """Get the BUS-UCLM dataloader for breast lesion segmentation.
157
158    Args:
159        path: Filepath to a folder where the data is downloaded for further processing.
160        batch_size: The batch size for training.
161        patch_shape: The patch shape to use for training.
162        resize_inputs: Whether to resize the inputs.
163        download: Whether to download the data if it is not present.
164        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
165
166    Returns:
167        The DataLoader.
168    """
169    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
170    dataset = get_bus_uclm_dataset(path, patch_shape, resize_inputs, download, **ds_kwargs)
171    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
KAGGLE_DATASET_NAME = 'orvile/bus-uclm-breast-ultrasound-dataset'
LABEL_COLORS = {0: (0, 0, 0), 1: (0, 255, 0), 2: (255, 0, 0)}
def get_bus_uclm_data(path: Union[os.PathLike, str], download: bool = False) -> str:
44def get_bus_uclm_data(path: Union[os.PathLike, str], download: bool = False) -> str:
45    """Download the BUS-UCLM dataset.
46
47    Args:
48        path: Filepath to a folder where the data is downloaded for further processing.
49        download: Whether to download the data if it is not present.
50
51    Returns:
52        Filepath where the data is downloaded.
53    """
54    data_dirs = glob(os.path.join(path, "**", "BUS-UCLM"), recursive=True)
55    if data_dirs:
56        return data_dirs[0]
57
58    os.makedirs(path, exist_ok=True)
59
60    util.download_source_kaggle(path=path, dataset_name=KAGGLE_DATASET_NAME, download=download)
61
62    zip_path = os.path.join(path, "bus-uclm-breast-ultrasound-dataset.zip")
63    util.unzip(zip_path=zip_path, dst=path)
64
65    data_dirs = glob(os.path.join(path, "**", "BUS-UCLM"), recursive=True)
66    if not data_dirs:
67        raise RuntimeError(f"The dataset could not be found at '{path}' after extraction.")
68
69    return data_dirs[0]

Download the BUS-UCLM dataset.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • download: Whether to download the data if it is not present.
Returns:

Filepath where the data is downloaded.

def get_bus_uclm_paths( path: Union[os.PathLike, str], download: bool = False) -> Tuple[List[str], List[str]]:
 72def get_bus_uclm_paths(path: Union[os.PathLike, str], download: bool = False) -> Tuple[List[str], List[str]]:
 73    """Get paths to the BUS-UCLM data.
 74
 75    Args:
 76        path: Filepath to a folder where the data is downloaded for further processing.
 77        download: Whether to download the data if it is not present.
 78
 79    Returns:
 80        List of filepaths for the image data.
 81        List of filepaths for the label data.
 82    """
 83    data_dir = get_bus_uclm_data(path=path, download=download)
 84
 85    image_paths = natsorted(glob(os.path.join(data_dir, "images", "*.png")))
 86    mask_paths = natsorted(glob(os.path.join(data_dir, "masks", "*.png")))
 87
 88    if len(image_paths) == 0 or len(image_paths) != len(mask_paths):
 89        raise RuntimeError("Something went wrong with fetching the image and label paths.")
 90
 91    neu_gt_dir = os.path.join(data_dir, "masks", "preprocessed")
 92    os.makedirs(neu_gt_dir, exist_ok=True)
 93
 94    reference_colors = np.array(list(LABEL_COLORS.values()))
 95
 96    gt_paths = []
 97    for mask_path in tqdm(mask_paths, desc="Preprocessing labels"):
 98        gt_path = os.path.join(neu_gt_dir, f"{Path(mask_path).stem}.tif")
 99        gt_paths.append(gt_path)
100        if os.path.exists(gt_path):
101            continue
102
103        mask = imageio.imread(mask_path)[..., :3].astype("float32")
104        distances = np.linalg.norm(mask[..., None, :] - reference_colors[None, None, :, :], axis=-1)
105        semantic_gt = np.argmin(distances, axis=-1).astype("uint8")
106        imageio.imwrite(gt_path, semantic_gt, compression="zlib")
107
108    return image_paths, gt_paths

Get paths to the BUS-UCLM data.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • download: Whether to download the data if it is not present.
Returns:

List of filepaths for the image data. List of filepaths for the label data.

def get_bus_uclm_dataset( path: Union[os.PathLike, str], patch_shape: Tuple[int, int], resize_inputs: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataset.Dataset:
111def get_bus_uclm_dataset(
112    path: Union[os.PathLike, str],
113    patch_shape: Tuple[int, int],
114    resize_inputs: bool = False,
115    download: bool = False,
116    **kwargs
117) -> Dataset:
118    """Get the BUS-UCLM dataset for breast lesion segmentation.
119
120    Args:
121        path: Filepath to a folder where the data is downloaded for further processing.
122        patch_shape: The patch shape to use for training.
123        resize_inputs: Whether to resize the inputs.
124        download: Whether to download the data if it is not present.
125        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
126
127    Returns:
128        The segmentation dataset.
129    """
130    image_paths, gt_paths = get_bus_uclm_paths(path, download)
131
132    if resize_inputs:
133        resize_kwargs = {"patch_shape": patch_shape, "is_rgb": True}
134        kwargs, patch_shape = util.update_kwargs_for_resize_trafo(
135            kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs
136        )
137
138    return torch_em.default_segmentation_dataset(
139        raw_paths=image_paths,
140        raw_key=None,
141        label_paths=gt_paths,
142        label_key=None,
143        patch_shape=patch_shape,
144        is_seg_dataset=False,
145        **kwargs
146    )

Get the BUS-UCLM dataset for breast lesion segmentation.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • patch_shape: The patch shape to use for training.
  • resize_inputs: Whether to resize the inputs.
  • download: Whether to download the data if it is not present.
  • kwargs: Additional keyword arguments for torch_em.default_segmentation_dataset.
Returns:

The segmentation dataset.

def get_bus_uclm_loader( path: Union[os.PathLike, str], batch_size: int, patch_shape: Tuple[int, int], resize_inputs: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataloader.DataLoader:
149def get_bus_uclm_loader(
150    path: Union[os.PathLike, str],
151    batch_size: int,
152    patch_shape: Tuple[int, int],
153    resize_inputs: bool = False,
154    download: bool = False,
155    **kwargs
156) -> DataLoader:
157    """Get the BUS-UCLM dataloader for breast lesion segmentation.
158
159    Args:
160        path: Filepath to a folder where the data is downloaded for further processing.
161        batch_size: The batch size for training.
162        patch_shape: The patch shape to use for training.
163        resize_inputs: Whether to resize the inputs.
164        download: Whether to download the data if it is not present.
165        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
166
167    Returns:
168        The DataLoader.
169    """
170    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
171    dataset = get_bus_uclm_dataset(path, patch_shape, resize_inputs, download, **ds_kwargs)
172    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)

Get the BUS-UCLM dataloader for breast lesion segmentation.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • batch_size: The batch size for training.
  • patch_shape: The patch shape to use for training.
  • resize_inputs: Whether to resize the inputs.
  • download: Whether to download the data if it is not present.
  • kwargs: Additional keyword arguments for torch_em.default_segmentation_dataset or for the PyTorch DataLoader.
Returns:

The DataLoader.