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)
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.
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.
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.
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_datasetor for the PyTorch DataLoader.
Returns:
The DataLoader.