maite-datasets 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,207 @@
1
+ from __future__ import annotations
2
+
3
+ __all__ = []
4
+
5
+ from pathlib import Path
6
+ from typing import Any, Literal, Sequence
7
+
8
+ import numpy as np
9
+ from numpy.typing import NDArray
10
+
11
+ from maite_datasets._base import BaseODDataset, DataLocation
12
+ from maite_datasets._mixin._numpy import BaseDatasetNumpyMixin
13
+ from maite_datasets._protocols import Transform
14
+
15
+
16
+ class MILCO(
17
+ BaseODDataset[NDArray[np.number[Any]], list[str], str], BaseDatasetNumpyMixin
18
+ ):
19
+ """
20
+ A side-scan sonar dataset focused on mine-like object detection.
21
+
22
+ The dataset comes from the paper
23
+ `Side-scan sonar imaging data of underwater vehicles for mine detection <https://doi.org/10.1016/j.dib.2024.110132>`_
24
+ by N.P. Santos et. al. (2024).
25
+
26
+ The full dataset contains 1170 side-scan sonar images collected using a 900-1800 kHz Marine Sonic
27
+ dual frequency side-scan sonar of a Teledyne Marine Gavia Autonomous Underwater Vehicle.
28
+ All the images were carefully analyzed and annotated, including the image coordinates of the
29
+ Bounding Box (BB) of the detected objects divided into NOn-Mine-like BOttom Objects (NOMBO)
30
+ and MIne-Like COntacts (MILCO) classes.
31
+
32
+ This dataset is consists of 345 images from 2010, 120 images from 2015, 93 images from 2017, 564 images from 2018,
33
+ and 48 images from 2021). In these 1170 images, there are 432 MILCO objects, and 235 NOMBO objects.
34
+ The class “0” corresponds to a MILCO object and the class “1” corresponds to a NOMBO object.
35
+ The raw BB coordinates provided in the downloaded text files are (x, y, w, h),
36
+ given as percentages of the image (x_BB = x/img_width, y_BB = y/img_height, etc.).
37
+ The images come in 2 sizes, 416 x 416 or 1024 x 1024.
38
+
39
+ Parameters
40
+ ----------
41
+ root : str or pathlib.Path
42
+ Root directory where the data should be downloaded to or the ``milco`` folder of the already downloaded data.
43
+ image_set: "train", "operational", or "base", default "train"
44
+ If "train", then the images from 2015, 2017 and 2021 are selected,
45
+ resulting in 315 MILCO objects and 177 NOMBO objects.
46
+ If "operational", then the images from 2010 and 2018 are selected,
47
+ resulting in 117 MILCO objects and 58 NOMBO objects.
48
+ If "base", then the full dataset is selected.
49
+ transforms : Transform, Sequence[Transform] or None, default None
50
+ Transform(s) to apply to the data.
51
+ download : bool, default False
52
+ If True, downloads the dataset from the internet and puts it in root directory.
53
+ Class checks to see if data is already downloaded to ensure it does not create a duplicate download.
54
+ verbose : bool, default False
55
+ If True, outputs print statements.
56
+
57
+ Attributes
58
+ ----------
59
+ path : pathlib.Path
60
+ Location of the folder containing the data.
61
+ image_set : "train", "operational" or "base"
62
+ The selected image set from the dataset.
63
+ index2label : dict[int, str]
64
+ Dictionary which translates from class integers to the associated class strings.
65
+ label2index : dict[str, int]
66
+ Dictionary which translates from class strings to the associated class integers.
67
+ metadata : DatasetMetadata
68
+ Typed dictionary containing dataset metadata, such as `id` which returns the dataset class name.
69
+ transforms : Sequence[Transform]
70
+ The transforms to be applied to the data.
71
+ size : int
72
+ The size of the dataset.
73
+
74
+ Note
75
+ ----
76
+ Data License: `CC BY 4.0 <https://creativecommons.org/licenses/by/4.0/>`_
77
+ """
78
+
79
+ _resources = [
80
+ DataLocation(
81
+ url="https://figshare.com/ndownloader/files/43169002",
82
+ filename="2015.zip",
83
+ md5=True,
84
+ checksum="93dfbb4fb7987734152c372496b4884c",
85
+ ),
86
+ DataLocation(
87
+ url="https://figshare.com/ndownloader/files/43169005",
88
+ filename="2017.zip",
89
+ md5=True,
90
+ checksum="9c2de230a2bbf654921416bea6fc0f42",
91
+ ),
92
+ DataLocation(
93
+ url="https://figshare.com/ndownloader/files/43168999",
94
+ filename="2021.zip",
95
+ md5=True,
96
+ checksum="b84749b21fa95a4a4c7de3741db78bc7",
97
+ ),
98
+ DataLocation(
99
+ url="https://figshare.com/ndownloader/files/43169008",
100
+ filename="2010.zip",
101
+ md5=True,
102
+ checksum="43347a0cc383c0d3dbe0d24ae56f328d",
103
+ ),
104
+ DataLocation(
105
+ url="https://figshare.com/ndownloader/files/43169011",
106
+ filename="2018.zip",
107
+ md5=True,
108
+ checksum="25d091044a10c78674fedad655023e3b",
109
+ ),
110
+ ]
111
+
112
+ index2label: dict[int, str] = {
113
+ 0: "MILCO",
114
+ 1: "NOMBO",
115
+ }
116
+
117
+ def __init__(
118
+ self,
119
+ root: str | Path,
120
+ image_set: Literal["train", "operational", "base"] = "train",
121
+ transforms: Transform[NDArray[np.number[Any]]]
122
+ | Sequence[Transform[NDArray[np.number[Any]]]]
123
+ | None = None,
124
+ download: bool = False,
125
+ verbose: bool = False,
126
+ ) -> None:
127
+ super().__init__(
128
+ root,
129
+ image_set,
130
+ transforms,
131
+ download,
132
+ verbose,
133
+ )
134
+ self._bboxes_per_size = True
135
+
136
+ def _load_data(self) -> tuple[list[str], list[str], dict[str, list[Any]]]:
137
+ filepaths: list[str] = []
138
+ targets: list[str] = []
139
+ datum_metadata: dict[str, list[Any]] = {}
140
+ metadata_list: list[dict[str, Any]] = []
141
+ image_sets: dict[str, list[int]] = {
142
+ "base": list(range(len(self._resources))),
143
+ "train": list(range(3)),
144
+ "operational": list(range(3, len(self._resources))),
145
+ }
146
+
147
+ # Load the data
148
+ resource_indices = image_sets[self.image_set]
149
+ for idx in resource_indices:
150
+ self._resource = self._resources[idx]
151
+ filepath, target, metadata = super()._load_data()
152
+ filepaths.extend(filepath)
153
+ targets.extend(target)
154
+ metadata_list.append(metadata)
155
+
156
+ # Adjust datum metadata to correct format
157
+ for data_dict in metadata_list:
158
+ for key, val in data_dict.items():
159
+ if key not in datum_metadata:
160
+ datum_metadata[str(key)] = []
161
+ datum_metadata[str(key)].extend(val)
162
+
163
+ return filepaths, targets, datum_metadata
164
+
165
+ def _load_data_inner(self) -> tuple[list[str], list[str], dict[str, Any]]:
166
+ file_data = {"year": [], "image_id": [], "data_path": [], "label_path": []}
167
+ data_folder = sorted((self.path / self._resource.filename[:-4]).glob("*.jpg"))
168
+ if not data_folder:
169
+ raise FileNotFoundError
170
+
171
+ for entry in data_folder:
172
+ # Remove file extension and split by "_"
173
+ parts = entry.stem.split("_")
174
+ file_data["image_id"].append(parts[0])
175
+ file_data["year"].append(parts[1])
176
+ file_data["data_path"].append(str(entry))
177
+ file_data["label_path"].append(str(entry.parent / entry.stem) + ".txt")
178
+ data = file_data.pop("data_path")
179
+ annotations = file_data.pop("label_path")
180
+
181
+ return data, annotations, file_data
182
+
183
+ def _read_annotations(
184
+ self, annotation: str
185
+ ) -> tuple[list[list[float]], list[int], dict[str, Any]]:
186
+ """Function for extracting the info out of the text files"""
187
+ labels: list[int] = []
188
+ boxes: list[list[float]] = []
189
+ with open(annotation) as f:
190
+ for line in f.readlines():
191
+ out = line.strip().split()
192
+ labels.append(int(out[0]))
193
+
194
+ xcenter, ycenter, width, height = [
195
+ float(out[1]),
196
+ float(out[2]),
197
+ float(out[3]),
198
+ float(out[4]),
199
+ ]
200
+
201
+ x0 = xcenter - width / 2
202
+ x1 = x0 + width
203
+ y0 = ycenter - height / 2
204
+ y1 = y0 + height
205
+ boxes.append([x0, y0, x1, y1])
206
+
207
+ return boxes, labels, {}