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.
- python_wml-3.0.0.dist-info/LICENSE +23 -0
- python_wml-3.0.0.dist-info/METADATA +51 -0
- python_wml-3.0.0.dist-info/RECORD +164 -0
- python_wml-3.0.0.dist-info/WHEEL +5 -0
- python_wml-3.0.0.dist-info/top_level.txt +1 -0
- wml/__init__.py +0 -0
- wml/basic_data_def/__init__.py +2 -0
- wml/basic_data_def/detection_data_def.py +279 -0
- wml/basic_data_def/io_data_def.py +2 -0
- wml/basic_img_utils.py +816 -0
- wml/img_patch.py +92 -0
- wml/img_utils.py +571 -0
- wml/iotoolkit/__init__.py +17 -0
- wml/iotoolkit/aic_keypoint.py +115 -0
- wml/iotoolkit/baidu_mask_toolkit.py +244 -0
- wml/iotoolkit/base_dataset.py +210 -0
- wml/iotoolkit/bboxes_statistics.py +515 -0
- wml/iotoolkit/build.py +0 -0
- wml/iotoolkit/cityscapes_toolkit.py +183 -0
- wml/iotoolkit/classification_data_statistics.py +25 -0
- wml/iotoolkit/coco_data_fwd.py +225 -0
- wml/iotoolkit/coco_keypoints.py +118 -0
- wml/iotoolkit/coco_keypoints_fmt2.py +103 -0
- wml/iotoolkit/coco_toolkit.py +397 -0
- wml/iotoolkit/coco_wholebody.py +269 -0
- wml/iotoolkit/common.py +108 -0
- wml/iotoolkit/crowd_pose.py +146 -0
- wml/iotoolkit/fast_labelme.py +110 -0
- wml/iotoolkit/image_folder.py +95 -0
- wml/iotoolkit/imgs_cache.py +58 -0
- wml/iotoolkit/imgs_reader_mt.py +73 -0
- wml/iotoolkit/labelme_base.py +102 -0
- wml/iotoolkit/labelme_json_to_img.py +49 -0
- wml/iotoolkit/labelme_toolkit.py +117 -0
- wml/iotoolkit/labelme_toolkit_fwd.py +733 -0
- wml/iotoolkit/labelmemckeypoints_dataset.py +169 -0
- wml/iotoolkit/lspet.py +48 -0
- wml/iotoolkit/mapillary_vistas_toolkit.py +269 -0
- wml/iotoolkit/mat_data.py +90 -0
- wml/iotoolkit/mckeypoints_statistics.py +28 -0
- wml/iotoolkit/mot_datasets.py +62 -0
- wml/iotoolkit/mpii.py +108 -0
- wml/iotoolkit/npmckeypoints_dataset.py +164 -0
- wml/iotoolkit/o365_to_coco.py +136 -0
- wml/iotoolkit/object365_toolkit.py +156 -0
- wml/iotoolkit/object365v2_toolkit.py +71 -0
- wml/iotoolkit/pascal_voc_data.py +51 -0
- wml/iotoolkit/pascal_voc_toolkit.py +194 -0
- wml/iotoolkit/pascal_voc_toolkit_fwd.py +473 -0
- wml/iotoolkit/penn_action.py +57 -0
- wml/iotoolkit/rawframe_dataset.py +129 -0
- wml/iotoolkit/rewrite_pascal_voc.py +28 -0
- wml/iotoolkit/semantic_data.py +49 -0
- wml/iotoolkit/split_file_by_type.py +29 -0
- wml/iotoolkit/sports_mot_datasets.py +78 -0
- wml/iotoolkit/vis_objectdetection_dataset.py +70 -0
- wml/iotoolkit/vis_torch_data.py +39 -0
- wml/iotoolkit/yolo_toolkit.py +38 -0
- wml/object_detection2/__init__.py +4 -0
- wml/object_detection2/basic_visualization.py +37 -0
- wml/object_detection2/bboxes.py +812 -0
- wml/object_detection2/data_process_toolkit.py +146 -0
- wml/object_detection2/keypoints.py +292 -0
- wml/object_detection2/mask.py +120 -0
- wml/object_detection2/metrics/__init__.py +3 -0
- wml/object_detection2/metrics/build.py +15 -0
- wml/object_detection2/metrics/classifier_toolkit.py +440 -0
- wml/object_detection2/metrics/common.py +71 -0
- wml/object_detection2/metrics/mckps_toolkit.py +338 -0
- wml/object_detection2/metrics/toolkit.py +1953 -0
- wml/object_detection2/npod_toolkit.py +361 -0
- wml/object_detection2/odtools.py +243 -0
- wml/object_detection2/standard_names.py +75 -0
- wml/object_detection2/visualization.py +956 -0
- wml/object_detection2/wmath.py +34 -0
- wml/semantic/__init__.py +0 -0
- wml/semantic/basic_toolkit.py +65 -0
- wml/semantic/mask_utils.py +156 -0
- wml/semantic/semantic_test.py +21 -0
- wml/semantic/structures.py +1 -0
- wml/semantic/toolkit.py +105 -0
- wml/semantic/visualization_utils.py +658 -0
- wml/threadtoolkit.py +50 -0
- wml/walgorithm.py +228 -0
- wml/wcollections.py +212 -0
- wml/wfilesystem.py +487 -0
- wml/wml_utils.py +657 -0
- wml/wstructures/__init__.py +4 -0
- wml/wstructures/common.py +9 -0
- wml/wstructures/keypoints_train_toolkit.py +149 -0
- wml/wstructures/kps_structures.py +579 -0
- wml/wstructures/mask_structures.py +1161 -0
- wml/wtorch/__init__.py +8 -0
- wml/wtorch/bboxes.py +104 -0
- wml/wtorch/classes_suppression.py +24 -0
- wml/wtorch/conv_module.py +181 -0
- wml/wtorch/conv_ws.py +144 -0
- wml/wtorch/data/__init__.py +16 -0
- wml/wtorch/data/_utils/__init__.py +45 -0
- wml/wtorch/data/_utils/collate.py +183 -0
- wml/wtorch/data/_utils/fetch.py +47 -0
- wml/wtorch/data/_utils/pin_memory.py +121 -0
- wml/wtorch/data/_utils/signal_handling.py +72 -0
- wml/wtorch/data/_utils/worker.py +227 -0
- wml/wtorch/data/base_data_loader_iter.py +93 -0
- wml/wtorch/data/dataloader.py +501 -0
- wml/wtorch/data/datapipes/__init__.py +1 -0
- wml/wtorch/data/datapipes/iter/__init__.py +12 -0
- wml/wtorch/data/datapipes/iter/batch.py +126 -0
- wml/wtorch/data/datapipes/iter/callable.py +92 -0
- wml/wtorch/data/datapipes/iter/listdirfiles.py +37 -0
- wml/wtorch/data/datapipes/iter/loadfilesfromdisk.py +30 -0
- wml/wtorch/data/datapipes/iter/readfilesfromtar.py +60 -0
- wml/wtorch/data/datapipes/iter/readfilesfromzip.py +63 -0
- wml/wtorch/data/datapipes/iter/sampler.py +94 -0
- wml/wtorch/data/datapipes/utils/__init__.py +0 -0
- wml/wtorch/data/datapipes/utils/common.py +65 -0
- wml/wtorch/data/dataset.py +354 -0
- wml/wtorch/data/datasets/__init__.py +4 -0
- wml/wtorch/data/datasets/common.py +53 -0
- wml/wtorch/data/datasets/listdirfilesdataset.py +36 -0
- wml/wtorch/data/datasets/loadfilesfromdiskdataset.py +30 -0
- wml/wtorch/data/distributed.py +135 -0
- wml/wtorch/data/multi_processing_data_loader_iter.py +866 -0
- wml/wtorch/data/sampler.py +267 -0
- wml/wtorch/data/single_process_data_loader_iter.py +24 -0
- wml/wtorch/data/test_data_loader.py +26 -0
- wml/wtorch/dataset_toolkit.py +67 -0
- wml/wtorch/depthwise_separable_conv_module.py +98 -0
- wml/wtorch/dist.py +591 -0
- wml/wtorch/dropblock/__init__.py +6 -0
- wml/wtorch/dropblock/dropblock.py +228 -0
- wml/wtorch/dropblock/dropout.py +40 -0
- wml/wtorch/dropblock/scheduler.py +48 -0
- wml/wtorch/ema.py +61 -0
- wml/wtorch/fc_module.py +73 -0
- wml/wtorch/functional.py +34 -0
- wml/wtorch/iter_dataset.py +26 -0
- wml/wtorch/loss.py +69 -0
- wml/wtorch/nets/__init__.py +0 -0
- wml/wtorch/nets/ckpt_toolkit.py +219 -0
- wml/wtorch/nets/fpn.py +276 -0
- wml/wtorch/nets/hrnet/__init__.py +0 -0
- wml/wtorch/nets/hrnet/config.py +2 -0
- wml/wtorch/nets/hrnet/hrnet.py +494 -0
- wml/wtorch/nets/misc.py +249 -0
- wml/wtorch/nets/resnet/__init__.py +0 -0
- wml/wtorch/nets/resnet/layers/__init__.py +17 -0
- wml/wtorch/nets/resnet/layers/aspp.py +144 -0
- wml/wtorch/nets/resnet/layers/batch_norm.py +231 -0
- wml/wtorch/nets/resnet/layers/blocks.py +111 -0
- wml/wtorch/nets/resnet/layers/wrappers.py +110 -0
- wml/wtorch/nets/resnet/r50_config.py +38 -0
- wml/wtorch/nets/resnet/resnet.py +691 -0
- wml/wtorch/nets/shape_spec.py +20 -0
- wml/wtorch/nets/simple_fpn.py +101 -0
- wml/wtorch/nms.py +109 -0
- wml/wtorch/nn.py +896 -0
- wml/wtorch/ocr_block.py +193 -0
- wml/wtorch/summary.py +331 -0
- wml/wtorch/train_toolkit.py +603 -0
- wml/wtorch/transformer_blocks.py +266 -0
- wml/wtorch/utils.py +719 -0
- 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
|
+
|