mindkosh 1.0.2__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.
- mindkosh/__init__.py +6 -0
- mindkosh/annotations/__init__.py +0 -0
- mindkosh/annotations/manager.py +254 -0
- mindkosh/annotations/tag.py +24 -0
- mindkosh/annotations/testset.py +442 -0
- mindkosh/client.py +740 -0
- mindkosh/core.py +183 -0
- mindkosh/datasets/__init__.py +0 -0
- mindkosh/datasets/data_handler.py +447 -0
- mindkosh/datasets/files.py +127 -0
- mindkosh/datasets/helpers.py +276 -0
- mindkosh/datasets/utils.py +61 -0
- mindkosh/exceptions.py +42 -0
- mindkosh/issue.py +135 -0
- mindkosh/job.py +22 -0
- mindkosh/label.py +154 -0
- mindkosh/project.py +161 -0
- mindkosh/task.py +881 -0
- mindkosh/utils.py +80 -0
- mindkosh/webhook.py +19 -0
- mindkosh-1.0.2.dist-info/METADATA +432 -0
- mindkosh-1.0.2.dist-info/RECORD +40 -0
- mindkosh-1.0.2.dist-info/WHEEL +5 -0
- mindkosh-1.0.2.dist-info/licenses/LICENSE +201 -0
- mindkosh-1.0.2.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/conftest.py +51 -0
- tests/integration/__init__.py +0 -0
- tests/integration/test_client.py +26 -0
- tests/integration/test_crop_rotate.py +48 -0
- tests/integration/test_dataset.py +123 -0
- tests/integration/test_frame_annotations.py +147 -0
- tests/integration/test_frames.py +28 -0
- tests/integration/test_job.py +32 -0
- tests/integration/test_project.py +66 -0
- tests/integration/test_task.py +236 -0
- tests/integration/test_user.py +10 -0
- tests/unit/__init__.py +0 -0
- tests/unit/test_dataset_tag.py +10 -0
- tests/unit/test_label.py +45 -0
mindkosh/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# Copyright (C) 2022 Mindkosh Technologies. All rights reserved.
|
|
2
|
+
# Author: Parmeshwar Kumawat
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import json
|
|
6
|
+
import tempfile
|
|
7
|
+
import shutil
|
|
8
|
+
import zipfile
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
def convert(datasetspath, format, newformat, location):
|
|
13
|
+
try:
|
|
14
|
+
import datumaro
|
|
15
|
+
except ImportError:
|
|
16
|
+
raise Exception("datumaro==0.3.1 is not installed")
|
|
17
|
+
filename = datetime.now().strftime("%Y_%m_%d-%I_%M_%S_%p")
|
|
18
|
+
annotationfile = os.path.join(location, newformat + "_" + filename)
|
|
19
|
+
tempdir1, tempdir2 = tempfile.mkdtemp(), tempfile.mkdtemp()
|
|
20
|
+
|
|
21
|
+
with zipfile.ZipFile(datasetspath, 'r') as zip_ref:
|
|
22
|
+
zip_ref.extractall(tempdir1)
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
dataset = datumaro.Dataset.import_from(tempdir1, format)
|
|
26
|
+
dataset.export(tempdir2, format=newformat, save_images=False)
|
|
27
|
+
shutil.make_archive(annotationfile, 'zip', tempdir2)
|
|
28
|
+
|
|
29
|
+
except Exception as e:
|
|
30
|
+
shutil.rmtree(tempdir1)
|
|
31
|
+
shutil.rmtree(tempdir2)
|
|
32
|
+
raise e
|
|
33
|
+
|
|
34
|
+
print("Saved : ", annotationfile + ".zip")
|
|
35
|
+
shutil.rmtree(tempdir1)
|
|
36
|
+
shutil.rmtree(tempdir2)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def create(frames, raw_annotations, labels, annotationfile, annotationformat):
|
|
40
|
+
try:
|
|
41
|
+
import datumaro as dm
|
|
42
|
+
except ImportError:
|
|
43
|
+
raise Exception("datumaro==0.3.1 is not installed")
|
|
44
|
+
assert annotationformat in (
|
|
45
|
+
'coco', 'yolo', 'voc', 'datumaro'), f"invalid dataset format : {annotationformat}"
|
|
46
|
+
|
|
47
|
+
labels_ = {}
|
|
48
|
+
attributes_ = {}
|
|
49
|
+
categories_ = {}
|
|
50
|
+
categories_idx = 0
|
|
51
|
+
for label in labels:
|
|
52
|
+
labels_[label.id] = label.name
|
|
53
|
+
for attr in label.attributes:
|
|
54
|
+
attributes_[attr.id] = attr.name
|
|
55
|
+
|
|
56
|
+
image_id = 1
|
|
57
|
+
dataset_items = []
|
|
58
|
+
|
|
59
|
+
for raw_annotation in raw_annotations:
|
|
60
|
+
|
|
61
|
+
annotations_ = {}
|
|
62
|
+
shapes = raw_annotation['shapes']
|
|
63
|
+
task_id = raw_annotation['task_id']
|
|
64
|
+
for shape in shapes:
|
|
65
|
+
if not shape['type']:
|
|
66
|
+
annotations_[shape["frame"]] = []
|
|
67
|
+
continue
|
|
68
|
+
points = shape['points']
|
|
69
|
+
attributes = {"occluded": shape["occluded"]}
|
|
70
|
+
for attr in shape['attributes']:
|
|
71
|
+
attributes[attributes_[attr['spec_id']]] = attr['value']
|
|
72
|
+
|
|
73
|
+
label_name = labels_[shape['label_id']]
|
|
74
|
+
if label_name not in categories_:
|
|
75
|
+
categories_[label_name] = categories_idx
|
|
76
|
+
label_id = categories_idx
|
|
77
|
+
categories_idx += 1
|
|
78
|
+
else:
|
|
79
|
+
label_id = categories_[label_name]
|
|
80
|
+
|
|
81
|
+
if shape['type'] == 'rectangle':
|
|
82
|
+
annotation = dm.Bbox(points[0], points[1], points[2]-points[0], points[3]-points[1],
|
|
83
|
+
label=label_id, group=shape['group'],
|
|
84
|
+
z_order=shape['z_order'], attributes=attributes)
|
|
85
|
+
|
|
86
|
+
elif shape['type'] == 'polygon':
|
|
87
|
+
annotation = dm.Polygon(points, label=label_id,
|
|
88
|
+
group=shape['group'], z_order=shape['z_order'], attributes=attributes)
|
|
89
|
+
|
|
90
|
+
elif shape['type'] == 'points':
|
|
91
|
+
annotation = dm.Points(points, label=label_id,
|
|
92
|
+
group=shape['group'], z_order=shape['z_order'], attributes=attributes)
|
|
93
|
+
|
|
94
|
+
elif shape['type'] == 'polyline':
|
|
95
|
+
annotation = dm.PolyLine(points, label=label_id,
|
|
96
|
+
group=shape['group'], z_order=shape['z_order'], attributes=attributes)
|
|
97
|
+
|
|
98
|
+
elif shape['type'] == 'cuboid':
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
if shape["frame"] in annotations_:
|
|
102
|
+
annotations_[shape["frame"]].append(annotation)
|
|
103
|
+
else:
|
|
104
|
+
annotations_[shape["frame"]] = [annotation]
|
|
105
|
+
|
|
106
|
+
for frame_id, frame_obj in frames[task_id].items():
|
|
107
|
+
w, h = frame_obj.width, frame_obj.height
|
|
108
|
+
name, ext = os.path.splitext(frame_obj.name)
|
|
109
|
+
try:
|
|
110
|
+
frame_anno = annotations_[frame_id]
|
|
111
|
+
except KeyError:
|
|
112
|
+
frame_anno = []
|
|
113
|
+
dataset_item = dm.DatasetItem(id=name,
|
|
114
|
+
media=dm.components.media.Image(data=np.zeros(
|
|
115
|
+
shape=(h, w, 3)), ext=ext),
|
|
116
|
+
subset=None,
|
|
117
|
+
attributes={'id': image_id},
|
|
118
|
+
annotations=frame_anno
|
|
119
|
+
)
|
|
120
|
+
dataset_items.append(dataset_item)
|
|
121
|
+
image_id += 1
|
|
122
|
+
|
|
123
|
+
dataset = dm.Dataset.from_iterable(
|
|
124
|
+
dataset_items, categories=list(categories_.keys()))
|
|
125
|
+
|
|
126
|
+
tempdir = tempfile.mkdtemp()
|
|
127
|
+
dataset.export(tempdir, format=annotationformat, save_images=False)
|
|
128
|
+
try:
|
|
129
|
+
shutil.make_archive(annotationfile, 'zip', tempdir)
|
|
130
|
+
except Exception as e:
|
|
131
|
+
shutil.rmtree(tempdir)
|
|
132
|
+
raise e
|
|
133
|
+
print("Downloaded : ", annotationfile + ".zip")
|
|
134
|
+
shutil.rmtree(tempdir)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _verify_annotations(file_path,annotation_format,labels):
|
|
138
|
+
if annotation_format=='segmentation_mask':
|
|
139
|
+
raise Exception('format not supported')
|
|
140
|
+
|
|
141
|
+
label_set = set()
|
|
142
|
+
for label in labels:
|
|
143
|
+
label_set.add(label.name)
|
|
144
|
+
|
|
145
|
+
tempDir = tempfile.mkdtemp()
|
|
146
|
+
with zipfile.ZipFile(file_path, 'r') as zip_ref:
|
|
147
|
+
zip_ref.extractall(tempDir)
|
|
148
|
+
|
|
149
|
+
if annotation_format == 'mindkosh':
|
|
150
|
+
category_set = validate_mk_datasets(file_path)
|
|
151
|
+
elif annotation_format == 'kitti':
|
|
152
|
+
category_set = validate_kitti_datasets(file_path)
|
|
153
|
+
elif annotation_format == 'cvat':
|
|
154
|
+
return
|
|
155
|
+
else:
|
|
156
|
+
try:
|
|
157
|
+
import datumaro
|
|
158
|
+
except ImportError:
|
|
159
|
+
raise Exception("datumaro==0.3.1 is not installed")
|
|
160
|
+
dataset = datumaro.Dataset.import_from(tempDir, annotation_format)
|
|
161
|
+
categories = dataset.categories()
|
|
162
|
+
category_dict = (next(iter(categories.values()))._indices)
|
|
163
|
+
if annotation_format=='voc':
|
|
164
|
+
category_dict.pop('background',None)
|
|
165
|
+
category_set = set(category_dict.keys())
|
|
166
|
+
|
|
167
|
+
if not category_set.issubset(label_set):
|
|
168
|
+
raise Exception(f"""task doesn't have all labels that are present in annotation files.
|
|
169
|
+
task labels : {label_set}
|
|
170
|
+
labels present in annotations : {category_set}"""
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def validate_mk_datasets(file_path):
|
|
175
|
+
"""Returns labels present in datasets
|
|
176
|
+
"""
|
|
177
|
+
labels = set()
|
|
178
|
+
supported_anno_types = ['boxes', 'polylines', 'points', 'cuboids', 'polygons', 'tags']
|
|
179
|
+
def get_labels(data):
|
|
180
|
+
meta = data["annotations"]["meta"]
|
|
181
|
+
images = data["annotations"]["images"]
|
|
182
|
+
|
|
183
|
+
label_id_name_mapping = {}
|
|
184
|
+
attr_id_name_mapping = {}
|
|
185
|
+
for label in meta["task"]["labels"]:
|
|
186
|
+
label_id_name_mapping[label["id"]] = label["name"]
|
|
187
|
+
for attr in label["attributes"]:
|
|
188
|
+
attr_id_name_mapping[attr["id"]] = attr["name"]
|
|
189
|
+
|
|
190
|
+
for image in images:
|
|
191
|
+
for anno_type in supported_anno_types:
|
|
192
|
+
if anno_type in image:
|
|
193
|
+
for anno in image[anno_type]:
|
|
194
|
+
label = label_id_name_mapping[anno['label']]
|
|
195
|
+
labels.add(label)
|
|
196
|
+
|
|
197
|
+
if anno_type == 'boxes':
|
|
198
|
+
assert all([v in anno for v in ('xtl','ytl','xbr','ybr')])
|
|
199
|
+
elif anno_type == 'cuboids':
|
|
200
|
+
assert all([v in anno for v in ('xtl1','ytl1','xbl1','ybl1','xtr1','ytr1',
|
|
201
|
+
'xbr1','ybr1','xtl2','ytl2','xbl2','ybl2','xtr2','ytr2','xbr2','ybr2')])
|
|
202
|
+
elif anno_type == 'polygons':
|
|
203
|
+
group = anno['group_id']
|
|
204
|
+
if group is not None:
|
|
205
|
+
assert isinstance(group, int) and group >= 0
|
|
206
|
+
for polygon_obj in anno['objects']:
|
|
207
|
+
assert 'points' in polygon_obj and len(polygon_obj['points']) % 2 == 0
|
|
208
|
+
else:
|
|
209
|
+
assert 'points' in anno and len(anno['points']) % 2 == 0
|
|
210
|
+
|
|
211
|
+
is_zip = zipfile.is_zipfile(file_path)
|
|
212
|
+
try:
|
|
213
|
+
if is_zip:
|
|
214
|
+
with zipfile.ZipFile(file_path,"r") as zf:
|
|
215
|
+
for filename in zf.namelist():
|
|
216
|
+
if filename.endswith('.json'):
|
|
217
|
+
with zf.open(filename) as f:
|
|
218
|
+
json_data = json.loads(f.read().decode("utf-8"))
|
|
219
|
+
get_labels(json_data)
|
|
220
|
+
else:
|
|
221
|
+
get_labels(json.load(open(file_path)))
|
|
222
|
+
except Exception as e:
|
|
223
|
+
raise Exception(f"Couldn't find mindkosh annotations at {file_path}")
|
|
224
|
+
|
|
225
|
+
return labels
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def validate_kitti_datasets(file_path):
|
|
229
|
+
"""Returns labels present in datasets
|
|
230
|
+
"""
|
|
231
|
+
#TODO: Needs to be updated according to the new mindkosh_3d format
|
|
232
|
+
labels = set()
|
|
233
|
+
def get_labels(tracklets):
|
|
234
|
+
tracklet_json = json.loads(tracklets)
|
|
235
|
+
annotations = tracklet_json['boost_serialization']['tracklets']['item']
|
|
236
|
+
for anno in annotations:
|
|
237
|
+
labels.add(anno['objectType'])
|
|
238
|
+
assert all([v in anno for v in ('h','l','w','frame')])
|
|
239
|
+
assert all([v in anno['poses']['item'] for v in ('tx','ty','tz','rx','ry','rz')])
|
|
240
|
+
|
|
241
|
+
try:
|
|
242
|
+
with zipfile.ZipFile(file_path,"r") as zf:
|
|
243
|
+
label_attrspec = zf.read('label_attrspec.json')
|
|
244
|
+
tracklet_labels = zf.read('tracklet_labels.json')
|
|
245
|
+
segmentations = zf.read('segmentations.json')
|
|
246
|
+
frame_list = zf.read('frame_list.txt')
|
|
247
|
+
|
|
248
|
+
label_items = json.loads(label_attrspec)
|
|
249
|
+
get_labels(tracklet_labels)
|
|
250
|
+
except:
|
|
251
|
+
raise Exception(f"Couldn't find kitti annotations at {file_path}")
|
|
252
|
+
|
|
253
|
+
return labels
|
|
254
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Tag:
|
|
2
|
+
def __init__(
|
|
3
|
+
self,
|
|
4
|
+
id,
|
|
5
|
+
frame,
|
|
6
|
+
label_id,
|
|
7
|
+
group,
|
|
8
|
+
source,
|
|
9
|
+
attributes,
|
|
10
|
+
**kwargs
|
|
11
|
+
):
|
|
12
|
+
self.id = id
|
|
13
|
+
self.frame = frame
|
|
14
|
+
self.label_id = label_id
|
|
15
|
+
self.group = group
|
|
16
|
+
self.source = source
|
|
17
|
+
self.attributes = attributes
|
|
18
|
+
self.label_name = kwargs['label_name']
|
|
19
|
+
|
|
20
|
+
def __str__(self):
|
|
21
|
+
return str(self.__dict__)
|
|
22
|
+
|
|
23
|
+
def __repr__(self) -> str:
|
|
24
|
+
return self.label_name
|