synapse-sdk 1.0.0a79__py3-none-any.whl → 1.0.0a81__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.
Potentially problematic release.
This version of synapse-sdk might be problematic. Click here for more details.
- synapse_sdk/shared/enums.py +60 -0
- synapse_sdk/utils/converters/coco/from_dm.py +56 -3
- synapse_sdk/utils/converters/coco/to_dm.py +102 -0
- synapse_sdk/utils/converters/dm/__init__.py +24 -76
- synapse_sdk/utils/converters/dm/from_v1.py +300 -88
- synapse_sdk/utils/converters/dm/to_v1.py +135 -22
- synapse_sdk/utils/converters/pascal/from_dm.py +48 -3
- synapse_sdk/utils/converters/pascal/to_dm.py +80 -1
- synapse_sdk/utils/converters/yolo/to_dm.py +12 -8
- {synapse_sdk-1.0.0a79.dist-info → synapse_sdk-1.0.0a81.dist-info}/METADATA +1 -1
- {synapse_sdk-1.0.0a79.dist-info → synapse_sdk-1.0.0a81.dist-info}/RECORD +15 -15
- {synapse_sdk-1.0.0a79.dist-info → synapse_sdk-1.0.0a81.dist-info}/WHEEL +0 -0
- {synapse_sdk-1.0.0a79.dist-info → synapse_sdk-1.0.0a81.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a79.dist-info → synapse_sdk-1.0.0a81.dist-info}/licenses/LICENSE +0 -0
- {synapse_sdk-1.0.0a79.dist-info → synapse_sdk-1.0.0a81.dist-info}/top_level.txt +0 -0
|
@@ -7,13 +7,18 @@ from . import BaseDMConverter
|
|
|
7
7
|
class DMV2ToV1Converter(BaseDMConverter):
|
|
8
8
|
"""DM v2 to v1 format converter class."""
|
|
9
9
|
|
|
10
|
-
def __init__(self, new_dm_data={}):
|
|
10
|
+
def __init__(self, new_dm_data={}, file_type=None):
|
|
11
11
|
"""Initialize the converter.
|
|
12
12
|
|
|
13
13
|
Args:
|
|
14
14
|
new_dm_data (dict): DM v2 format data to be converted
|
|
15
|
+
file_type (str, optional): Type of file being converted (image, video, pcd, text, audio)
|
|
15
16
|
"""
|
|
16
|
-
|
|
17
|
+
# Auto-detect file type if not provided
|
|
18
|
+
if file_type is None:
|
|
19
|
+
file_type = self._detect_file_type(new_dm_data)
|
|
20
|
+
|
|
21
|
+
super().__init__(file_type=file_type)
|
|
17
22
|
self.new_dm_data = new_dm_data
|
|
18
23
|
self.annotations = {}
|
|
19
24
|
self.annotations_data = {}
|
|
@@ -21,6 +26,32 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
21
26
|
self.relations = {}
|
|
22
27
|
self.annotation_groups = {}
|
|
23
28
|
|
|
29
|
+
def _detect_file_type(self, data):
|
|
30
|
+
"""Auto-detect file type from the data structure.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
data (dict): DM v2 format data
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
str: Detected file type (image, video, pcd, text, audio)
|
|
37
|
+
"""
|
|
38
|
+
if not data:
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
# Check for media type keys (plural forms)
|
|
42
|
+
if 'images' in data:
|
|
43
|
+
return 'image'
|
|
44
|
+
elif 'videos' in data:
|
|
45
|
+
return 'video'
|
|
46
|
+
elif 'pcds' in data:
|
|
47
|
+
return 'pcd'
|
|
48
|
+
elif 'texts' in data:
|
|
49
|
+
return 'text'
|
|
50
|
+
elif 'audios' in data:
|
|
51
|
+
return 'audio'
|
|
52
|
+
|
|
53
|
+
return None
|
|
54
|
+
|
|
24
55
|
def convert(self):
|
|
25
56
|
"""Convert DM v2 data to v1 format.
|
|
26
57
|
|
|
@@ -110,7 +141,7 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
110
141
|
else:
|
|
111
142
|
self._handle_unknown_tool(tool_type, annotation_id)
|
|
112
143
|
|
|
113
|
-
def
|
|
144
|
+
def _convert_bounding_box(self, annotation_id, data, annotations_data):
|
|
114
145
|
"""Process bounding box annotation data.
|
|
115
146
|
|
|
116
147
|
Args:
|
|
@@ -124,7 +155,7 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
124
155
|
|
|
125
156
|
annotations_data.append({'id': annotation_id, 'coordinate': coordinate})
|
|
126
157
|
|
|
127
|
-
def
|
|
158
|
+
def _convert_named_entity(self, annotation_id, data, annotations_data):
|
|
128
159
|
"""Process named entity annotation data.
|
|
129
160
|
|
|
130
161
|
Args:
|
|
@@ -142,7 +173,7 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
142
173
|
|
|
143
174
|
annotations_data.append(entity_data)
|
|
144
175
|
|
|
145
|
-
def
|
|
176
|
+
def _convert_classification(self, annotation_id, data, annotations_data):
|
|
146
177
|
"""Process classification annotation data.
|
|
147
178
|
|
|
148
179
|
Args:
|
|
@@ -153,23 +184,30 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
153
184
|
# Classification data is typically empty in v2, so we just add the ID
|
|
154
185
|
annotations_data.append({'id': annotation_id})
|
|
155
186
|
|
|
156
|
-
def
|
|
187
|
+
def _convert_polyline(self, annotation_id, data, annotations_data):
|
|
157
188
|
"""Process polyline annotation data.
|
|
158
189
|
|
|
159
190
|
Args:
|
|
160
191
|
annotation_id (str): ID of the annotation
|
|
161
|
-
data (list): Polyline data [x1, y1, x2, y2, ...]
|
|
192
|
+
data (list): Polyline data - can be flat [x1, y1, x2, y2, ...] or nested [[x1, y1], [x2, y2], ...]
|
|
162
193
|
annotations_data (list): List to append the processed data
|
|
163
194
|
"""
|
|
164
|
-
# Convert flat array to coordinate objects
|
|
165
195
|
coordinates = []
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
196
|
+
|
|
197
|
+
if data and isinstance(data[0], list):
|
|
198
|
+
# Nested format: [[x1, y1], [x2, y2], ...]
|
|
199
|
+
for point in data:
|
|
200
|
+
if len(point) >= 2:
|
|
201
|
+
coordinates.append({'x': point[0], 'y': point[1], 'id': self._generate_random_id()})
|
|
202
|
+
else:
|
|
203
|
+
# Flat format: [x1, y1, x2, y2, ...]
|
|
204
|
+
for i in range(0, len(data), 2):
|
|
205
|
+
if i + 1 < len(data):
|
|
206
|
+
coordinates.append({'x': data[i], 'y': data[i + 1], 'id': self._generate_random_id()})
|
|
169
207
|
|
|
170
208
|
annotations_data.append({'id': annotation_id, 'coordinate': coordinates})
|
|
171
209
|
|
|
172
|
-
def
|
|
210
|
+
def _convert_keypoint(self, annotation_id, data, annotations_data):
|
|
173
211
|
"""Process keypoint annotation data.
|
|
174
212
|
|
|
175
213
|
Args:
|
|
@@ -182,7 +220,7 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
182
220
|
|
|
183
221
|
annotations_data.append({'id': annotation_id, 'coordinate': coordinate})
|
|
184
222
|
|
|
185
|
-
def
|
|
223
|
+
def _convert_3d_bounding_box(self, annotation_id, data, annotations_data):
|
|
186
224
|
"""Process 3D bounding box annotation data.
|
|
187
225
|
|
|
188
226
|
Args:
|
|
@@ -192,7 +230,7 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
192
230
|
"""
|
|
193
231
|
annotations_data.append({'id': annotation_id, 'psr': data})
|
|
194
232
|
|
|
195
|
-
def
|
|
233
|
+
def _convert_image_segmentation(self, annotation_id, data, annotations_data):
|
|
196
234
|
"""Process segmentation annotation data.
|
|
197
235
|
|
|
198
236
|
Args:
|
|
@@ -211,23 +249,98 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
211
249
|
|
|
212
250
|
annotations_data.append(annotation_data)
|
|
213
251
|
|
|
214
|
-
def
|
|
252
|
+
def _convert_video_segmentation(self, annotation_id, data, annotations_data):
|
|
253
|
+
"""Process video segmentation annotation data.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
annotation_id (str): ID of the annotation
|
|
257
|
+
data (list or dict): Segmentation data (pixel_indices or section)
|
|
258
|
+
annotations_data (list): List to append the processed data
|
|
259
|
+
"""
|
|
260
|
+
annotation_data = {'id': annotation_id}
|
|
261
|
+
|
|
262
|
+
if isinstance(data, list):
|
|
263
|
+
# Pixel-based segmentation
|
|
264
|
+
annotation_data['pixel_indices'] = data
|
|
265
|
+
elif isinstance(data, dict):
|
|
266
|
+
# Section-based segmentation (video)
|
|
267
|
+
annotation_data['section'] = data
|
|
268
|
+
|
|
269
|
+
annotations_data.append(annotation_data)
|
|
270
|
+
|
|
271
|
+
def _convert_3d_segmentation(self, annotation_id, data, annotations_data):
|
|
272
|
+
"""Process 3D segmentation annotation data.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
annotation_id (str): ID of the annotation
|
|
276
|
+
data (list or dict): 3D segmentation data
|
|
277
|
+
annotations_data (list): List to append the processed data
|
|
278
|
+
"""
|
|
279
|
+
annotation_data = {'id': annotation_id}
|
|
280
|
+
|
|
281
|
+
if isinstance(data, list):
|
|
282
|
+
# Pixel-based segmentation
|
|
283
|
+
annotation_data['pixel_indices'] = data
|
|
284
|
+
elif isinstance(data, dict):
|
|
285
|
+
# Section-based segmentation
|
|
286
|
+
annotation_data['section'] = data
|
|
287
|
+
|
|
288
|
+
annotations_data.append(annotation_data)
|
|
289
|
+
|
|
290
|
+
def _convert_prompt(self, annotation_id, data, annotations_data):
|
|
291
|
+
"""Process prompt annotation data.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
annotation_id (str): ID of the annotation
|
|
295
|
+
data (dict): Prompt data
|
|
296
|
+
annotations_data (list): List to append the processed data
|
|
297
|
+
"""
|
|
298
|
+
annotation_data = {'id': annotation_id}
|
|
299
|
+
|
|
300
|
+
if isinstance(data, dict):
|
|
301
|
+
annotation_data.update(data)
|
|
302
|
+
|
|
303
|
+
annotations_data.append(annotation_data)
|
|
304
|
+
|
|
305
|
+
def _convert_answer(self, annotation_id, data, annotations_data):
|
|
306
|
+
"""Process answer annotation data.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
annotation_id (str): ID of the annotation
|
|
310
|
+
data (dict): Answer data
|
|
311
|
+
annotations_data (list): List to append the processed data
|
|
312
|
+
"""
|
|
313
|
+
annotation_data = {'id': annotation_id}
|
|
314
|
+
|
|
315
|
+
if isinstance(data, dict):
|
|
316
|
+
annotation_data.update(data)
|
|
317
|
+
|
|
318
|
+
annotations_data.append(annotation_data)
|
|
319
|
+
|
|
320
|
+
def _convert_polygon(self, annotation_id, data, annotations_data):
|
|
215
321
|
"""Process polygon annotation data.
|
|
216
322
|
|
|
217
323
|
Args:
|
|
218
324
|
annotation_id (str): ID of the annotation
|
|
219
|
-
data (list): Polygon data [x1, y1, x2, y2, ...]
|
|
325
|
+
data (list): Polygon data - can be flat [x1, y1, x2, y2, ...] or nested [[x1, y1], [x2, y2], ...]
|
|
220
326
|
annotations_data (list): List to append the processed data
|
|
221
327
|
"""
|
|
222
|
-
# Convert flat array to coordinate objects
|
|
223
328
|
coordinates = []
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
329
|
+
|
|
330
|
+
if data and isinstance(data[0], list):
|
|
331
|
+
# Nested format: [[x1, y1], [x2, y2], ...]
|
|
332
|
+
for point in data:
|
|
333
|
+
if len(point) >= 2:
|
|
334
|
+
coordinates.append({'x': point[0], 'y': point[1], 'id': self._generate_random_id()})
|
|
335
|
+
else:
|
|
336
|
+
# Flat format: [x1, y1, x2, y2, ...]
|
|
337
|
+
for i in range(0, len(data), 2):
|
|
338
|
+
if i + 1 < len(data):
|
|
339
|
+
coordinates.append({'x': data[i], 'y': data[i + 1], 'id': self._generate_random_id()})
|
|
227
340
|
|
|
228
341
|
annotations_data.append({'id': annotation_id, 'coordinate': coordinates})
|
|
229
342
|
|
|
230
|
-
def
|
|
343
|
+
def _convert_relation(self, annotation_id, data, annotations_data):
|
|
231
344
|
"""Process relation annotation data.
|
|
232
345
|
|
|
233
346
|
Args:
|
|
@@ -237,7 +350,7 @@ class DMV2ToV1Converter(BaseDMConverter):
|
|
|
237
350
|
"""
|
|
238
351
|
annotations_data.append({'id': annotation_id, 'data': data})
|
|
239
352
|
|
|
240
|
-
def
|
|
353
|
+
def _convert_group(self, annotation_id, data, annotations_data):
|
|
241
354
|
"""Process group annotation data.
|
|
242
355
|
|
|
243
356
|
Args:
|
|
@@ -3,7 +3,7 @@ import os
|
|
|
3
3
|
import shutil
|
|
4
4
|
import xml.etree.ElementTree as ET
|
|
5
5
|
from glob import glob
|
|
6
|
-
from typing import Any, List, Optional
|
|
6
|
+
from typing import Any, Dict, IO, List, Optional
|
|
7
7
|
|
|
8
8
|
from PIL import Image
|
|
9
9
|
|
|
@@ -15,8 +15,8 @@ class FromDMToPascalConverter(FromDMConverter):
|
|
|
15
15
|
|
|
16
16
|
IMG_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.bmp']
|
|
17
17
|
|
|
18
|
-
def __init__(self, root_dir: str, is_categorized_dataset: bool = False):
|
|
19
|
-
super().__init__(root_dir, is_categorized_dataset)
|
|
18
|
+
def __init__(self, root_dir: str = None, is_categorized_dataset: bool = False, is_single_conversion: bool = False):
|
|
19
|
+
super().__init__(root_dir, is_categorized_dataset, is_single_conversion)
|
|
20
20
|
self.class_names = set()
|
|
21
21
|
|
|
22
22
|
def find_image_for_base(self, img_dir: str, base: str) -> Optional[str]:
|
|
@@ -175,3 +175,48 @@ class FromDMToPascalConverter(FromDMConverter):
|
|
|
175
175
|
for c in sorted(self.class_names):
|
|
176
176
|
f.write(f'{c}\n')
|
|
177
177
|
print(f'Pascal VOC data exported to {outdir}')
|
|
178
|
+
|
|
179
|
+
def convert_single_file(self, data: Dict[str, Any], original_file: IO) -> Dict[str, Any]:
|
|
180
|
+
"""Convert a single DM data dict and corresponding image file object to Pascal VOC format.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
data: DM format data dictionary (JSON content)
|
|
184
|
+
original_file: File object for the corresponding original image
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Dictionary containing Pascal VOC format data for the single file
|
|
188
|
+
"""
|
|
189
|
+
if not self.is_single_conversion:
|
|
190
|
+
raise RuntimeError('convert_single_file is only available when is_single_conversion=True')
|
|
191
|
+
|
|
192
|
+
# Extract image info from file object
|
|
193
|
+
with Image.open(original_file) as img:
|
|
194
|
+
width, height = img.size
|
|
195
|
+
depth = len(img.getbands())
|
|
196
|
+
|
|
197
|
+
# Get filename from original_file
|
|
198
|
+
img_filename = getattr(original_file, 'name', 'image.jpg')
|
|
199
|
+
if img_filename:
|
|
200
|
+
img_filename = os.path.basename(img_filename)
|
|
201
|
+
|
|
202
|
+
# Process annotations from the first (and only) image in data
|
|
203
|
+
if 'images' in data and len(data['images']) > 0:
|
|
204
|
+
img_ann = data['images'][0]
|
|
205
|
+
objects = self.parse_dm_annotations(img_ann)
|
|
206
|
+
else:
|
|
207
|
+
objects = []
|
|
208
|
+
|
|
209
|
+
# Build Pascal VOC XML
|
|
210
|
+
xml_tree = self.build_pascal_xml(img_filename, (width, height, depth), objects)
|
|
211
|
+
xml_filename = os.path.splitext(img_filename)[0] + '.xml'
|
|
212
|
+
|
|
213
|
+
# Convert XML tree to string for easy viewing
|
|
214
|
+
xml_string = ET.tostring(xml_tree.getroot(), encoding='unicode', xml_declaration=True)
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
'xml_tree': xml_tree,
|
|
218
|
+
'xml_content': xml_string,
|
|
219
|
+
'xml_filename': xml_filename,
|
|
220
|
+
'image_filename': img_filename,
|
|
221
|
+
'class_names': sorted(list(self.class_names)),
|
|
222
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import xml.etree.ElementTree as ET
|
|
3
|
-
from typing import Any, Dict, List, Optional, Tuple
|
|
3
|
+
from typing import Any, Dict, IO, List, Optional, Tuple
|
|
4
4
|
|
|
5
5
|
from PIL import Image
|
|
6
6
|
|
|
@@ -12,6 +12,9 @@ class PascalToDMConverter(ToDMConverter):
|
|
|
12
12
|
|
|
13
13
|
IMG_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.bmp']
|
|
14
14
|
|
|
15
|
+
def __init__(self, root_dir: str = None, is_categorized_dataset: bool = False, is_single_conversion: bool = False):
|
|
16
|
+
super().__init__(root_dir, is_categorized_dataset, is_single_conversion)
|
|
17
|
+
|
|
15
18
|
def convert(self):
|
|
16
19
|
"""Convert the Pascal VOC dataset to DM format."""
|
|
17
20
|
if self.is_categorized_dataset:
|
|
@@ -133,3 +136,79 @@ class PascalToDMConverter(ToDMConverter):
|
|
|
133
136
|
print(f'[WARNING] Error processing {xml_filename}: {e}, skipping.')
|
|
134
137
|
continue
|
|
135
138
|
return result
|
|
139
|
+
|
|
140
|
+
def convert_single_file(self, data: str, original_file: IO) -> Dict[str, Any]:
|
|
141
|
+
"""Convert a single Pascal VOC XML data and corresponding image to DM format.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
data: Pascal VOC XML content as string
|
|
145
|
+
original_file: File object for the corresponding original image
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Dictionary containing DM format data for the single file
|
|
149
|
+
"""
|
|
150
|
+
if not self.is_single_conversion:
|
|
151
|
+
raise RuntimeError('convert_single_file is only available when is_single_conversion=True')
|
|
152
|
+
|
|
153
|
+
# Get filename from original_file
|
|
154
|
+
img_path = getattr(original_file, 'name', None)
|
|
155
|
+
if not img_path:
|
|
156
|
+
raise ValueError('original_file must have a "name" attribute representing its path or filename.')
|
|
157
|
+
|
|
158
|
+
img_filename = os.path.basename(img_path)
|
|
159
|
+
|
|
160
|
+
# Parse XML data from string
|
|
161
|
+
try:
|
|
162
|
+
root = ET.fromstring(data)
|
|
163
|
+
except ET.ParseError as e:
|
|
164
|
+
raise ValueError(f'Failed to parse Pascal VOC XML data: {e}')
|
|
165
|
+
|
|
166
|
+
# Extract objects from XML
|
|
167
|
+
objects = []
|
|
168
|
+
for obj in root.findall('object'):
|
|
169
|
+
name_elem = obj.find('name')
|
|
170
|
+
bndbox_elem = obj.find('bndbox')
|
|
171
|
+
if name_elem is None or bndbox_elem is None:
|
|
172
|
+
continue
|
|
173
|
+
|
|
174
|
+
class_name = name_elem.text
|
|
175
|
+
xmin_elem = bndbox_elem.find('xmin')
|
|
176
|
+
ymin_elem = bndbox_elem.find('ymin')
|
|
177
|
+
xmax_elem = bndbox_elem.find('xmax')
|
|
178
|
+
ymax_elem = bndbox_elem.find('ymax')
|
|
179
|
+
|
|
180
|
+
if any(elem is None for elem in [xmin_elem, ymin_elem, xmax_elem, ymax_elem]):
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
xmin = int(float(xmin_elem.text))
|
|
184
|
+
ymin = int(float(ymin_elem.text))
|
|
185
|
+
xmax = int(float(xmax_elem.text))
|
|
186
|
+
ymax = int(float(ymax_elem.text))
|
|
187
|
+
width = xmax - xmin
|
|
188
|
+
height = ymax - ymin
|
|
189
|
+
|
|
190
|
+
objects.append({'classification': class_name, 'data': [xmin, ymin, width, height]})
|
|
191
|
+
|
|
192
|
+
# Prepare DM annotation structure
|
|
193
|
+
dm_img = {
|
|
194
|
+
'bounding_box': [],
|
|
195
|
+
'polygon': [],
|
|
196
|
+
'keypoint': [],
|
|
197
|
+
'relation': [],
|
|
198
|
+
'group': [],
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
for obj in objects:
|
|
202
|
+
dm_img['bounding_box'].append({
|
|
203
|
+
'id': self._generate_unique_id(),
|
|
204
|
+
'classification': obj['classification'],
|
|
205
|
+
'attrs': [],
|
|
206
|
+
'data': obj['data'],
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
dm_json = {'images': [dm_img]}
|
|
210
|
+
return {
|
|
211
|
+
'dm_json': dm_json,
|
|
212
|
+
'image_path': img_path,
|
|
213
|
+
'image_name': img_filename,
|
|
214
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from typing import Any, Dict, List, Tuple
|
|
2
|
+
from typing import IO, Any, Dict, List, Tuple
|
|
3
3
|
|
|
4
4
|
import yaml
|
|
5
5
|
from PIL import Image
|
|
@@ -187,12 +187,12 @@ class YOLOToDMConverter(ToDMConverter):
|
|
|
187
187
|
result[os.path.basename(img_path)] = (dm_json, img_path)
|
|
188
188
|
return result
|
|
189
189
|
|
|
190
|
-
def convert_single_file(self, data: List[str],
|
|
190
|
+
def convert_single_file(self, data: List[str], original_file: IO, class_names: List[str]) -> Dict[str, Any]:
|
|
191
191
|
"""Convert a single YOLO label data and corresponding image to DM format.
|
|
192
192
|
|
|
193
193
|
Args:
|
|
194
194
|
data: List of YOLO label lines (strings from .txt file content)
|
|
195
|
-
|
|
195
|
+
original_file: File object for the corresponding original image
|
|
196
196
|
class_names: List of class names corresponding to indices in the label data
|
|
197
197
|
|
|
198
198
|
Returns:
|
|
@@ -201,10 +201,14 @@ class YOLOToDMConverter(ToDMConverter):
|
|
|
201
201
|
if not self.is_single_conversion:
|
|
202
202
|
raise RuntimeError('convert_single_file is only available when is_single_conversion=True')
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
img_path = getattr(original_file, 'name', None)
|
|
205
|
+
if not img_path:
|
|
206
|
+
raise ValueError('original_file must have a "name" attribute representing its path or filename.')
|
|
206
207
|
|
|
207
|
-
|
|
208
|
+
if hasattr(self, '_get_image_size'):
|
|
209
|
+
img_size = self._get_image_size(original_file)
|
|
210
|
+
else:
|
|
211
|
+
raise AttributeError('Converter missing _get_image_size method for file objects.')
|
|
208
212
|
|
|
209
213
|
# data is already a list of label lines
|
|
210
214
|
label_lines = [line.strip() for line in data if line.strip()]
|
|
@@ -249,6 +253,6 @@ class YOLOToDMConverter(ToDMConverter):
|
|
|
249
253
|
dm_json = {'images': [dm_img]}
|
|
250
254
|
return {
|
|
251
255
|
'dm_json': dm_json,
|
|
252
|
-
'image_path':
|
|
253
|
-
'image_name': os.path.basename(
|
|
256
|
+
'image_path': img_path,
|
|
257
|
+
'image_name': os.path.basename(img_path),
|
|
254
258
|
}
|
|
@@ -187,7 +187,7 @@ synapse_sdk/plugins/utils/config.py,sha256=uyGp9GhphQE-b6sla3NwMUH0DeBunvi7szycR
|
|
|
187
187
|
synapse_sdk/plugins/utils/legacy.py,sha256=UWEk5FHk_AqU4GxhfyKJ76VgBUHS-ktKV6_jTJCgT8k,2689
|
|
188
188
|
synapse_sdk/plugins/utils/registry.py,sha256=HKALzYcPQSFsdLAzodYXMdfFnKOcg6oHYBrx7EwVqNU,1484
|
|
189
189
|
synapse_sdk/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
190
|
-
synapse_sdk/shared/enums.py,sha256=
|
|
190
|
+
synapse_sdk/shared/enums.py,sha256=t00jZvVxt6OY7Cp1c42oWTVwHWx8PzBiUqfDmhHlqVA,2282
|
|
191
191
|
synapse_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
192
192
|
synapse_sdk/utils/dataset.py,sha256=zWTzFmv589izFr62BDuApi3r5FpTsdm-5AmriC0AEdM,1865
|
|
193
193
|
synapse_sdk/utils/debug.py,sha256=F7JlUwYjTFZAMRbBqKm6hxOIz-_IXYA8lBInOS4jbS4,100
|
|
@@ -198,17 +198,17 @@ synapse_sdk/utils/network.py,sha256=WI8qn6KlKpHdMi45V57ofKJB8zusJrbQsxT74LwVfsY,
|
|
|
198
198
|
synapse_sdk/utils/string.py,sha256=rEwuZ9SAaZLcQ8TYiwNKr1h2u4CfnrQx7SUL8NWmChg,216
|
|
199
199
|
synapse_sdk/utils/converters/__init__.py,sha256=xQi_n7xS9BNyDiolsxH2jw1CtD6avxMPj2cHnwvidi8,11311
|
|
200
200
|
synapse_sdk/utils/converters/coco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
201
|
-
synapse_sdk/utils/converters/coco/from_dm.py,sha256=
|
|
202
|
-
synapse_sdk/utils/converters/coco/to_dm.py,sha256=
|
|
203
|
-
synapse_sdk/utils/converters/dm/__init__.py,sha256=
|
|
204
|
-
synapse_sdk/utils/converters/dm/from_v1.py,sha256=
|
|
205
|
-
synapse_sdk/utils/converters/dm/to_v1.py,sha256=
|
|
201
|
+
synapse_sdk/utils/converters/coco/from_dm.py,sha256=B9zvb8Kph9haYLVIZhzneWiHCImFbuWqAaE7g6Nk0lI,11365
|
|
202
|
+
synapse_sdk/utils/converters/coco/to_dm.py,sha256=YmD_NHKSUL8RZbzWX52FgDaJG0uX4I8f8Omp7ilhSec,9054
|
|
203
|
+
synapse_sdk/utils/converters/dm/__init__.py,sha256=_B6w814bMPhisNCNlSPEiQOs9RH0EZHQqd89LnVhD1U,1983
|
|
204
|
+
synapse_sdk/utils/converters/dm/from_v1.py,sha256=4BG_NA_7YdW5rI1F8LCFg39M-IJZVfRgi2b9FBxTAmw,26059
|
|
205
|
+
synapse_sdk/utils/converters/dm/to_v1.py,sha256=A123zAR_dLqEW83BgAl5_J1ACstjZWTHivlW5qvOu_E,13432
|
|
206
206
|
synapse_sdk/utils/converters/pascal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
207
|
-
synapse_sdk/utils/converters/pascal/from_dm.py,sha256=
|
|
208
|
-
synapse_sdk/utils/converters/pascal/to_dm.py,sha256=
|
|
207
|
+
synapse_sdk/utils/converters/pascal/from_dm.py,sha256=AKOeQoyeSbSOawf-ya9dLx-pZP_MomNcDaCW5ka5_8Y,10378
|
|
208
|
+
synapse_sdk/utils/converters/pascal/to_dm.py,sha256=JkA_OI_IR1ealZPe2uo4hFBcFyOh_VfeyIY43-R4IBA,8614
|
|
209
209
|
synapse_sdk/utils/converters/yolo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
210
210
|
synapse_sdk/utils/converters/yolo/from_dm.py,sha256=-JDCQLk4g1_FIVoOwZ1Tcs2kWFkhXRCAPVLKLXz6sLU,16180
|
|
211
|
-
synapse_sdk/utils/converters/yolo/to_dm.py,sha256=
|
|
211
|
+
synapse_sdk/utils/converters/yolo/to_dm.py,sha256=UUGTbBNeG5Ao8PSJbizrZRQJfeAMuSDfZs8SGOyr-YU,10464
|
|
212
212
|
synapse_sdk/utils/pydantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
213
213
|
synapse_sdk/utils/pydantic/config.py,sha256=1vYOcUI35GslfD1rrqhFkNXXJOXt4IDqOPSx9VWGfNE,123
|
|
214
214
|
synapse_sdk/utils/pydantic/errors.py,sha256=0v0T12eQBr1KrFiEOBu6KMaPK4aPEGEC6etPJGoR5b4,1061
|
|
@@ -220,9 +220,9 @@ synapse_sdk/utils/storage/providers/gcp.py,sha256=i2BQCu1Kej1If9SuNr2_lEyTcr5M_n
|
|
|
220
220
|
synapse_sdk/utils/storage/providers/http.py,sha256=2DhIulND47JOnS5ZY7MZUex7Su3peAPksGo1Wwg07L4,5828
|
|
221
221
|
synapse_sdk/utils/storage/providers/s3.py,sha256=ZmqekAvIgcQBdRU-QVJYv1Rlp6VHfXwtbtjTSphua94,2573
|
|
222
222
|
synapse_sdk/utils/storage/providers/sftp.py,sha256=_8s9hf0JXIO21gvm-JVS00FbLsbtvly4c-ETLRax68A,1426
|
|
223
|
-
synapse_sdk-1.0.
|
|
224
|
-
synapse_sdk-1.0.
|
|
225
|
-
synapse_sdk-1.0.
|
|
226
|
-
synapse_sdk-1.0.
|
|
227
|
-
synapse_sdk-1.0.
|
|
228
|
-
synapse_sdk-1.0.
|
|
223
|
+
synapse_sdk-1.0.0a81.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
|
|
224
|
+
synapse_sdk-1.0.0a81.dist-info/METADATA,sha256=iAK5lypAXDJzvZjjqFOX0lyvyYyx3rYQvlOOkzXEbKg,3805
|
|
225
|
+
synapse_sdk-1.0.0a81.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
226
|
+
synapse_sdk-1.0.0a81.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
|
|
227
|
+
synapse_sdk-1.0.0a81.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
|
|
228
|
+
synapse_sdk-1.0.0a81.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|