python-wml 3.0.0__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 python-wml might be problematic. Click here for more details.

Files changed (164) hide show
  1. python_wml-3.0.0.dist-info/LICENSE +23 -0
  2. python_wml-3.0.0.dist-info/METADATA +51 -0
  3. python_wml-3.0.0.dist-info/RECORD +164 -0
  4. python_wml-3.0.0.dist-info/WHEEL +5 -0
  5. python_wml-3.0.0.dist-info/top_level.txt +1 -0
  6. wml/__init__.py +0 -0
  7. wml/basic_data_def/__init__.py +2 -0
  8. wml/basic_data_def/detection_data_def.py +279 -0
  9. wml/basic_data_def/io_data_def.py +2 -0
  10. wml/basic_img_utils.py +816 -0
  11. wml/img_patch.py +92 -0
  12. wml/img_utils.py +571 -0
  13. wml/iotoolkit/__init__.py +17 -0
  14. wml/iotoolkit/aic_keypoint.py +115 -0
  15. wml/iotoolkit/baidu_mask_toolkit.py +244 -0
  16. wml/iotoolkit/base_dataset.py +210 -0
  17. wml/iotoolkit/bboxes_statistics.py +515 -0
  18. wml/iotoolkit/build.py +0 -0
  19. wml/iotoolkit/cityscapes_toolkit.py +183 -0
  20. wml/iotoolkit/classification_data_statistics.py +25 -0
  21. wml/iotoolkit/coco_data_fwd.py +225 -0
  22. wml/iotoolkit/coco_keypoints.py +118 -0
  23. wml/iotoolkit/coco_keypoints_fmt2.py +103 -0
  24. wml/iotoolkit/coco_toolkit.py +397 -0
  25. wml/iotoolkit/coco_wholebody.py +269 -0
  26. wml/iotoolkit/common.py +108 -0
  27. wml/iotoolkit/crowd_pose.py +146 -0
  28. wml/iotoolkit/fast_labelme.py +110 -0
  29. wml/iotoolkit/image_folder.py +95 -0
  30. wml/iotoolkit/imgs_cache.py +58 -0
  31. wml/iotoolkit/imgs_reader_mt.py +73 -0
  32. wml/iotoolkit/labelme_base.py +102 -0
  33. wml/iotoolkit/labelme_json_to_img.py +49 -0
  34. wml/iotoolkit/labelme_toolkit.py +117 -0
  35. wml/iotoolkit/labelme_toolkit_fwd.py +733 -0
  36. wml/iotoolkit/labelmemckeypoints_dataset.py +169 -0
  37. wml/iotoolkit/lspet.py +48 -0
  38. wml/iotoolkit/mapillary_vistas_toolkit.py +269 -0
  39. wml/iotoolkit/mat_data.py +90 -0
  40. wml/iotoolkit/mckeypoints_statistics.py +28 -0
  41. wml/iotoolkit/mot_datasets.py +62 -0
  42. wml/iotoolkit/mpii.py +108 -0
  43. wml/iotoolkit/npmckeypoints_dataset.py +164 -0
  44. wml/iotoolkit/o365_to_coco.py +136 -0
  45. wml/iotoolkit/object365_toolkit.py +156 -0
  46. wml/iotoolkit/object365v2_toolkit.py +71 -0
  47. wml/iotoolkit/pascal_voc_data.py +51 -0
  48. wml/iotoolkit/pascal_voc_toolkit.py +194 -0
  49. wml/iotoolkit/pascal_voc_toolkit_fwd.py +473 -0
  50. wml/iotoolkit/penn_action.py +57 -0
  51. wml/iotoolkit/rawframe_dataset.py +129 -0
  52. wml/iotoolkit/rewrite_pascal_voc.py +28 -0
  53. wml/iotoolkit/semantic_data.py +49 -0
  54. wml/iotoolkit/split_file_by_type.py +29 -0
  55. wml/iotoolkit/sports_mot_datasets.py +78 -0
  56. wml/iotoolkit/vis_objectdetection_dataset.py +70 -0
  57. wml/iotoolkit/vis_torch_data.py +39 -0
  58. wml/iotoolkit/yolo_toolkit.py +38 -0
  59. wml/object_detection2/__init__.py +4 -0
  60. wml/object_detection2/basic_visualization.py +37 -0
  61. wml/object_detection2/bboxes.py +812 -0
  62. wml/object_detection2/data_process_toolkit.py +146 -0
  63. wml/object_detection2/keypoints.py +292 -0
  64. wml/object_detection2/mask.py +120 -0
  65. wml/object_detection2/metrics/__init__.py +3 -0
  66. wml/object_detection2/metrics/build.py +15 -0
  67. wml/object_detection2/metrics/classifier_toolkit.py +440 -0
  68. wml/object_detection2/metrics/common.py +71 -0
  69. wml/object_detection2/metrics/mckps_toolkit.py +338 -0
  70. wml/object_detection2/metrics/toolkit.py +1953 -0
  71. wml/object_detection2/npod_toolkit.py +361 -0
  72. wml/object_detection2/odtools.py +243 -0
  73. wml/object_detection2/standard_names.py +75 -0
  74. wml/object_detection2/visualization.py +956 -0
  75. wml/object_detection2/wmath.py +34 -0
  76. wml/semantic/__init__.py +0 -0
  77. wml/semantic/basic_toolkit.py +65 -0
  78. wml/semantic/mask_utils.py +156 -0
  79. wml/semantic/semantic_test.py +21 -0
  80. wml/semantic/structures.py +1 -0
  81. wml/semantic/toolkit.py +105 -0
  82. wml/semantic/visualization_utils.py +658 -0
  83. wml/threadtoolkit.py +50 -0
  84. wml/walgorithm.py +228 -0
  85. wml/wcollections.py +212 -0
  86. wml/wfilesystem.py +487 -0
  87. wml/wml_utils.py +657 -0
  88. wml/wstructures/__init__.py +4 -0
  89. wml/wstructures/common.py +9 -0
  90. wml/wstructures/keypoints_train_toolkit.py +149 -0
  91. wml/wstructures/kps_structures.py +579 -0
  92. wml/wstructures/mask_structures.py +1161 -0
  93. wml/wtorch/__init__.py +8 -0
  94. wml/wtorch/bboxes.py +104 -0
  95. wml/wtorch/classes_suppression.py +24 -0
  96. wml/wtorch/conv_module.py +181 -0
  97. wml/wtorch/conv_ws.py +144 -0
  98. wml/wtorch/data/__init__.py +16 -0
  99. wml/wtorch/data/_utils/__init__.py +45 -0
  100. wml/wtorch/data/_utils/collate.py +183 -0
  101. wml/wtorch/data/_utils/fetch.py +47 -0
  102. wml/wtorch/data/_utils/pin_memory.py +121 -0
  103. wml/wtorch/data/_utils/signal_handling.py +72 -0
  104. wml/wtorch/data/_utils/worker.py +227 -0
  105. wml/wtorch/data/base_data_loader_iter.py +93 -0
  106. wml/wtorch/data/dataloader.py +501 -0
  107. wml/wtorch/data/datapipes/__init__.py +1 -0
  108. wml/wtorch/data/datapipes/iter/__init__.py +12 -0
  109. wml/wtorch/data/datapipes/iter/batch.py +126 -0
  110. wml/wtorch/data/datapipes/iter/callable.py +92 -0
  111. wml/wtorch/data/datapipes/iter/listdirfiles.py +37 -0
  112. wml/wtorch/data/datapipes/iter/loadfilesfromdisk.py +30 -0
  113. wml/wtorch/data/datapipes/iter/readfilesfromtar.py +60 -0
  114. wml/wtorch/data/datapipes/iter/readfilesfromzip.py +63 -0
  115. wml/wtorch/data/datapipes/iter/sampler.py +94 -0
  116. wml/wtorch/data/datapipes/utils/__init__.py +0 -0
  117. wml/wtorch/data/datapipes/utils/common.py +65 -0
  118. wml/wtorch/data/dataset.py +354 -0
  119. wml/wtorch/data/datasets/__init__.py +4 -0
  120. wml/wtorch/data/datasets/common.py +53 -0
  121. wml/wtorch/data/datasets/listdirfilesdataset.py +36 -0
  122. wml/wtorch/data/datasets/loadfilesfromdiskdataset.py +30 -0
  123. wml/wtorch/data/distributed.py +135 -0
  124. wml/wtorch/data/multi_processing_data_loader_iter.py +866 -0
  125. wml/wtorch/data/sampler.py +267 -0
  126. wml/wtorch/data/single_process_data_loader_iter.py +24 -0
  127. wml/wtorch/data/test_data_loader.py +26 -0
  128. wml/wtorch/dataset_toolkit.py +67 -0
  129. wml/wtorch/depthwise_separable_conv_module.py +98 -0
  130. wml/wtorch/dist.py +591 -0
  131. wml/wtorch/dropblock/__init__.py +6 -0
  132. wml/wtorch/dropblock/dropblock.py +228 -0
  133. wml/wtorch/dropblock/dropout.py +40 -0
  134. wml/wtorch/dropblock/scheduler.py +48 -0
  135. wml/wtorch/ema.py +61 -0
  136. wml/wtorch/fc_module.py +73 -0
  137. wml/wtorch/functional.py +34 -0
  138. wml/wtorch/iter_dataset.py +26 -0
  139. wml/wtorch/loss.py +69 -0
  140. wml/wtorch/nets/__init__.py +0 -0
  141. wml/wtorch/nets/ckpt_toolkit.py +219 -0
  142. wml/wtorch/nets/fpn.py +276 -0
  143. wml/wtorch/nets/hrnet/__init__.py +0 -0
  144. wml/wtorch/nets/hrnet/config.py +2 -0
  145. wml/wtorch/nets/hrnet/hrnet.py +494 -0
  146. wml/wtorch/nets/misc.py +249 -0
  147. wml/wtorch/nets/resnet/__init__.py +0 -0
  148. wml/wtorch/nets/resnet/layers/__init__.py +17 -0
  149. wml/wtorch/nets/resnet/layers/aspp.py +144 -0
  150. wml/wtorch/nets/resnet/layers/batch_norm.py +231 -0
  151. wml/wtorch/nets/resnet/layers/blocks.py +111 -0
  152. wml/wtorch/nets/resnet/layers/wrappers.py +110 -0
  153. wml/wtorch/nets/resnet/r50_config.py +38 -0
  154. wml/wtorch/nets/resnet/resnet.py +691 -0
  155. wml/wtorch/nets/shape_spec.py +20 -0
  156. wml/wtorch/nets/simple_fpn.py +101 -0
  157. wml/wtorch/nms.py +109 -0
  158. wml/wtorch/nn.py +896 -0
  159. wml/wtorch/ocr_block.py +193 -0
  160. wml/wtorch/summary.py +331 -0
  161. wml/wtorch/train_toolkit.py +603 -0
  162. wml/wtorch/transformer_blocks.py +266 -0
  163. wml/wtorch/utils.py +719 -0
  164. wml/wtorch/wlr_scheduler.py +100 -0
