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/wml_utils.py
ADDED
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
#coding=utf-8
|
|
2
|
+
from wml.wcollections import *
|
|
3
|
+
from wml.wfilesystem import *
|
|
4
|
+
from wml.walgorithm import *
|
|
5
|
+
import numpy as np
|
|
6
|
+
import random
|
|
7
|
+
import time
|
|
8
|
+
from functools import wraps
|
|
9
|
+
import sys
|
|
10
|
+
import datetime
|
|
11
|
+
import hashlib
|
|
12
|
+
import math
|
|
13
|
+
import pickle
|
|
14
|
+
from collections import OrderedDict
|
|
15
|
+
from importlib import metadata
|
|
16
|
+
import re
|
|
17
|
+
import torch
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _to_chinese_num(i,numbers,unites):
|
|
21
|
+
j = i%10
|
|
22
|
+
i = i/10
|
|
23
|
+
res = numbers[j]
|
|
24
|
+
if unites[0] is not None and len(unites)>0:
|
|
25
|
+
res = res+unites[0]
|
|
26
|
+
if i>0:
|
|
27
|
+
return _to_chinese_num(i,numbers,unites[1:])+res
|
|
28
|
+
else:
|
|
29
|
+
return res
|
|
30
|
+
|
|
31
|
+
def to_chinese_num(i):
|
|
32
|
+
if i==0:
|
|
33
|
+
return "零"
|
|
34
|
+
unites=[None,"十","百","千","万","十万","千万","亿","十亿"]
|
|
35
|
+
numbers=["","一","二","三","四","五","六","七","八","九"]
|
|
36
|
+
res = _to_chinese_num(i,numbers,unites)
|
|
37
|
+
if res.startswith("一十"):
|
|
38
|
+
res = res.decode("utf-8")
|
|
39
|
+
res = res[1:]
|
|
40
|
+
res = res.encode("utf-8")
|
|
41
|
+
return res
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def show_member(obj,name=None):
|
|
45
|
+
if name is not None:
|
|
46
|
+
print("Show %s."%(name))
|
|
47
|
+
|
|
48
|
+
for name,var in vars(obj).items():
|
|
49
|
+
print("%s : "%(name),var)
|
|
50
|
+
|
|
51
|
+
def show_list(values,fmt=None,recurse=False):
|
|
52
|
+
if values is None:
|
|
53
|
+
return
|
|
54
|
+
if isinstance(values,str):
|
|
55
|
+
return show_list([values])
|
|
56
|
+
print("[")
|
|
57
|
+
if fmt is None:
|
|
58
|
+
for v in values:
|
|
59
|
+
if recurse and isinstance(v,(list,tuple,np.ndarray)):
|
|
60
|
+
show_list(v)
|
|
61
|
+
else:
|
|
62
|
+
print(v)
|
|
63
|
+
else:
|
|
64
|
+
for v in values:
|
|
65
|
+
if recurse and isinstance(v,(list,tuple,np.ndarray)):
|
|
66
|
+
show_list(v)
|
|
67
|
+
else:
|
|
68
|
+
print(fmt.format(v))
|
|
69
|
+
|
|
70
|
+
print("]")
|
|
71
|
+
|
|
72
|
+
def show_dict(values,format:str=None):
|
|
73
|
+
print("{")
|
|
74
|
+
for k,v in values.items():
|
|
75
|
+
if format is None:
|
|
76
|
+
print(k,":",v,",")
|
|
77
|
+
else:
|
|
78
|
+
print(k,":",format.format(v),",")
|
|
79
|
+
print("}")
|
|
80
|
+
|
|
81
|
+
def nparray2str(value,split=",",format="{}"):
|
|
82
|
+
if not isinstance(value,np.ndarray):
|
|
83
|
+
value = np.array(value)
|
|
84
|
+
ndims = len(value.shape)
|
|
85
|
+
if ndims == 1:
|
|
86
|
+
r_str = "["
|
|
87
|
+
for x in value[:-1]:
|
|
88
|
+
r_str+=format.format(x)+split
|
|
89
|
+
r_str+=format.format(value[-1])+"]"
|
|
90
|
+
return r_str
|
|
91
|
+
else:
|
|
92
|
+
r_str = "["
|
|
93
|
+
for x in value[:-1]:
|
|
94
|
+
r_str+=nparray2str(x,split=split,format=format)+split+"\n"
|
|
95
|
+
r_str+=nparray2str(value[-1],split=split,format=format)+"]\n"
|
|
96
|
+
return r_str
|
|
97
|
+
|
|
98
|
+
def show_nparray(value,name=None,split=",",format="{}"):
|
|
99
|
+
if name is not None:
|
|
100
|
+
print(name)
|
|
101
|
+
print(nparray2str(value,split=split,format=format))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def reduce_prod(x):
|
|
105
|
+
if len(x)==0:
|
|
106
|
+
return 0
|
|
107
|
+
elif len(x)==1:
|
|
108
|
+
return x[0]
|
|
109
|
+
res = x[0]
|
|
110
|
+
for v in x[1:]:
|
|
111
|
+
res *= v
|
|
112
|
+
|
|
113
|
+
return res
|
|
114
|
+
|
|
115
|
+
def any(iterable,v=None):
|
|
116
|
+
if v is None:
|
|
117
|
+
for value in iterable:
|
|
118
|
+
if value is None:
|
|
119
|
+
return True
|
|
120
|
+
return False
|
|
121
|
+
else:
|
|
122
|
+
t = type(v)
|
|
123
|
+
for value in iterable:
|
|
124
|
+
if isinstance(t,value) and v==value:
|
|
125
|
+
return True
|
|
126
|
+
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
def all(iterable,v=None):
|
|
130
|
+
if v is None:
|
|
131
|
+
for value in iterable:
|
|
132
|
+
if value is not None:
|
|
133
|
+
return False
|
|
134
|
+
return True
|
|
135
|
+
else:
|
|
136
|
+
t = type(v)
|
|
137
|
+
for value in iterable:
|
|
138
|
+
if (not isinstance(t,value)) or v!=value:
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
return True
|
|
142
|
+
|
|
143
|
+
def gather(data,indexs):
|
|
144
|
+
res_data = []
|
|
145
|
+
|
|
146
|
+
for d in indexs:
|
|
147
|
+
res_data.append(data[d])
|
|
148
|
+
|
|
149
|
+
return res_data
|
|
150
|
+
|
|
151
|
+
class TimeThis():
|
|
152
|
+
def __init__(self,name="TimeThis",auto_show=True):
|
|
153
|
+
self.begin_time = time.time()
|
|
154
|
+
self.end_time = 0
|
|
155
|
+
self.name = name
|
|
156
|
+
self.auto_show = auto_show
|
|
157
|
+
self.idx = 0
|
|
158
|
+
|
|
159
|
+
def __enter__(self):
|
|
160
|
+
self.begin_time = time.time()
|
|
161
|
+
|
|
162
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
163
|
+
self.end_time = time.time()
|
|
164
|
+
if self.auto_show:
|
|
165
|
+
te = (self.end_time-self.begin_time)*1000
|
|
166
|
+
fps = 1000/(te+1e-8)
|
|
167
|
+
print(f"{self.name}: total time {te:.3f}ms, FPS={fps:.3f}.")
|
|
168
|
+
|
|
169
|
+
def time(self,reset=False):
|
|
170
|
+
self.end_time = time.time()
|
|
171
|
+
r = self.end_time-self.begin_time
|
|
172
|
+
if reset:
|
|
173
|
+
self.reset()
|
|
174
|
+
return r
|
|
175
|
+
|
|
176
|
+
def reset(self):
|
|
177
|
+
self.begin_time = time.time()
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def log_and_restart(self,sub_name=""):
|
|
181
|
+
self.end_time = time.time()
|
|
182
|
+
te = (self.end_time - self.begin_time) * 1000
|
|
183
|
+
fps = 1000 / (te + 1e-8)
|
|
184
|
+
print(f"{self.name}:{self.idx}:{sub_name}: total time {te:.3f}, FPS={fps:.3f}.")
|
|
185
|
+
self.begin_time = self.end_time
|
|
186
|
+
self.idx += 1
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class AvgTimeThis():
|
|
190
|
+
def __init__(self,name="TimeThis",skip_nr=3):
|
|
191
|
+
self.step = 0
|
|
192
|
+
self.begin_time = 0.
|
|
193
|
+
self.name = name
|
|
194
|
+
self.datas = []
|
|
195
|
+
self.skip_nr = skip_nr
|
|
196
|
+
|
|
197
|
+
def __enter__(self):
|
|
198
|
+
self.begin_time = time.time()
|
|
199
|
+
|
|
200
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
201
|
+
self.step = self.step + 1
|
|
202
|
+
if(self.step>self.skip_nr):
|
|
203
|
+
self.datas.append(time.time()-self.begin_time)
|
|
204
|
+
|
|
205
|
+
def clear(self):
|
|
206
|
+
self.datas = []
|
|
207
|
+
|
|
208
|
+
def get_time(self):
|
|
209
|
+
if(len(self.datas) == 0):
|
|
210
|
+
return 0
|
|
211
|
+
return np.mean(np.array(self.datas))
|
|
212
|
+
|
|
213
|
+
def max(self):
|
|
214
|
+
return np.max(self.datas)
|
|
215
|
+
|
|
216
|
+
def min(self):
|
|
217
|
+
return np.min(self.datas)
|
|
218
|
+
|
|
219
|
+
def __str__(self):
|
|
220
|
+
return "AVG: "+str(self.get_time())+ f", test_nr = {self.step}"
|
|
221
|
+
|
|
222
|
+
class MTimer():
|
|
223
|
+
def __init__(self,name="TimeThis",auto_show=True):
|
|
224
|
+
self._begin_time = []
|
|
225
|
+
self.name = name
|
|
226
|
+
self.auto_show = auto_show
|
|
227
|
+
self.idx = 0
|
|
228
|
+
self.times = OrderedDict()
|
|
229
|
+
self.sub_name = None
|
|
230
|
+
self.last = 0
|
|
231
|
+
self.enter_size = 0
|
|
232
|
+
|
|
233
|
+
def __enter__(self,name):
|
|
234
|
+
self.enter_size = len(self._begin_time)
|
|
235
|
+
self.begin_time(name)
|
|
236
|
+
|
|
237
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
238
|
+
self.end_time()
|
|
239
|
+
while len(self._begin_time)>self.enter_size:
|
|
240
|
+
self.end_time()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def begin_time(self,name):
|
|
244
|
+
torch.cuda.synchronize()
|
|
245
|
+
if len(self._begin_time) > 0:
|
|
246
|
+
name = self._begin_time[-1][0]+"."+name
|
|
247
|
+
self.sub_name = name
|
|
248
|
+
self._begin_time.append((name,time.time()))
|
|
249
|
+
|
|
250
|
+
def end_time(self,*,new_time=None):
|
|
251
|
+
if len(self._begin_time)==0:
|
|
252
|
+
print(f"Haven't begin time.")
|
|
253
|
+
return
|
|
254
|
+
torch.cuda.synchronize()
|
|
255
|
+
end_time = time.time()
|
|
256
|
+
name,begin_time = self._begin_time[-1]
|
|
257
|
+
if self.name is not None and len(self.name)>0:
|
|
258
|
+
name = self.name+": "+name
|
|
259
|
+
self.last = end_time-begin_time
|
|
260
|
+
self.times[name] = self.last
|
|
261
|
+
if self.auto_show:
|
|
262
|
+
te = (end_time-begin_time)*1000
|
|
263
|
+
fps = 1000/(te+1e-8)
|
|
264
|
+
print(f"{name}: total time {te:.3f}ms, FPS={fps:.3f}.")
|
|
265
|
+
self._begin_time = self._begin_time[:-1]
|
|
266
|
+
|
|
267
|
+
if new_time is not None:
|
|
268
|
+
self.begin_time(new_time)
|
|
269
|
+
|
|
270
|
+
def end_all(self):
|
|
271
|
+
while len(self._begin_time)>0:
|
|
272
|
+
self.end_time()
|
|
273
|
+
|
|
274
|
+
def reset(self,new_time=None):
|
|
275
|
+
self.end_all()
|
|
276
|
+
if new_time is not None:
|
|
277
|
+
self.begin_time(new_time)
|
|
278
|
+
|
|
279
|
+
def __repr__(self):
|
|
280
|
+
res = "{\n"
|
|
281
|
+
for k,v in self.times.items():
|
|
282
|
+
res += f"{k}: {v}\n"
|
|
283
|
+
res += "}"
|
|
284
|
+
return res
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class MovingAvg(object):
|
|
288
|
+
def __init__(self,init_val = 0.0,momentum=0.99):
|
|
289
|
+
self.v = init_val
|
|
290
|
+
self.momentum = momentum
|
|
291
|
+
|
|
292
|
+
def __call__(self, v):
|
|
293
|
+
self.v = self.v*self.momentum+v*(1-self.momentum)
|
|
294
|
+
|
|
295
|
+
def value(self):
|
|
296
|
+
return self.v
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class EstimateTimeCost(object):
|
|
300
|
+
RECORD_STEP = 100
|
|
301
|
+
def __init__(self,total_nr,auto_log=False,avg_step=2000):
|
|
302
|
+
self.begin_time = None
|
|
303
|
+
self.total_nr = total_nr
|
|
304
|
+
self.process_nr = 0
|
|
305
|
+
self.begin_step = 0
|
|
306
|
+
self._time_datas = None
|
|
307
|
+
self.t0 = None
|
|
308
|
+
self.reset()
|
|
309
|
+
self.auto_log = auto_log
|
|
310
|
+
self.avg_step = avg_step
|
|
311
|
+
|
|
312
|
+
def reset(self,total_nr = None):
|
|
313
|
+
self.begin_time = time.time()
|
|
314
|
+
self.t0 = time.time()
|
|
315
|
+
if total_nr is not None:
|
|
316
|
+
self.total_nr = total_nr
|
|
317
|
+
self.process_nr = 0
|
|
318
|
+
self.begin_step = 0
|
|
319
|
+
self._time_datas = None
|
|
320
|
+
|
|
321
|
+
def add_count(self):
|
|
322
|
+
self.process_nr += 1
|
|
323
|
+
if self.process_nr%EstimateTimeCost.RECORD_STEP == EstimateTimeCost.RECORD_STEP-1 and self._time_datas is None:
|
|
324
|
+
self._time_datas = (self.process_nr,time.time())
|
|
325
|
+
return self.__repr__()
|
|
326
|
+
|
|
327
|
+
def set_process_nr(self,process_nr):
|
|
328
|
+
self.process_nr = process_nr
|
|
329
|
+
if self.process_nr%EstimateTimeCost.RECORD_STEP == EstimateTimeCost.RECORD_STEP-1 and self._time_datas is None:
|
|
330
|
+
self._time_datas = (self.process_nr,time.time())
|
|
331
|
+
return self.__repr__()
|
|
332
|
+
|
|
333
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
334
|
+
info = self.add_count()
|
|
335
|
+
if self.auto_log:
|
|
336
|
+
print(info)
|
|
337
|
+
|
|
338
|
+
def time_elapse(self):
|
|
339
|
+
return time.time() - self.t0
|
|
340
|
+
|
|
341
|
+
def time_remaind(self):
|
|
342
|
+
return ((time.time() - self.begin_time) / max(self.process_nr-self.begin_step, 1)) * (
|
|
343
|
+
self.total_nr- self.process_nr)
|
|
344
|
+
|
|
345
|
+
def total_time(self):
|
|
346
|
+
return ((time.time() - self.begin_time) / max(self.process_nr-self.begin_step, 1))*self.total_nr
|
|
347
|
+
|
|
348
|
+
def __repr__(self):
|
|
349
|
+
if self._time_datas is not None and self.process_nr-self._time_datas[0]>self.avg_step:
|
|
350
|
+
self.begin_step = self._time_datas[0]
|
|
351
|
+
self.begin_time = self._time_datas[1]
|
|
352
|
+
self._time_datas = None
|
|
353
|
+
|
|
354
|
+
left_time = ((time.time() - self.begin_time) / max(self.process_nr-self.begin_step, 1)) * (
|
|
355
|
+
self.total_nr- self.process_nr)
|
|
356
|
+
finish_time = datetime.datetime.now() + datetime.timedelta(seconds=left_time)
|
|
357
|
+
cur_str = datetime.datetime.now().strftime("%d %H:%M")
|
|
358
|
+
ft_str = finish_time.strftime("%d %H:%M")
|
|
359
|
+
#res = f"used {(time.time() - self.begin_time) / 3600:.3f}h, {left_time / 3600:.3f}h left, exp finish {str(d)}"
|
|
360
|
+
#res = f"{(time.time() - self.begin_time) / 3600:.3f}h/{left_time / 3600:.3f}h/{str(d)}"
|
|
361
|
+
res = f"{(time.time() - self.t0) / 3600:.3f}h/{left_time / 3600:.3f}h/{cur_str}/{ft_str}"
|
|
362
|
+
return res
|
|
363
|
+
|
|
364
|
+
def time_this(func):
|
|
365
|
+
@wraps(func)
|
|
366
|
+
def wraps_func(*args,**kwargs):
|
|
367
|
+
begin_t = time.time()
|
|
368
|
+
res = func(*args,**kwargs)
|
|
369
|
+
print(f"Time cost {time.time()-begin_t}s.")
|
|
370
|
+
return res
|
|
371
|
+
return wraps_func
|
|
372
|
+
|
|
373
|
+
def no_throw(func):
|
|
374
|
+
@wraps(func)
|
|
375
|
+
def wraps_func(*args,**kwargs):
|
|
376
|
+
try:
|
|
377
|
+
return func(*args,**kwargs)
|
|
378
|
+
except Exception as e:
|
|
379
|
+
print(f"ERROR: in no_throw wraps {e}")
|
|
380
|
+
return None
|
|
381
|
+
return wraps_func
|
|
382
|
+
'''
|
|
383
|
+
将list data分为多个组,每个组size个元素
|
|
384
|
+
'''
|
|
385
|
+
def list_to_2dlist(data,size):
|
|
386
|
+
data_nr = len(data)
|
|
387
|
+
if data_nr<size:
|
|
388
|
+
return [data]
|
|
389
|
+
res = []
|
|
390
|
+
index = 0
|
|
391
|
+
while index<data_nr:
|
|
392
|
+
end_index = min(index+size,data_nr)
|
|
393
|
+
res.append(data[index:end_index])
|
|
394
|
+
index = end_index
|
|
395
|
+
return res
|
|
396
|
+
|
|
397
|
+
'''
|
|
398
|
+
将list data分nr个组,每个组的元素数量基本相等
|
|
399
|
+
'''
|
|
400
|
+
def list_to_2dlistv2(data,nr):
|
|
401
|
+
size = (len(data)+nr-1)//nr
|
|
402
|
+
return list_to_2dlist(data,size)
|
|
403
|
+
|
|
404
|
+
def random_uniform(minmaxs):
|
|
405
|
+
res = []
|
|
406
|
+
for min,max in minmaxs:
|
|
407
|
+
res.append(random.uniform(min,max))
|
|
408
|
+
return res
|
|
409
|
+
|
|
410
|
+
def random_uniform_indict(minmaxs):
|
|
411
|
+
res = {}
|
|
412
|
+
for key,data in minmaxs.items():
|
|
413
|
+
if len(data) == 2:
|
|
414
|
+
if isinstance(data[0],bool):
|
|
415
|
+
index = random.randint(0,1)
|
|
416
|
+
res[key] = data[index]
|
|
417
|
+
else:
|
|
418
|
+
min,max = data[0],data[1]
|
|
419
|
+
res[key] = random.uniform(min,max)
|
|
420
|
+
else:
|
|
421
|
+
index = random.randint(0,len(data)-1)
|
|
422
|
+
res[key] = data[index]
|
|
423
|
+
|
|
424
|
+
return res
|
|
425
|
+
|
|
426
|
+
def is_child_of(obj, cls):
|
|
427
|
+
try:
|
|
428
|
+
for i in obj.__bases__:
|
|
429
|
+
if i is cls or isinstance(i, cls):
|
|
430
|
+
return True
|
|
431
|
+
for i in obj.__bases__:
|
|
432
|
+
if is_child_of(i, cls):
|
|
433
|
+
return True
|
|
434
|
+
except AttributeError:
|
|
435
|
+
return is_child_of(obj.__class__, cls)
|
|
436
|
+
return False
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def add_dict(lhv,rhv):
|
|
440
|
+
res = dict(lhv)
|
|
441
|
+
for k,v in rhv.items():
|
|
442
|
+
if k in res:
|
|
443
|
+
res[k] = res[k]+v
|
|
444
|
+
else:
|
|
445
|
+
res[k] = v
|
|
446
|
+
return res
|
|
447
|
+
|
|
448
|
+
def sleep_for(hours):
|
|
449
|
+
finish_time = datetime.datetime.now() + datetime.timedelta(seconds=int(hours*3600))
|
|
450
|
+
sleep_until(finish_time)
|
|
451
|
+
|
|
452
|
+
def sleep_until(runtime):
|
|
453
|
+
if isinstance(runtime,(str,bytes)):
|
|
454
|
+
target_datetime = datetime.datetime.strptime(runtime, "%Y-%m-%d %H:%M:%S")
|
|
455
|
+
else:
|
|
456
|
+
target_datetime = runtime
|
|
457
|
+
|
|
458
|
+
while True:
|
|
459
|
+
wait_time = (target_datetime - datetime.datetime.now()).total_seconds() / 3600.0
|
|
460
|
+
sys.stdout.write(
|
|
461
|
+
f"\rRumtime is {target_datetime}, current datetime is {datetime.datetime.now()}, need to wait for {wait_time:.2f}h", )
|
|
462
|
+
sys.stdout.flush()
|
|
463
|
+
|
|
464
|
+
if datetime.datetime.now() >= target_datetime:
|
|
465
|
+
break
|
|
466
|
+
else:
|
|
467
|
+
time.sleep(30)
|
|
468
|
+
|
|
469
|
+
def file_md5(path):
|
|
470
|
+
with open(path,'rb') as f:
|
|
471
|
+
data = f.read()
|
|
472
|
+
return hashlib.md5(data).hexdigest()
|
|
473
|
+
|
|
474
|
+
def nparray(data,default_shape=[0],dtype=np.float32):
|
|
475
|
+
res = np.array(data)
|
|
476
|
+
if res.size == 0:
|
|
477
|
+
return np.zeros(default_shape,dtype=dtype)
|
|
478
|
+
return res
|
|
479
|
+
|
|
480
|
+
def is_int(v,eps=1e-6):
|
|
481
|
+
return math.fabs(v-int(v))<eps
|
|
482
|
+
|
|
483
|
+
def to_fraction(v):
|
|
484
|
+
'''
|
|
485
|
+
将小数转化为分数
|
|
486
|
+
example:
|
|
487
|
+
v=0.4:
|
|
488
|
+
return:
|
|
489
|
+
2,5
|
|
490
|
+
'''
|
|
491
|
+
max_try = 20
|
|
492
|
+
if is_int(v):
|
|
493
|
+
return v
|
|
494
|
+
denominator = 1
|
|
495
|
+
for i in range(max_try):
|
|
496
|
+
v *= 10
|
|
497
|
+
denominator *= 10
|
|
498
|
+
if is_int(v):
|
|
499
|
+
break
|
|
500
|
+
if not is_int(v):
|
|
501
|
+
return v,denominator
|
|
502
|
+
|
|
503
|
+
v = int(v)
|
|
504
|
+
for _ in range(max_try):
|
|
505
|
+
is_find = False
|
|
506
|
+
for i in range(2,v+1):
|
|
507
|
+
if v%i == 0 and denominator%i==0:
|
|
508
|
+
v = v//i
|
|
509
|
+
denominator = denominator//i
|
|
510
|
+
is_find = True
|
|
511
|
+
break
|
|
512
|
+
if not is_find:
|
|
513
|
+
break
|
|
514
|
+
return v,denominator
|
|
515
|
+
|
|
516
|
+
def is_divide_exactly(lhv,rhv):
|
|
517
|
+
return (lhv//rhv)*rhv==lhv
|
|
518
|
+
|
|
519
|
+
def lowest_common_multiple(a,b):
|
|
520
|
+
'''
|
|
521
|
+
最小公倍数
|
|
522
|
+
'''
|
|
523
|
+
if a==b:
|
|
524
|
+
return a
|
|
525
|
+
|
|
526
|
+
max_v = max(a,b)
|
|
527
|
+
min_v = min(a,b)
|
|
528
|
+
|
|
529
|
+
if is_divide_exactly(max_v,min_v):
|
|
530
|
+
return max_v
|
|
531
|
+
|
|
532
|
+
res = max_v*min_v
|
|
533
|
+
|
|
534
|
+
while True:
|
|
535
|
+
for i in range(1,min_v):
|
|
536
|
+
if is_divide_exactly(res,i):
|
|
537
|
+
tmp_v = res//i
|
|
538
|
+
if is_divide_exactly(tmp_v,max_v) and is_divide_exactly(tmp_v,min_v):
|
|
539
|
+
res = tmp_v
|
|
540
|
+
break
|
|
541
|
+
if i>=min_v-1:
|
|
542
|
+
break
|
|
543
|
+
|
|
544
|
+
return res
|
|
545
|
+
|
|
546
|
+
def dump2file(obj,file):
|
|
547
|
+
if isinstance(file,(str,bytes)):
|
|
548
|
+
with open(file,"wb") as f:
|
|
549
|
+
return pickle.dump(obj,f)
|
|
550
|
+
else:
|
|
551
|
+
return pickle.dump(obj,file)
|
|
552
|
+
|
|
553
|
+
def load_from_file(file):
|
|
554
|
+
if isinstance(file,(str,bytes)):
|
|
555
|
+
with open(file,"rb") as f:
|
|
556
|
+
return pickle.load(f)
|
|
557
|
+
else:
|
|
558
|
+
return pickle.load(file)
|
|
559
|
+
|
|
560
|
+
def parse_version(version="0.0.0") -> tuple:
|
|
561
|
+
"""
|
|
562
|
+
Convert a version string to a tuple of integers, ignoring any extra non-numeric string attached to the version. This
|
|
563
|
+
function replaces deprecated 'pkg_resources.parse_version(v)'.
|
|
564
|
+
|
|
565
|
+
Args:
|
|
566
|
+
version (str): Version string, i.e. '2.0.1+cpu'
|
|
567
|
+
|
|
568
|
+
Returns:
|
|
569
|
+
(tuple): Tuple of integers representing the numeric part of the version and the extra string, i.e. (2, 0, 1)
|
|
570
|
+
"""
|
|
571
|
+
try:
|
|
572
|
+
return tuple(map(int, re.findall(r"\d+", version)[:3])) # '2.0.1+cpu' -> (2, 0, 1)
|
|
573
|
+
except Exception as e:
|
|
574
|
+
print(f"WARNING ⚠️ failure for parse_version({version}), returning (0, 0, 0): {e}")
|
|
575
|
+
return 0, 0, 0
|
|
576
|
+
|
|
577
|
+
def check_version(
|
|
578
|
+
current: str = "0.0.0",
|
|
579
|
+
required: str = "0.0.0",
|
|
580
|
+
name: str = "version",
|
|
581
|
+
hard: bool = False,
|
|
582
|
+
verbose: bool = False,
|
|
583
|
+
msg: str = "",
|
|
584
|
+
) -> bool:
|
|
585
|
+
"""
|
|
586
|
+
Check current version against the required version or range.
|
|
587
|
+
|
|
588
|
+
Args:
|
|
589
|
+
current (str): Current version or package name to get version from.
|
|
590
|
+
required (str): Required version or range (in pip-style format).
|
|
591
|
+
name (str, optional): Name to be used in warning message.
|
|
592
|
+
hard (bool, optional): If True, raise an AssertionError if the requirement is not met.
|
|
593
|
+
verbose (bool, optional): If True, print warning message if requirement is not met.
|
|
594
|
+
msg (str, optional): Extra message to display if verbose.
|
|
595
|
+
|
|
596
|
+
Returns:
|
|
597
|
+
(bool): True if requirement is met, False otherwise.
|
|
598
|
+
|
|
599
|
+
Example:
|
|
600
|
+
```python
|
|
601
|
+
# Check if current version is exactly 22.04
|
|
602
|
+
check_version(current="22.04", required="==22.04")
|
|
603
|
+
|
|
604
|
+
# Check if current version is greater than or equal to 22.04
|
|
605
|
+
check_version(current="22.10", required="22.04") # assumes '>=' inequality if none passed
|
|
606
|
+
|
|
607
|
+
# Check if current version is less than or equal to 22.04
|
|
608
|
+
check_version(current="22.04", required="<=22.04")
|
|
609
|
+
|
|
610
|
+
# Check if current version is between 20.04 (inclusive) and 22.04 (exclusive)
|
|
611
|
+
check_version(current="21.10", required=">20.04,<22.04")
|
|
612
|
+
```
|
|
613
|
+
"""
|
|
614
|
+
if not current: # if current is '' or None
|
|
615
|
+
print(f"WARNING ⚠️ invalid check_version({current}, {required}) requested, please check values.")
|
|
616
|
+
return True
|
|
617
|
+
elif not current[0].isdigit(): # current is package name rather than version string, i.e. current='ultralytics'
|
|
618
|
+
try:
|
|
619
|
+
name = current # assigned package name to 'name' arg
|
|
620
|
+
current = metadata.version(current) # get version string from package name
|
|
621
|
+
except metadata.PackageNotFoundError as e:
|
|
622
|
+
if hard:
|
|
623
|
+
raise ModuleNotFoundError(f"WARNING ⚠️ {current} package is required but not installed") from e
|
|
624
|
+
else:
|
|
625
|
+
return False
|
|
626
|
+
|
|
627
|
+
if not required: # if required is '' or None
|
|
628
|
+
return True
|
|
629
|
+
|
|
630
|
+
op = ""
|
|
631
|
+
version = ""
|
|
632
|
+
result = True
|
|
633
|
+
c = parse_version(current) # '1.2.3' -> (1, 2, 3)
|
|
634
|
+
for r in required.strip(",").split(","):
|
|
635
|
+
op, version = re.match(r"([^0-9]*)([\d.]+)", r).groups() # split '>=22.04' -> ('>=', '22.04')
|
|
636
|
+
if not op:
|
|
637
|
+
op = ">=" # assume >= if no op passed
|
|
638
|
+
v = parse_version(version) # '1.2.3' -> (1, 2, 3)
|
|
639
|
+
if op == "==" and c != v:
|
|
640
|
+
result = False
|
|
641
|
+
elif op == "!=" and c == v:
|
|
642
|
+
result = False
|
|
643
|
+
elif op == ">=" and not (c >= v):
|
|
644
|
+
result = False
|
|
645
|
+
elif op == "<=" and not (c <= v):
|
|
646
|
+
result = False
|
|
647
|
+
elif op == ">" and not (c > v):
|
|
648
|
+
result = False
|
|
649
|
+
elif op == "<" and not (c < v):
|
|
650
|
+
result = False
|
|
651
|
+
if not result:
|
|
652
|
+
warning = f"WARNING ⚠️ {name}{op}{version} is required, but {name}=={current} is currently installed {msg}"
|
|
653
|
+
if hard:
|
|
654
|
+
raise ModuleNotFoundError(warning) # assert version requirements met
|
|
655
|
+
if verbose:
|
|
656
|
+
print(warning)
|
|
657
|
+
return result
|