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
wml/iotoolkit/common.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import wml.wml_utils as wmlu
|
|
3
|
+
import PIL
|
|
4
|
+
import wml.img_utils as wmli
|
|
5
|
+
import os.path as osp
|
|
6
|
+
import glob
|
|
7
|
+
from collections import namedtuple
|
|
8
|
+
|
|
9
|
+
DetData = namedtuple('DetData','path,img_shape,labels,labels_name,bboxes,masks,area,is_crowd,extra_data') #img_shape:(H,W)
|
|
10
|
+
DetBboxesData = namedtuple('DetBboxesdata','path,img_shape,labels,bboxes,is_crowd')
|
|
11
|
+
|
|
12
|
+
def __get_resample_nr(labels,resample_parameters):
|
|
13
|
+
nr = 1
|
|
14
|
+
for l in labels:
|
|
15
|
+
if l in resample_parameters:
|
|
16
|
+
nr = max(nr,resample_parameters[l])
|
|
17
|
+
return nr
|
|
18
|
+
|
|
19
|
+
def resample(files,labels,resample_parameters):
|
|
20
|
+
'''
|
|
21
|
+
files: list of files
|
|
22
|
+
labels: list of labels
|
|
23
|
+
resample_parameters: {labels:resample_nr}
|
|
24
|
+
'''
|
|
25
|
+
new_files = []
|
|
26
|
+
repeat_files_nr = 0
|
|
27
|
+
repeat_nr = 0
|
|
28
|
+
for f,l in zip(files,labels):
|
|
29
|
+
nr = __get_resample_nr(l,resample_parameters)
|
|
30
|
+
if nr>1:
|
|
31
|
+
new_files = new_files+[f]*nr
|
|
32
|
+
#print(f"Repeat {f} {nr} times.")
|
|
33
|
+
repeat_files_nr += 1
|
|
34
|
+
repeat_nr += nr
|
|
35
|
+
elif nr==1:
|
|
36
|
+
new_files.append(f)
|
|
37
|
+
print(f"Total repeat {repeat_files_nr} files, total repeat {repeat_nr} times.")
|
|
38
|
+
print(f"{len(files)} old files --> {len(new_files)} new files")
|
|
39
|
+
|
|
40
|
+
return new_files
|
|
41
|
+
|
|
42
|
+
def get_shape_from_img(xml_path,img_path):
|
|
43
|
+
'''
|
|
44
|
+
return: [H,W]
|
|
45
|
+
'''
|
|
46
|
+
if not os.path.exists(img_path):
|
|
47
|
+
img_path = wmlu.change_suffix(xml_path, "jpg")
|
|
48
|
+
if not os.path.exists(img_path):
|
|
49
|
+
img_path = wmlu.change_suffix(xml_path, "jpeg")
|
|
50
|
+
return wmli.get_img_size(img_path)
|
|
51
|
+
|
|
52
|
+
def ignore_case_dict_label_text2id(name,dict_data):
|
|
53
|
+
name = name.lower()
|
|
54
|
+
if name not in dict_data:
|
|
55
|
+
print(f"ERROR: trans {name} faild.")
|
|
56
|
+
return dict_data.get(name,None)
|
|
57
|
+
|
|
58
|
+
def dict_label_text2id(name,dict_data):
|
|
59
|
+
if name not in dict_data:
|
|
60
|
+
print(f"ERROR: trans {name} faild.")
|
|
61
|
+
return dict_data.get(name,None)
|
|
62
|
+
|
|
63
|
+
def find_imgs_for_ann_file(ann_path):
|
|
64
|
+
ann_path = osp.abspath(ann_path)
|
|
65
|
+
img_suffix = [".jpg",".jpeg",".bmp",".png",".gif"]
|
|
66
|
+
pattern = wmlu.change_suffix(ann_path,"*")
|
|
67
|
+
files = glob.glob(pattern)
|
|
68
|
+
img_file = None
|
|
69
|
+
for file in files:
|
|
70
|
+
if file==ann_path:
|
|
71
|
+
continue
|
|
72
|
+
if osp.splitext(file)[1].lower() in img_suffix:
|
|
73
|
+
img_file = file
|
|
74
|
+
else:
|
|
75
|
+
print(f"WARNING: Unknow img format file {file} for {ann_path}")
|
|
76
|
+
img_file = file
|
|
77
|
+
return img_file
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_auto_dataset_suffix(data_dir,suffix="auto"):
|
|
81
|
+
|
|
82
|
+
if isinstance(data_dir,(list,tuple)):
|
|
83
|
+
data_dir = data_dir[0]
|
|
84
|
+
if suffix.lower() != "auto":
|
|
85
|
+
return suffix
|
|
86
|
+
|
|
87
|
+
if isinstance(data_dir,str) and osp.isfile(data_dir):
|
|
88
|
+
with open(data_dir,"r") as f:
|
|
89
|
+
data_dir = f.readline().strip()
|
|
90
|
+
data_dir = data_dir.split(",")[0]
|
|
91
|
+
data_dir = osp.dirname(data_dir)
|
|
92
|
+
|
|
93
|
+
for f in wmlu.find_files(data_dir,suffix=".json"):
|
|
94
|
+
return "json"
|
|
95
|
+
|
|
96
|
+
for f in wmlu.find_files(data_dir,suffix=".xml"):
|
|
97
|
+
return "xml"
|
|
98
|
+
|
|
99
|
+
return "none"
|
|
100
|
+
|
|
101
|
+
def check_dataset_dir(dir_path):
|
|
102
|
+
if isinstance(dir_path,(list,tuple)):
|
|
103
|
+
return dir_path
|
|
104
|
+
if "," in dir_path:
|
|
105
|
+
dir_path = dir_path.split(",")
|
|
106
|
+
return [osp.abspath(osp.expanduser(p)) for p in dir_path]
|
|
107
|
+
else:
|
|
108
|
+
return osp.abspath(osp.expanduser(dir_path))
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import numpy as np
|
|
3
|
+
import wml.object_detection2.visualization as odv
|
|
4
|
+
import wml.object_detection2.bboxes as odb
|
|
5
|
+
import os.path as osp
|
|
6
|
+
import wml.wml_utils as wmlu
|
|
7
|
+
import wml.img_utils as wmli
|
|
8
|
+
import wml.object_detection2.keypoints as odk
|
|
9
|
+
import math
|
|
10
|
+
|
|
11
|
+
'''
|
|
12
|
+
'left_shoulder', 'right_shoulder', 0,1
|
|
13
|
+
'left_elbow', 'right_elbow', 2,3
|
|
14
|
+
'left_wrist', 'right_wrist', 4,5
|
|
15
|
+
'left_hip', 'right_hip', 6,7
|
|
16
|
+
'left_knee', 'right_knee', 8,9
|
|
17
|
+
'left_ankle', 'right_ankle', 10,11
|
|
18
|
+
'head', 'neck' 12,13
|
|
19
|
+
'''
|
|
20
|
+
def read_crowd_pose(file_path):
|
|
21
|
+
with open(file_path,"r") as f:
|
|
22
|
+
datas = json.load(f)
|
|
23
|
+
id2img = {}
|
|
24
|
+
for data in datas['images']:
|
|
25
|
+
id = data['id']
|
|
26
|
+
file_name = data['file_name']
|
|
27
|
+
id2img[id] = file_name
|
|
28
|
+
|
|
29
|
+
res = {}
|
|
30
|
+
for data in datas['annotations']:
|
|
31
|
+
kps = data['keypoints']
|
|
32
|
+
kps = np.array(kps,dtype=np.float32)
|
|
33
|
+
kps = np.reshape(kps,[-1,3])
|
|
34
|
+
if data['iscrowd']:
|
|
35
|
+
continue
|
|
36
|
+
mask = kps[...,2]
|
|
37
|
+
if np.sum(mask)<2:
|
|
38
|
+
continue
|
|
39
|
+
if np.count_nonzero(mask>0.1)<2:
|
|
40
|
+
continue
|
|
41
|
+
bbox = data['bbox']
|
|
42
|
+
bbox = [bbox[0],bbox[1],bbox[0]+bbox[2],bbox[1]+bbox[3]]
|
|
43
|
+
kps_bbox = odk.npget_bbox(kps)
|
|
44
|
+
bbox = odb.bbox_of_boxes([bbox,kps_bbox])
|
|
45
|
+
id = data['image_id']
|
|
46
|
+
image = id2img[id]
|
|
47
|
+
if id not in res:
|
|
48
|
+
res[id] = [image,[kps],[bbox]]
|
|
49
|
+
else:
|
|
50
|
+
res[id][1].append(kps)
|
|
51
|
+
res[id][2].append(bbox)
|
|
52
|
+
|
|
53
|
+
r_res = []
|
|
54
|
+
for k,v in res.items():
|
|
55
|
+
r_res.append([v[0],np.array(v[1]),np.array(v[2])])
|
|
56
|
+
|
|
57
|
+
return r_res
|
|
58
|
+
|
|
59
|
+
class Trans2COCO:
|
|
60
|
+
def __init__(self) -> None:
|
|
61
|
+
self.dst_idxs = [5,6,7,8,9,10,11,12,13,14,15,16]
|
|
62
|
+
self.src_idxs = np.array([0,1,2,3,4,5,6,7,8,9,10,11],dtype=np.int32)
|
|
63
|
+
self.coco_idxs = [0,1,2,3,4]
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def get_head_pos(kp):
|
|
67
|
+
p0 = kp[12]
|
|
68
|
+
p1 = kp[13]
|
|
69
|
+
if p0[2]>0 and p1[2]>0:
|
|
70
|
+
dx = p0[0] - p1[0]
|
|
71
|
+
dy = p0[1] - p1[1]
|
|
72
|
+
dis = math.sqrt(dx*dx+dy*dy)*0.75
|
|
73
|
+
cx = (p0[0] + p1[0])/2
|
|
74
|
+
cy = (p0[1] + p1[1])/2
|
|
75
|
+
x0 = cx-dis
|
|
76
|
+
x1 = cx+dis
|
|
77
|
+
y0 = cy-dis
|
|
78
|
+
y1 = cy+dis
|
|
79
|
+
return [x0,y0,x1,y1]
|
|
80
|
+
else:
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def kps_in_bbox(kps,bbox):
|
|
85
|
+
nr = kps.shape[0]
|
|
86
|
+
for i in range(nr):
|
|
87
|
+
if kps[i,2]<= 0:
|
|
88
|
+
return False
|
|
89
|
+
x = kps[i,0]
|
|
90
|
+
y = kps[i,1]
|
|
91
|
+
if x<bbox[0] or x>bbox[2] or y<bbox[1] or y>bbox[3]:
|
|
92
|
+
return False
|
|
93
|
+
return True
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def __call__(self,mpii_kps,coco_kps):
|
|
97
|
+
if len(mpii_kps.shape)==2:
|
|
98
|
+
return self.trans_one(mpii_kps,coco_kps)
|
|
99
|
+
res = []
|
|
100
|
+
for mp,coco in zip(mpii_kps,coco_kps):
|
|
101
|
+
res.append(self.trans_one(mp,coco))
|
|
102
|
+
return np.array(res)
|
|
103
|
+
|
|
104
|
+
'''def trans_one(self,mpii_kps,coco_kps):
|
|
105
|
+
res = np.zeros([17,3],dtype=np.float32)
|
|
106
|
+
res[self.dst_idxs] = mpii_kps[self.src_idxs]
|
|
107
|
+
res[self.coco_idxs] = coco_kps[self.coco_idxs]
|
|
108
|
+
return res'''
|
|
109
|
+
|
|
110
|
+
def trans_one(self,mpii_kps,coco_kps=None):
|
|
111
|
+
'''
|
|
112
|
+
img: [RGB]
|
|
113
|
+
'''
|
|
114
|
+
res = np.zeros([17,3],dtype=np.float32)
|
|
115
|
+
res[self.dst_idxs] = mpii_kps[self.src_idxs]
|
|
116
|
+
if coco_kps is not None:
|
|
117
|
+
left_right_pairs = [[5,6],[11,12]]
|
|
118
|
+
is_good = True
|
|
119
|
+
for pair in left_right_pairs:
|
|
120
|
+
l,r = pair
|
|
121
|
+
if res[l,0]<res[r,0] or res[l,2]<0.1 or res[r,2]<0.1:
|
|
122
|
+
is_good = False
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
head_bbox = self.get_head_pos(mpii_kps)
|
|
126
|
+
if is_good and head_bbox is not None and self.kps_in_bbox(coco_kps[self.coco_idxs],head_bbox):
|
|
127
|
+
res[self.coco_idxs] = coco_kps[self.coco_idxs]
|
|
128
|
+
return res
|
|
129
|
+
|
|
130
|
+
if __name__ == "__main__":
|
|
131
|
+
file_path = '/home/wj/ai/mldata1/crowd_pose/CrowdPose/crowdpose_train.json'
|
|
132
|
+
images_dir = '/home/wj/ai/mldata1/crowd_pose/images'
|
|
133
|
+
save_dir = '/home/wj/ai/mldata1/crowd_pose/tmp/vis'
|
|
134
|
+
wmlu.create_empty_dir(save_dir,remove_if_exists=False)
|
|
135
|
+
datas = read_crowd_pose(file_path)
|
|
136
|
+
do_vis = True
|
|
137
|
+
for data in datas:
|
|
138
|
+
image_name,kps,bbox = data
|
|
139
|
+
image = osp.join(images_dir,image_name)
|
|
140
|
+
img = wmli.imread(image)
|
|
141
|
+
img = odv.draw_keypoints(img, kps, no_line=True)
|
|
142
|
+
t_bboxes = np.array([bbox])
|
|
143
|
+
t_bboxes = odb.npchangexyorder(t_bboxes)
|
|
144
|
+
img = odv.draw_bboxes(img, bboxes=t_bboxes, is_relative_coordinate=False)
|
|
145
|
+
save_path = osp.join(save_dir,image_name)
|
|
146
|
+
wmli.imwrite(save_path, img)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import wml.wml_utils as wmlu
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import numpy as np
|
|
5
|
+
import cv2 as cv
|
|
6
|
+
import copy
|
|
7
|
+
import wml.img_utils as wmli
|
|
8
|
+
import random
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
import sys
|
|
11
|
+
import cv2
|
|
12
|
+
from wml.object_detection2.standard_names import *
|
|
13
|
+
import wml.object_detection2.bboxes as odb
|
|
14
|
+
from functools import partial
|
|
15
|
+
from .common import *
|
|
16
|
+
from .labelme_toolkit_fwd import *
|
|
17
|
+
from wml.semantic.structures import *
|
|
18
|
+
from .labelme_base import LabelMeBase
|
|
19
|
+
import glob
|
|
20
|
+
|
|
21
|
+
class FastLabelMeData(LabelMeBase):
|
|
22
|
+
'''
|
|
23
|
+
与LabelMeData的区别为生成的Mask使用多边形的方式保存
|
|
24
|
+
'''
|
|
25
|
+
def __init__(self,label_text2id=None,shuffle=True,absolute_coord=True,
|
|
26
|
+
filter_empty_files=False,
|
|
27
|
+
resample_parameters=None,
|
|
28
|
+
read_data_kwargs={'circle_points_nr':20},**kwargs):
|
|
29
|
+
'''
|
|
30
|
+
label_text2id: func(name)->int
|
|
31
|
+
'''
|
|
32
|
+
super().__init__(label_text2id=label_text2id,
|
|
33
|
+
shuffle=shuffle,
|
|
34
|
+
absolute_coord=absolute_coord,
|
|
35
|
+
filter_empty_files=filter_empty_files,
|
|
36
|
+
resample_parameters=resample_parameters,
|
|
37
|
+
read_data_kwargs=read_data_kwargs,**kwargs)
|
|
38
|
+
|
|
39
|
+
def __getitem__(self,idx):
|
|
40
|
+
'''
|
|
41
|
+
:return:
|
|
42
|
+
full_path,img_size,category_ids,category_names,boxes,binary_masks,area,is_crowd,num_annotations_skipped
|
|
43
|
+
binary_masks:[N,H,W]
|
|
44
|
+
bboxes:[N,4] (ymin,xmin,ymax,xmax)
|
|
45
|
+
'''
|
|
46
|
+
img_file, json_file = self.files[idx]
|
|
47
|
+
image, annotations_list = read_labelme_data(json_file, None,mask_on=self.mask_on,use_semantic=True,use_polygon_mask=True,
|
|
48
|
+
**self.read_data_kwargs)
|
|
49
|
+
labels_names,bboxes = get_labels_and_bboxes(image,annotations_list,is_relative_coordinate=not self.absolute_coord)
|
|
50
|
+
masks = [ann["segmentation"] for ann in annotations_list] if self.mask_on else None
|
|
51
|
+
difficult = np.array([v['difficult'] for v in annotations_list],dtype=np.bool)
|
|
52
|
+
img_height = image['height']
|
|
53
|
+
img_width = image['width']
|
|
54
|
+
if masks is not None:
|
|
55
|
+
masks = WPolygonMasks(masks,width=img_width,height=img_height)
|
|
56
|
+
|
|
57
|
+
if self.label_text2id is not None:
|
|
58
|
+
try:
|
|
59
|
+
labels = [self.label_text2id(x) for x in labels_names]
|
|
60
|
+
except:
|
|
61
|
+
labels = []
|
|
62
|
+
keep = [x is not None for x in labels]
|
|
63
|
+
labels = [x if x is not None else -1 for x in labels]
|
|
64
|
+
labels = np.array(labels,dtype=np.int32)
|
|
65
|
+
labels = labels[keep]
|
|
66
|
+
bboxes = bboxes[keep]
|
|
67
|
+
if masks is not None:
|
|
68
|
+
masks = masks[keep]
|
|
69
|
+
difficult = difficult[keep]
|
|
70
|
+
labels_names = np.array(labels_names)[keep]
|
|
71
|
+
else:
|
|
72
|
+
labels = None
|
|
73
|
+
|
|
74
|
+
return DetData(img_file, [image['height'],image['width']],labels, labels_names, bboxes, masks, None, difficult,None)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
#data_statistics("/home/vghost/ai/mldata/qualitycontrol/rdatasv3")
|
|
79
|
+
import wml.img_utils as wmli
|
|
80
|
+
import wml.object_detection2.visualization as odv
|
|
81
|
+
import matplotlib.pyplot as plt
|
|
82
|
+
ID_TO_TEXT = {1:{"id":1,"name":"a"},2:{"id":2,"name":"b"},3:{"id":3,"name":"c"}}
|
|
83
|
+
NAME_TO_ID = {}
|
|
84
|
+
for k,v in ID_TO_TEXT.items():
|
|
85
|
+
NAME_TO_ID[v["name"]] = v["id"]
|
|
86
|
+
def name_to_id(name):
|
|
87
|
+
return NAME_TO_ID[name]
|
|
88
|
+
|
|
89
|
+
data = FastLabelMeData(label_text2id=name_to_id,shuffle=True)
|
|
90
|
+
#data.read_data("/data/mldata/qualitycontrol/rdatasv5_splited/rdatasv5")
|
|
91
|
+
#data.read_data("/home/vghost/ai/mldata2/qualitycontrol/rdatav10_preproc")
|
|
92
|
+
#data.read_data("/home/vghost/ai/mldata2/qualitycontrol/rdatasv10_neg_preproc")
|
|
93
|
+
data.read_data("/home/vghost/ai/mldata2/qualitycontrol/rdatasv10_1x_neg_preproc")
|
|
94
|
+
#data.read_data("/home/vghost/ai/mldata2/qualitycontrol/x")
|
|
95
|
+
for x in data.get_items():
|
|
96
|
+
full_path, img_info,category_ids, category_names, boxes, binary_mask, area, is_crowd, num_annotations_skipped = x
|
|
97
|
+
img = wmli.imread(full_path)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def text_fn(classes, scores):
|
|
101
|
+
return ID_TO_TEXT[classes]['name']
|
|
102
|
+
|
|
103
|
+
odv.draw_bboxes_and_maskv2(
|
|
104
|
+
img=img, classes=category_ids, scores=None, bboxes=boxes, masks=binary_mask, color_fn=None,
|
|
105
|
+
text_fn=text_fn, thickness=4,
|
|
106
|
+
show_text=True,
|
|
107
|
+
fontScale=0.8)
|
|
108
|
+
plt.figure()
|
|
109
|
+
plt.imshow(img)
|
|
110
|
+
plt.show()
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import wml.wml_utils as wmlu
|
|
2
|
+
import os.path as osp
|
|
3
|
+
import wml.img_utils as wmli
|
|
4
|
+
import copy
|
|
5
|
+
|
|
6
|
+
class ImageFolder:
|
|
7
|
+
def __init__(self,label_text2id=None,classes=None):
|
|
8
|
+
self.label_text2id = label_text2id
|
|
9
|
+
self._classes = classes
|
|
10
|
+
self._data = []
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
def read_one_dir(self,data_dir):
|
|
14
|
+
sub_dirs = wmlu.get_subdir_in_dir(data_dir)
|
|
15
|
+
if self._classes is None:
|
|
16
|
+
self._classes = copy.deepcopy(sub_dirs)
|
|
17
|
+
else:
|
|
18
|
+
for sd in sub_dirs:
|
|
19
|
+
if sd not in self._classes:
|
|
20
|
+
self._classes.append(sd)
|
|
21
|
+
for dir in sub_dirs:
|
|
22
|
+
label = dir.lower()
|
|
23
|
+
if self.label_text2id is not None:
|
|
24
|
+
label = self.label_text2id(label)
|
|
25
|
+
files = wmlu.get_files(osp.join(data_dir,dir),suffix=wmli.BASE_IMG_SUFFIX)
|
|
26
|
+
for f in files:
|
|
27
|
+
self._data.append((label,f))
|
|
28
|
+
|
|
29
|
+
def read_data(self,data_dir):
|
|
30
|
+
self._data = []
|
|
31
|
+
if isinstance(data_dir,(str,bytes)):
|
|
32
|
+
self.read_one_dir(data_dir)
|
|
33
|
+
elif isinstance(data_dir,(list,tuple)):
|
|
34
|
+
for dir in data_dir:
|
|
35
|
+
self.read_one_dir(dir)
|
|
36
|
+
else:
|
|
37
|
+
print(f"ERROR: error data dir type {type(data_dir)}, {data_dir}")
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def classes(self):
|
|
41
|
+
return self._classes
|
|
42
|
+
|
|
43
|
+
def __len__(self):
|
|
44
|
+
return len(self._data)
|
|
45
|
+
|
|
46
|
+
def __getitem__(self,idx):
|
|
47
|
+
return self._data[idx]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def get_label(file_path):
|
|
52
|
+
dirname = osp.dirname(osp.abspath(file_path))
|
|
53
|
+
label = osp.basename(dirname).lower()
|
|
54
|
+
if "(" in label and ")" in label:
|
|
55
|
+
idx0 = label.index("(")
|
|
56
|
+
idx1 = label.index(")")
|
|
57
|
+
if idx0<idx1:
|
|
58
|
+
label = label[:idx0]+label[idx1+1:]
|
|
59
|
+
return label
|
|
60
|
+
|
|
61
|
+
class ImageFolder2:
|
|
62
|
+
'''
|
|
63
|
+
使用文件父目录作为标签
|
|
64
|
+
'''
|
|
65
|
+
def __init__(self,label_text2id=None,classes=None):
|
|
66
|
+
self.label_text2id = label_text2id
|
|
67
|
+
self._classes = classes
|
|
68
|
+
self._data = []
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
def read_data(self,data_dir):
|
|
72
|
+
files = wmlu.get_files(data_dir,suffix=wmli.BASE_IMG_SUFFIX)
|
|
73
|
+
classes = set()
|
|
74
|
+
for f in files:
|
|
75
|
+
label = ImageFolder2.get_label(f)
|
|
76
|
+
self._data.append((label,f))
|
|
77
|
+
classes.add(label)
|
|
78
|
+
if self._classes is None:
|
|
79
|
+
self._classes = list(classes)
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def classes(self):
|
|
83
|
+
return self._classes
|
|
84
|
+
|
|
85
|
+
def __len__(self):
|
|
86
|
+
return len(self._data)
|
|
87
|
+
|
|
88
|
+
def __getitem__(self,idx):
|
|
89
|
+
return self._data[idx]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def get_label(file_path):
|
|
94
|
+
dirname = osp.dirname(osp.abspath(file_path)).replace(" ","")
|
|
95
|
+
return osp.basename(dirname).lower()
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import cv2
|
|
3
|
+
|
|
4
|
+
class ImgsCache(object):
|
|
5
|
+
def __init__(self,files,img_size=None,cache_limit=-1,mem_limit=-1):
|
|
6
|
+
'''
|
|
7
|
+
Args:
|
|
8
|
+
files: list of img files path.
|
|
9
|
+
img_size: (H,W)
|
|
10
|
+
cache_limit: cache number limit
|
|
11
|
+
mem_limit: meme limit (G)
|
|
12
|
+
'''
|
|
13
|
+
self.img_files = files
|
|
14
|
+
self.img_size = img_size
|
|
15
|
+
if cache_limit<=1 and mem_limit>0 and img_size is not None:
|
|
16
|
+
per_img_size = img_size[0]*img_size[1]*3
|
|
17
|
+
cache_limit = mem_limit*1e6/per_img_size
|
|
18
|
+
self.cache_limit = cache_limit
|
|
19
|
+
self.cache_data = {}
|
|
20
|
+
print(f"Cache limit is {self.cache_limit}.")
|
|
21
|
+
|
|
22
|
+
def __getitem__(self, item):
|
|
23
|
+
assert isinstance(item,int), f"Error item type: {item}"
|
|
24
|
+
if item in self.cache_data:
|
|
25
|
+
return self.cache_data[item].copy()
|
|
26
|
+
else:
|
|
27
|
+
img = self.load_image_data(item)
|
|
28
|
+
if self.cache_limit<=1 \
|
|
29
|
+
or (self.cache_limit>1 and len(self.cache_data)<self.cache_limit):
|
|
30
|
+
self.cache_data[item] = img.copy()
|
|
31
|
+
return img
|
|
32
|
+
|
|
33
|
+
def load_image_data(self,idx):
|
|
34
|
+
if self.img_size is not None:
|
|
35
|
+
return self.load_resized_img(idx)
|
|
36
|
+
else:
|
|
37
|
+
return self.load_image(idx)
|
|
38
|
+
|
|
39
|
+
def load_resized_img(self, index):
|
|
40
|
+
img = self.load_image(index)
|
|
41
|
+
r = min(self.img_size[0] / img.shape[0], self.img_size[1] / img.shape[1])
|
|
42
|
+
resized_img = cv2.resize(
|
|
43
|
+
img,
|
|
44
|
+
(int(img.shape[1] * r), int(img.shape[0] * r)),
|
|
45
|
+
interpolation=cv2.INTER_LINEAR,
|
|
46
|
+
).astype(np.uint8)
|
|
47
|
+
|
|
48
|
+
return resized_img
|
|
49
|
+
|
|
50
|
+
def load_image(self, index):
|
|
51
|
+
img_file = self.img_files[index]
|
|
52
|
+
img = cv2.imread(img_file, cv2.IMREAD_COLOR)
|
|
53
|
+
if img is None or img.shape[0]<2 or img.shape[1]<2:
|
|
54
|
+
print(f"ERROR: error img {img}, shape {img.shape if img is not None else 0}, file_path {self.img_files[index]}")
|
|
55
|
+
raise Exception("Empty img.")
|
|
56
|
+
|
|
57
|
+
return img
|
|
58
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import wml.img_utils as wmli
|
|
2
|
+
import wml.wml_utils as wmlu
|
|
3
|
+
from wml.wtorch.data.dataloader import DataLoader
|
|
4
|
+
from wml.wtorch.data._utils.collate import null_convert,default_collate
|
|
5
|
+
import numpy as np
|
|
6
|
+
import random
|
|
7
|
+
import sys
|
|
8
|
+
import os
|
|
9
|
+
from PIL import Image
|
|
10
|
+
Image.MAX_IMAGE_PIXELS = 1000000000
|
|
11
|
+
|
|
12
|
+
class MaxImgLongSize:
|
|
13
|
+
def __init__(self,max_size=2048):
|
|
14
|
+
self.max_size = max_size
|
|
15
|
+
|
|
16
|
+
def __call__(self,img):
|
|
17
|
+
if img.shape[0]>self.max_size or img.shape[1]>self.max_size:
|
|
18
|
+
img = wmli.resize_long_size(img,self.max_size)
|
|
19
|
+
return img
|
|
20
|
+
|
|
21
|
+
def __repr__(self):
|
|
22
|
+
return f"{type(self).__name__}: max_size={self.max_size}"
|
|
23
|
+
|
|
24
|
+
class ImgsDataset:
|
|
25
|
+
def __init__(self,data_dir_or_files,transform=None,shuffle=True):
|
|
26
|
+
if isinstance(data_dir_or_files,str):
|
|
27
|
+
self.files = wmlu.get_files(data_dir_or_files,suffix=wmli.BASE_IMG_SUFFIX)
|
|
28
|
+
else:
|
|
29
|
+
self.files = data_dir_or_files
|
|
30
|
+
if shuffle:
|
|
31
|
+
random.shuffle(self.files)
|
|
32
|
+
self.transform = transform
|
|
33
|
+
print(f"ImgsDataset transform:")
|
|
34
|
+
print(self.transform)
|
|
35
|
+
|
|
36
|
+
def __len__(self):
|
|
37
|
+
return len(self.files)
|
|
38
|
+
|
|
39
|
+
def __getitem__(self, item):
|
|
40
|
+
path = self.files[item]
|
|
41
|
+
try:
|
|
42
|
+
sys.stdout.flush()
|
|
43
|
+
img = wmli.hpimread(path)
|
|
44
|
+
if self.transform is not None:
|
|
45
|
+
img = self.transform(img)
|
|
46
|
+
return path,img
|
|
47
|
+
#return path,wmli.gpu_imread(path)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
print(f"ERROR: {e}")
|
|
50
|
+
sys.stdout.flush()
|
|
51
|
+
return path,np.zeros([0,0,1],dtype=np.uint8)
|
|
52
|
+
|
|
53
|
+
class ImgsReader:
|
|
54
|
+
def __init__(self, data_dir_or_files, thread_nr=8,transform=None,shuffle=True):
|
|
55
|
+
self.dataset = ImgsDataset(data_dir_or_files,transform=transform,shuffle=shuffle)
|
|
56
|
+
|
|
57
|
+
dataloader_kwargs = {"num_workers": thread_nr, "pin_memory": False}
|
|
58
|
+
dataloader_kwargs["sampler"] = list(range(len(self.dataset)))
|
|
59
|
+
dataloader_kwargs["batch_size"] = None
|
|
60
|
+
dataloader_kwargs["batch_split_nr"] = 1
|
|
61
|
+
dataloader_kwargs['collate_fn'] = null_convert
|
|
62
|
+
#dataloader_kwargs['collate_fn'] = default_collate
|
|
63
|
+
|
|
64
|
+
data_loader = DataLoader(self.dataset, **dataloader_kwargs)
|
|
65
|
+
|
|
66
|
+
self.data_loader = data_loader
|
|
67
|
+
self.data_loader_iter = iter(self.data_loader)
|
|
68
|
+
|
|
69
|
+
def __len__(self):
|
|
70
|
+
return len(self.dataset)
|
|
71
|
+
|
|
72
|
+
def __iter__(self):
|
|
73
|
+
return self.data_loader_iter
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import wml.wml_utils as wmlu
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import numpy as np
|
|
5
|
+
import cv2 as cv
|
|
6
|
+
import copy
|
|
7
|
+
import wml.img_utils as wmli
|
|
8
|
+
import random
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
import sys
|
|
11
|
+
import cv2
|
|
12
|
+
from wml.object_detection2.standard_names import *
|
|
13
|
+
import wml.object_detection2.bboxes as odb
|
|
14
|
+
from functools import partial
|
|
15
|
+
from .common import *
|
|
16
|
+
from .labelme_toolkit_fwd import *
|
|
17
|
+
import glob
|
|
18
|
+
from .base_dataset import BaseDataset
|
|
19
|
+
|
|
20
|
+
class LabelMeBase(BaseDataset):
|
|
21
|
+
def __init__(self,label_text2id=None,shuffle=True,absolute_coord=True,
|
|
22
|
+
filter_empty_files=False,
|
|
23
|
+
filter_error=False,
|
|
24
|
+
resample_parameters=None,
|
|
25
|
+
use_polygon_mask=False,
|
|
26
|
+
silent=False,
|
|
27
|
+
keep_no_ann_imgs=False,
|
|
28
|
+
mask_on=True,
|
|
29
|
+
read_data_kwargs={'circle_points_nr':20}):
|
|
30
|
+
'''
|
|
31
|
+
label_text2id: func(name)->int
|
|
32
|
+
'''
|
|
33
|
+
self.files = None
|
|
34
|
+
super().__init__(label_text2id=label_text2id,
|
|
35
|
+
filter_empty_files=filter_empty_files,
|
|
36
|
+
filter_error=filter_error,
|
|
37
|
+
resample_parameters=resample_parameters,
|
|
38
|
+
shuffle=shuffle,
|
|
39
|
+
silent=silent,
|
|
40
|
+
absolute_coord=absolute_coord,
|
|
41
|
+
keep_no_ann_imgs=keep_no_ann_imgs,
|
|
42
|
+
mask_on=mask_on)
|
|
43
|
+
self.read_data_kwargs = read_data_kwargs
|
|
44
|
+
self.use_polygon_mask = use_polygon_mask
|
|
45
|
+
|
|
46
|
+
def find_files_in_dir(self,dir_path,img_suffix=".jpg;;.bmp;;.png;;.jpeg"):
|
|
47
|
+
files = get_files(dir_path,img_suffix=img_suffix,keep_no_json_img=self.keep_no_ann_imgs)
|
|
48
|
+
return files
|
|
49
|
+
|
|
50
|
+
def get_labels(self,fs):
|
|
51
|
+
img_file,json_file = fs
|
|
52
|
+
image, annotations_list = read_labelme_data(json_file, None,use_semantic=True,mask_on=False,
|
|
53
|
+
use_polygon_mask=True,
|
|
54
|
+
do_raise=True,
|
|
55
|
+
**self.read_data_kwargs)
|
|
56
|
+
labels_names,bboxes = get_labels_and_bboxes(image,annotations_list,is_relative_coordinate=not self.absolute_coord)
|
|
57
|
+
if self.label_text2id:
|
|
58
|
+
labels = [self.label_text2id(x) for x in labels_names] #测试转label是否有误
|
|
59
|
+
else:
|
|
60
|
+
labels = None
|
|
61
|
+
|
|
62
|
+
return labels,labels_names
|
|
63
|
+
|
|
64
|
+
def get_ann_info(self,idx):
|
|
65
|
+
img_file,json_file = self.files[idx]
|
|
66
|
+
with open(json_file,"r",encoding="gb18030") as f:
|
|
67
|
+
data_str = f.read()
|
|
68
|
+
image = {}
|
|
69
|
+
try:
|
|
70
|
+
json_data = json.loads(data_str)
|
|
71
|
+
img_width = int(json_data["imageWidth"])
|
|
72
|
+
img_height = int(json_data["imageHeight"])
|
|
73
|
+
image["height"] = int(img_height)
|
|
74
|
+
image["width"] = int(img_width)
|
|
75
|
+
image["file_name"] = wmlu.base_name(json_file)
|
|
76
|
+
except:
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
return image
|
|
80
|
+
|
|
81
|
+
def get_items(self):
|
|
82
|
+
'''
|
|
83
|
+
:return:
|
|
84
|
+
full_path,img_size,category_ids,category_names,boxes,binary_masks,area,is_crowd,num_annotations_skipped
|
|
85
|
+
'''
|
|
86
|
+
for i in range(len(self.files)):
|
|
87
|
+
sys.stdout.write('\r>> read data %d/%d' % (i + 1, len(self.files)))
|
|
88
|
+
sys.stdout.flush()
|
|
89
|
+
yield self.__getitem__(i)
|
|
90
|
+
|
|
91
|
+
def get_boxes_items(self):
|
|
92
|
+
'''
|
|
93
|
+
:return:
|
|
94
|
+
full_path,img_size,category_ids,boxes,is_crowd
|
|
95
|
+
'''
|
|
96
|
+
for i,(img_file, json_file) in enumerate(self.files):
|
|
97
|
+
sys.stdout.write('\r>> read data %d/%d' % (i + 1, len(self.files)))
|
|
98
|
+
sys.stdout.flush()
|
|
99
|
+
image, annotations_list = read_labelme_data(json_file, None,mask_on=False,**self.read_data_kwargs)
|
|
100
|
+
labels_names,bboxes = get_labels_and_bboxes(image,annotations_list,is_relative_coordinate=not self.absolute_coord)
|
|
101
|
+
labels = [self.label_text2id(x) for x in labels_names]
|
|
102
|
+
yield DetBboxesData(img_file,[image['height'],image['width']],labels, bboxes, None)
|