@@ -0,0 +1,397 @@
1
+ from __future__ import absolute_import
2
+ from __future__ import division
3
+ from __future__ import print_function
4
+ import json
5
+ import os
6
+ import numpy as np
7
+ from pycocotools import mask
8
+ import wml.wml_utils as wmlu
9
+ import wml.img_utils as wmli
10
+ import wml.object_detection2.bboxes as odb
11
+ import sys
12
+ from PIL import Image
13
+ from wml.iotoolkit.coco_data_fwd import *
14
+ import copy
15
+ import os.path as osp
16
+ from wml.iotoolkit.pascal_voc_toolkit import read_voc_xml
17
+ from collections import defaultdict
18
+ from .common import *
19
+ from functools import partial
20
+
21
+
22
+
23
+ def create_category_index(categories):
24
+ """Creates dictionary of COCO compatible categories keyed by category id.
25
+
26
+ Args:
27
+ categories: a list of dicts, each of which has the following keys:
28
+ 'id': (required) an integer id uniquely identifying this category.
29
+ 'name': (required) string representing category name
30
+ e.g., 'cat', 'dog', 'pizza'.
31
+
32
+ Returns:
33
+ category_index: a dict containing the same entries as categories, but keyed
34
+ by the 'id' field of each category.
35
+ """
36
+ category_index = {}
37
+ for cat in categories:
38
+ category_index[cat['id']] = cat
39
+ return category_index
40
+
41
+ class COCOData:
42
+ load_patch = False
43
+ def __init__(self,trans_label=None,include_masks=True,is_relative_coordinate=False,remove_crowd=True,*args,**kwargs):
44
+ '''
45
+
46
+ Args:
47
+ trans_label: label fn(label) : return transed label if label is useful else return None
48
+ include_masks:
49
+ '''
50
+ self.images = None
51
+ self.annotations_index = None
52
+ self.image_dir = None
53
+ self.include_masks = include_masks
54
+ self.category_index = None
55
+ self.id2name = None #same as category_index
56
+ if isinstance(trans_label,dict):
57
+ self.trans_label= partial(dict_label_text2id,dict_data=trans_label)
58
+ else:
59
+ self.trans_label = trans_label
60
+ self.filename2image = None
61
+ self.is_relative_coordinate = is_relative_coordinate
62
+ self.ids = []
63
+ self.trans_file_name = None # fn(filename,image_dir)->filename
64
+ self.update_id2name = True
65
+ self.remove_crowd = remove_crowd
66
+ self.patchs_index = []
67
+
68
+ def get_image_full_path(self,image):
69
+ filename = image['file_name']
70
+ return os.path.join(self.image_dir, filename)
71
+
72
+ @staticmethod
73
+ def get_image_dir_by_annotations_file(path):
74
+ dir_name = wmlu.parent_dir_path_of_file(path)
75
+ basename = wmlu.base_name(path).split("_")[-1]
76
+ #return osp.join(dir_name,"images",basename)
77
+ return osp.join(dir_name,basename)
78
+
79
+ def read_data(self,annotations_file,image_dir=None,*args,**kwargs):
80
+ if image_dir is None:
81
+ image_dir = self.get_image_dir_by_annotations_file(annotations_file)
82
+ print(f"image dir {image_dir}")
83
+ if self.trans_label is not None:
84
+ print(f"Trans label is not None")
85
+ sys.stdout.flush()
86
+ image_id2shape = {}
87
+ with open(annotations_file, 'r') as fid:
88
+ groundtruth_data = json.load(fid)
89
+ _images = groundtruth_data['images']
90
+ category_index = create_category_index(
91
+ groundtruth_data['categories'])
92
+ for image in groundtruth_data['images']:
93
+ image_id2shape[image['id']] = (image['height'],image['width'])
94
+
95
+ annotations_index = {}
96
+ if 'annotations' in groundtruth_data:
97
+ print(
98
+ 'Found groundtruth annotations. Building annotations index.')
99
+ for annotation in groundtruth_data['annotations']:
100
+ if self.trans_label is not None:
101
+ category_id = annotation['category_id']
102
+ new_category_id = self.trans_label(category_id)
103
+ if new_category_id is None:
104
+ continue
105
+ else:
106
+ annotation['category_id'] = new_category_id
107
+ if self.remove_crowd and annotation['iscrowd']:
108
+ continue
109
+ image_id = annotation['image_id']
110
+ bbox = annotation['bbox']
111
+ bbox = self.check_bbox(bbox,image_id2shape[image_id])
112
+ if bbox is None:
113
+ continue
114
+ annotation['bbox'] = bbox
115
+ annotation['name'] = category_index[category_id]['name']
116
+ if image_id not in annotations_index:
117
+ annotations_index[image_id] = []
118
+ annotations_index[image_id].append(copy.deepcopy(annotation))
119
+ missing_annotation_count = 0
120
+ images = []
121
+ for image in _images:
122
+ #image["file_name"] = osp.basename(image['file_name'])
123
+ image_id = image['id']
124
+ if image_id not in annotations_index:
125
+ missing_annotation_count += 1
126
+ annotations_index[image_id] = []
127
+ else:
128
+ images.append(image)
129
+ print(f'{missing_annotation_count} images are missing annotations.')
130
+
131
+ self.image_dir = image_dir
132
+ if self.trans_file_name is not None:
133
+ _images = images
134
+ images = []
135
+ for image in _images:
136
+ image["file_name"] = self.trans_file_name(image["file_name"],self.image_dir)
137
+ images.append(image)
138
+ self.images = images
139
+ self.annotations_index = annotations_index
140
+ self.category_index = category_index
141
+ self.ids = [image["id"] for image in images]
142
+ if self.trans_label is None:
143
+ self.id2name = {}
144
+ for id,info in self.category_index.items():
145
+ self.id2name[id] = info['name']
146
+ wmlu.show_dict(self.id2name)
147
+ '''if COCOData.load_patch:
148
+ self._load_patch()'''
149
+
150
+
151
+ def _load_patch(self):
152
+ if not COCOData.load_patch:
153
+ return
154
+
155
+ patchs_index = []
156
+
157
+ for idx,image in enumerate(self.images):
158
+ image_id = image['id']
159
+ annotations_list = self.annotations_index[image_id]
160
+ full_path = self.get_image_full_path(image)
161
+ patch_path = wmlu.change_suffix(full_path,"xml")
162
+ if not osp.exists(patch_path):
163
+ continue
164
+ shape, bboxes, labels_text, difficult, truncated, probs = read_voc_xml(patch_path,absolute_coord=True)
165
+ if bboxes.shape[0] == 0:
166
+ continue
167
+
168
+ bboxes = odb.npchangexyorder(bboxes)
169
+ labels = [int(x) for x in labels_text]
170
+
171
+ old_len = len(annotations_list)
172
+ for i in range(bboxes.shape[0]):
173
+ bbox = bboxes[i]
174
+ bbox[2:] = bbox[2:]-bbox[:2]
175
+ area = np.prod(bbox[2:])
176
+ annotation = {"bbox":bbox,"category_id":labels[i],"iscrowd":False,"area":area}
177
+ annotations_list.append(annotation)
178
+
179
+ print(f"Load patch {patch_path}, old len {old_len}, new len {len(self.annotations_index[image_id])}.")
180
+
181
+ patchs_index.append(idx)
182
+
183
+ self.patchs_index = set(patchs_index)
184
+
185
+
186
+ def __len__(self):
187
+ return len(self.ids)
188
+
189
+ def __getitem__(self, item):
190
+ '''
191
+ binary_masks:[N,H,W]
192
+ '''
193
+ image = self.images[item]
194
+ res = self.get_image_annotation(image)
195
+ return res
196
+
197
+ def filter(self,filter_func):
198
+ '''
199
+ filter_func(labels,bboxes,is_crowd)->bool
200
+ '''
201
+ old_images = self.images
202
+ new_images = []
203
+ for image in old_images:
204
+ x = self.get_image_annotation(image)
205
+ full_path,img_shape,category_ids,category_names,boxes,binary_masks,area,is_crowd,num_annotations_skipped = x
206
+ if filter_func(labels=category_ids,bboxes=boxes,is_crowd=is_crowd):
207
+ new_images.append(image)
208
+ self.images = new_images
209
+ self.ids = [image["id"] for image in new_images]
210
+ print(f"Old len {len(old_images)}, new len {len(new_images)}")
211
+
212
+ def get_image_id(self,item):
213
+ return self.images[item]["id"]
214
+
215
+ def get_image_annotation_by_image_name(self,file_name):
216
+ if self.filename2image is None:
217
+ self.filename2image = {}
218
+ for image in self.images:
219
+ tfile_name = image["file_name"]
220
+ self.filename2image[tfile_name] = image
221
+
222
+ image = self.filename2image[file_name]
223
+
224
+ return self.get_image_annotation(image)
225
+
226
+ def check_bbox(self,bbox,img_shape):
227
+ image_height,image_width = img_shape
228
+ (x, y, width, height) = bbox
229
+ if width <= 0 or height <= 0:
230
+ return None
231
+ if x<0:
232
+ x = 0
233
+ if y<0:
234
+ y=0
235
+ if x>=image_width:
236
+ x = image_width-1
237
+ if y>=image_height:
238
+ y = image_height-1
239
+ if x + width > image_width:
240
+ width = image_width-x
241
+ if y + height > image_height:
242
+ height = image_height-y
243
+ if width <= 0 or height <= 0:
244
+ return None
245
+ return (x,y,width,height)
246
+
247
+ def get_image_annotation(self,image):
248
+ image_height = image['height']
249
+ image_width = image['width']
250
+ image_id = image['id']
251
+
252
+ full_path = self.get_image_full_path(image)
253
+
254
+ xmin = []
255
+ xmax = []
256
+ ymin = []
257
+ ymax = []
258
+ is_crowd = []
259
+ category_names = []
260
+ category_ids = []
261
+ area = []
262
+ num_annotations_skipped = 0
263
+ annotations_list = self.annotations_index[image_id]
264
+ binary_masks = []
265
+ for object_annotations in annotations_list:
266
+ (x, y, width, height) = tuple(object_annotations['bbox'])
267
+ category_id = int(object_annotations['category_id'])
268
+ org_category_id = category_id
269
+
270
+ if self.is_relative_coordinate:
271
+ xmin.append(float(x) / image_width)
272
+ xmax.append(float(x + width) / image_width)
273
+ ymin.append(float(y) / image_height)
274
+ ymax.append(float(y + height) / image_height)
275
+ else:
276
+ xmin.append(float(x))
277
+ xmax.append(float(x + width))
278
+ ymin.append(float(y))
279
+ ymax.append(float(y + height))
280
+
281
+ is_crowd.append(object_annotations['iscrowd'])
282
+ category_ids.append(category_id)
283
+ category_names.append(object_annotations['name'])
284
+ area.append(object_annotations['area'])
285
+
286
+ if self.include_masks:
287
+ run_len_encoding = mask.frPyObjects(object_annotations['segmentation'],
288
+ image_height, image_width)
289
+ binary_mask = mask.decode(run_len_encoding)
290
+ if not object_annotations['iscrowd']:
291
+ binary_mask = np.amax(binary_mask, axis=2)
292
+ binary_masks.append(binary_mask)
293
+
294
+ boxes = np.array(list(zip(ymin,xmin,ymax,xmax)),dtype=np.float32)
295
+
296
+ if len(binary_masks)>0:
297
+ binary_masks = np.stack(binary_masks,axis=0)
298
+ else:
299
+ binary_masks = None
300
+
301
+ img_shape = [image_height,image_width]
302
+
303
+ if len(category_ids)==0:
304
+ print("No annotation: ", full_path)
305
+ sys.stdout.flush()
306
+ return DetData(full_path,img_shape,[],[],np.zeros([0,4],dtype=np.float32),None,[],[],num_annotations_skipped)
307
+
308
+ category_ids = np.array(category_ids,dtype=np.int32)
309
+ return DetData(full_path,img_shape,category_ids,category_names,boxes,binary_masks,area,is_crowd,num_annotations_skipped)
310
+
311
+ def get_items(self):
312
+ for image in self.images:
313
+ res = self.get_image_annotation(image)
314
+ if res[0] is not None:
315
+ yield res
316
+
317
+ def get_boxes_items(self):
318
+ for image in self.images:
319
+ full_path,img_size,category_ids,category_names,boxes,binary_mask,area,is_crowd,num_annotations_skipped = \
320
+ self.get_image_annotation(image)
321
+ if full_path is not None:
322
+ yield DetBboxesData(full_path,img_size,category_ids,boxes,is_crowd)
323
+
324
+
325
+ class TorchCOCOData(COCOData):
326
+ def __init__(self, img_dir, anno_path,trans_label=None):
327
+ super().__init__(is_relative_coordinate=False,trans_label=trans_label)
328
+ super().read_data(anno_path, img_dir)
329
+
330
+ def __getitem__(self, item):
331
+ x = super().__getitem__(item)
332
+ full_path, shape, category_ids, category_names, boxes, binary_mask, area, is_crowd, num_annotations_skipped = x
333
+ try:
334
+ img = wmli.imread(full_path)
335
+ except Exception as e:
336
+ print(f"Read {full_path} faild, error:{e}")
337
+ img = np.zeros([shape[0],shape[1],3],dtype=np.uint8)
338
+ img = Image.fromarray(img)
339
+ res = []
340
+ nr = len(category_ids)
341
+ boxes = odb.npchangexyorder(boxes)
342
+ boxes[..., 2:] = boxes[..., 2:] - boxes[..., :2]
343
+ #new bboxes is [N,4], [x0,y0,w,h]
344
+ for i in range(nr):
345
+ item = {"bbox": boxes[i], "category_id": category_ids[i], "iscrowd": is_crowd[i],"area":area[i]}
346
+ res.append(item)
347
+
348
+ return img, res
349
+
350
+ def load_coco_results(json_path):
351
+ with open(json_path,"r") as f:
352
+ data = json.load(f)
353
+ res = wmlu.MDict(dvalue=wmlu.MDict(dtype=list))
354
+ r_res = wmlu.MDict(dvalue=wmlu.MDict(dtype=list))
355
+ if not isinstance(data,list) and 'annotations' in data:
356
+ data = data['annotations']
357
+ """
358
+ {
359
+ "image_id": original_id,
360
+ "category_id": labels[k],
361
+ "bbox": box,
362
+ "score": scores[k],
363
+ }
364
+ """
365
+ for re in data:
366
+ image_id = re["image_id"]
367
+ category_id = re["category_id"]
368
+ bbox = re["bbox"]
369
+ score = re.get("score",1.0)
370
+ res[image_id]["bbox"].append(bbox)
371
+ res[image_id]["category_id"].append(category_id)
372
+ res[image_id]["score"].append(score)
373
+
374
+ for k,v in res.items():
375
+ for k0,v0 in v.items():
376
+ r_res[k][k0] = np.array(v0)
377
+
378
+ return r_res
379
+
380
+ if __name__ == "__main__":
381
+ import wml.img_utils as wmli
382
+ import wml.object_detection2.visualization as odv
383
+ import matplotlib.pyplot as plt
384
+ data = COCOData()
385
+ data.read_data("/data/mldata/coco/annotations/instances_train2014.json",image_dir="/data/mldata/coco/train2014")
386
+ for x in data.get_items():
387
+ full_path, category_ids, category_names, boxes, binary_mask, area, is_crowd, num_annotations_skipped = x
388
+ img = wmli.imread(full_path)
389
+ def text_fn(classes,scores):
390
+ return ID_TO_TEXT[classes]['name']
391
+ odv.draw_bboxes_and_maskv2(
392
+ img=img, classes=category_ids, scores=None, bboxes=boxes, masks=binary_mask, color_fn = None, text_fn = text_fn, thickness = 4,
393
+ show_text = True,
394
+ fontScale = 0.8)
395
+ plt.figure()
396
+ plt.imshow(img)
397
+ plt.show()
@@ -0,0 +1,269 @@
1
+ from __future__ import absolute_import
2
+ from __future__ import division
3
+ from __future__ import print_function
4
+ import json
5
+ import os
6
+ import numpy as np
7
+ from pycocotools import mask
8
+ import wml.wml_utils as wmlu
9
+ import sys
10
+ import wml.object_detection2.keypoints as odk
11
+
12
+ def get_yxyx_bbox(bbox_data):
13
+ (x, y, width, height) = tuple(bbox_data)
14
+ return y,x,y+height,x+width
15
+
16
+ def get_xy_kps(kps_data):
17
+ kps_data = np.array(kps_data,dtype=np.float32)
18
+ kps_data = np.reshape(kps_data,[-1,3])
19
+ return kps_data
20
+
21
+ ID2NAMES = {
22
+ 1:"person",
23
+ 2:"lefthand",
24
+ 3:"righthand",
25
+ 4:"face",
26
+ }
27
+
28
+ def create_category_index(categories):
29
+ """Creates dictionary of COCO compatible categories keyed by category id.
30
+
31
+ Args:
32
+ categories: a list of dicts, each of which has the following keys:
33
+ 'id': (required) an integer id uniquely identifying this category.
34
+ 'name': (required) string representing category name
35
+ e.g., 'cat', 'dog', 'pizza'.
36
+
37
+ Returns:
38
+ category_index: a dict containing the same entries as categories, but keyed
39
+ by the 'id' field of each category.
40
+ """
41
+ category_index = {}
42
+ for cat in categories:
43
+ category_index[cat['id']] = cat
44
+ return category_index
45
+
46
+ class COCOWholeBodyData:
47
+ def __init__(self,trans_label=None,include_masks=False,no_crowd=True):
48
+ '''
49
+
50
+ Args:
51
+ trans_label: label fn(label) : return transed label is label is useful else return None
52
+ include_masks:
53
+ '''
54
+ self.images = None
55
+ self.annotations_index = None
56
+ self.image_dir = None
57
+ self.include_masks = include_masks
58
+ self.category_index = None
59
+ self.trans_label = trans_label
60
+ self.no_crowd = no_crowd
61
+
62
+ def get_image_full_path(self,image):
63
+ filename = image['file_name']
64
+ return os.path.join(self.image_dir, filename)
65
+
66
+ def read_data(self,annotations_file,image_dir):
67
+ with open(annotations_file, 'r') as fid:
68
+ groundtruth_data = json.load(fid)
69
+ images = groundtruth_data['images']
70
+ category_index = create_category_index(
71
+ groundtruth_data['categories'])
72
+
73
+ annotations_index = {}
74
+ if 'annotations' in groundtruth_data:
75
+ print('Found groundtruth annotations. Building annotations index.')
76
+ for annotation in groundtruth_data['annotations']:
77
+ image_id = annotation['image_id']
78
+ if image_id not in annotations_index:
79
+ annotations_index[image_id] = []
80
+ annotations_index[image_id].append(annotation)
81
+ missing_annotation_count = 0
82
+ for image in images:
83
+ image_id = image['id']
84
+ if image_id not in annotations_index:
85
+ missing_annotation_count += 1
86
+ annotations_index[image_id] = []
87
+ print('%d images are missing annotations.',
88
+ missing_annotation_count)
89
+
90
+ self.images = images
91
+ self.annotations_index = annotations_index
92
+ self.image_dir = image_dir
93
+ self.category_index = category_index
94
+
95
+ def get_image_annotation(self,image):
96
+ image_height = image['height']
97
+ image_width = image['width']
98
+ image_id = image['id']
99
+
100
+ full_path = self.get_image_full_path(image)
101
+
102
+ xmin = []
103
+ xmax = []
104
+ ymin = []
105
+ ymax = []
106
+ is_crowd = []
107
+ category_names = []
108
+ category_ids = []
109
+ area = []
110
+ num_annotations_skipped = 0
111
+ annotations_list = self.annotations_index[image_id]
112
+ binary_masks = []
113
+ lefthand_bboxes = []
114
+ righthand_bboxes = []
115
+ face_bboxes = []
116
+ keypoints = []
117
+ if image["file_name"] == "000000292082.jpg":
118
+ print("A")
119
+ for object_annotations in annotations_list:
120
+ (x, y, width, height) = tuple(object_annotations['bbox'])
121
+ if width <= 0 or height <= 0:
122
+ num_annotations_skipped += 1
123
+ continue
124
+ if x<0 or x>=image_width or y<0 or y>=image_height:
125
+ num_annotations_skipped += 1
126
+ continue
127
+ if x + width > image_width:
128
+ width = image_width-x
129
+ if y + height > image_height:
130
+ height = image_height-y
131
+
132
+
133
+ category_id = int(object_annotations['category_id'])
134
+ org_category_id = category_id
135
+ iscrowd = object_annotations['iscrowd']
136
+ if self.no_crowd and iscrowd:
137
+ continue
138
+ if self.trans_label is not None:
139
+ category_id = self.trans_label(category_id)
140
+ if category_id is None:
141
+ continue
142
+
143
+ cur_kps = []
144
+ cur_kps.append(get_xy_kps(object_annotations["keypoints"]))
145
+ lh_kps = get_xy_kps(object_annotations["lefthand_kpts"])
146
+ cur_kps.append(lh_kps)
147
+ rh_kps = get_xy_kps(object_annotations["righthand_kpts"])
148
+ cur_kps.append(rh_kps)
149
+ fc_kps = get_xy_kps(object_annotations['face_kpts'])
150
+ cur_kps.append(fc_kps)
151
+ keypoints.append(np.concatenate(cur_kps,axis=0))
152
+
153
+ lh_box = get_yxyx_bbox(object_annotations['lefthand_box'])
154
+ #lh_box = odk.expand_yxyx_bbox_by_kps(lh_box,lh_kps,threshold=0.1)
155
+ lefthand_bboxes.append(lh_box)
156
+ rh_box = get_yxyx_bbox(object_annotations['righthand_box'])
157
+ #rh_box = odk.expand_yxyx_bbox_by_kps(rh_box,rh_kps,threshold=0.1)
158
+ righthand_bboxes.append(rh_box)
159
+ fc_box = get_yxyx_bbox(object_annotations['face_box'])
160
+ #fc_box = odk.expand_yxyx_bbox_by_kps(fc_box,fc_kps,threshold=0.1)
161
+ face_bboxes.append(fc_box)
162
+
163
+ xmin.append(float(x) )
164
+ xmax.append(float(x + width))
165
+ ymin.append(float(y))
166
+ ymax.append(float(y + height))
167
+
168
+ is_crowd.append(iscrowd)
169
+ category_ids.append(category_id)
170
+ category_names.append(str(self.category_index[org_category_id]['name'].encode('utf8'),encoding='utf-8'))
171
+ area.append(object_annotations['area'])
172
+
173
+ if self.include_masks:
174
+ run_len_encoding = mask.frPyObjects(object_annotations['segmentation'],
175
+ image_height, image_width)
176
+ binary_mask = mask.decode(run_len_encoding)
177
+ if not object_annotations['iscrowd']:
178
+ binary_mask = np.amax(binary_mask, axis=2)
179
+ binary_masks.append(binary_mask)
180
+
181
+ boxes = np.array(list(zip(ymin,xmin,ymax,xmax)))
182
+ lefthand_bboxes = np.array(lefthand_bboxes)
183
+ righthand_bboxes = np.array(righthand_bboxes)
184
+ face_bboxes = np.array(face_bboxes)
185
+ keypoints = np.array(keypoints)
186
+
187
+ if len(binary_masks)>0:
188
+ binary_masks = np.stack(binary_masks,axis=0)
189
+ else:
190
+ binary_masks = None
191
+
192
+ if len(category_ids)==0:
193
+ print("No annotation: ", full_path)
194
+ sys.stdout.flush()
195
+ return None,None,None,None,None,None,None,None,None
196
+ category_ids = np.array(category_ids,dtype=np.int32)
197
+ return full_path,[image_height,image_width],category_ids,category_names,boxes,\
198
+ lefthand_bboxes,righthand_bboxes,face_bboxes,keypoints, \
199
+ binary_masks,area,is_crowd,num_annotations_skipped
200
+
201
+ def __len__(self):
202
+ return len(self.images)
203
+
204
+ def __getitem__(self, item):
205
+ image = self.images[item]
206
+ res = self.get_image_annotation(image)
207
+ return res
208
+
209
+ @staticmethod
210
+ def trans2bboxes(data):
211
+ full_path,img_shape,category_ids,category_names,boxes, \
212
+ lefthand_bboxes,righthand_bboxes,face_bboxes,keypoints, \
213
+ binary_masks,area,is_crowd,num_annotations_skipped = data
214
+ assert np.all(np.array(category_ids)==1),f"Error category {category_ids}"
215
+ lh_nr = lefthand_bboxes.shape[0]
216
+ rh_nr = righthand_bboxes.shape[0]
217
+ fc_nr = face_bboxes.shape[0]
218
+ lh_category = np.ones([lh_nr],dtype=np.int32)*2
219
+ rh_category = np.ones([rh_nr],dtype=np.int32)*3
220
+ fc_category = np.ones([fc_nr],dtype=np.int32)*4
221
+ all_bboxes = np.concatenate([boxes,lefthand_bboxes,righthand_bboxes,face_bboxes],axis=0)
222
+ categorys = np.concatenate([category_ids,lh_category,rh_category,fc_category],axis=0)
223
+ mask = np.max(all_bboxes,axis=-1)>0.5
224
+ all_bboxes = all_bboxes[mask]
225
+ categorys = categorys[mask]
226
+ category_names = [ID2NAMES[id] for id in categorys]
227
+
228
+ return full_path,img_shape,categorys,category_names,all_bboxes,keypoints
229
+
230
+
231
+ def get_items(self):
232
+ for image in self.images:
233
+ res = self.get_image_annotation(image)
234
+ if res[0] is not None:
235
+ yield res
236
+
237
+ def get_boxes_items(self):
238
+ for image in self.images:
239
+ anno_data = self.get_image_annotation(image)
240
+ if anno_data[0] is not None:
241
+ yield self.trans2bboxes(anno_data)
242
+
243
+ if __name__ == "__main__":
244
+ import wml.img_utils as wmli
245
+ import wml.object_detection2.visualization as odv
246
+ import matplotlib.pyplot as plt
247
+ data = COCOWholeBodyData()
248
+ data.read_data("/home/wj/ai/mldata/coco/annotations/coco_wholebody_val_v1.0.json",
249
+ image_dir="/home/wj/ai/mldata/coco/val2017")
250
+ save_dir = "/home/wj/ai/mldata/0day/tmp"
251
+ wmlu.create_empty_dir(save_dir,remove_if_exists=False)
252
+ for i,x in enumerate(data.get_boxes_items()):
253
+ full_path, img_shape, categorys, category_names, bboxes,kps = x
254
+ if 2 not in categorys and 3 not in categorys:
255
+ continue
256
+ img = wmli.imread(full_path)
257
+ def text_fn(classes,scores):
258
+ return ID2NAMES[classes]
259
+ img = odv.draw_bboxes(
260
+ img=img, classes=categorys, scores=None, bboxes=bboxes, color_fn = None,
261
+ text_fn = text_fn, thickness = 4,
262
+ show_text = True,
263
+ font_scale = 0.8,is_relative_coordinate=False)
264
+ #img = odv.draw_keypoints(img,kps,no_line=True)
265
+ save_path = wmlu.change_dirname(full_path,save_dir)
266
+ wmli.imwrite(save_path,img)
267
+ if i>100:
268
+ break
269
+