python-wml 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of python-wml might be problematic. Click here for more details.

Files changed (164) hide show
  1. python_wml-3.0.0.dist-info/LICENSE +23 -0
  2. python_wml-3.0.0.dist-info/METADATA +51 -0
  3. python_wml-3.0.0.dist-info/RECORD +164 -0
  4. python_wml-3.0.0.dist-info/WHEEL +5 -0
  5. python_wml-3.0.0.dist-info/top_level.txt +1 -0
  6. wml/__init__.py +0 -0
  7. wml/basic_data_def/__init__.py +2 -0
  8. wml/basic_data_def/detection_data_def.py +279 -0
  9. wml/basic_data_def/io_data_def.py +2 -0
  10. wml/basic_img_utils.py +816 -0
  11. wml/img_patch.py +92 -0
  12. wml/img_utils.py +571 -0
  13. wml/iotoolkit/__init__.py +17 -0
  14. wml/iotoolkit/aic_keypoint.py +115 -0
  15. wml/iotoolkit/baidu_mask_toolkit.py +244 -0
  16. wml/iotoolkit/base_dataset.py +210 -0
  17. wml/iotoolkit/bboxes_statistics.py +515 -0
  18. wml/iotoolkit/build.py +0 -0
  19. wml/iotoolkit/cityscapes_toolkit.py +183 -0
  20. wml/iotoolkit/classification_data_statistics.py +25 -0
  21. wml/iotoolkit/coco_data_fwd.py +225 -0
  22. wml/iotoolkit/coco_keypoints.py +118 -0
  23. wml/iotoolkit/coco_keypoints_fmt2.py +103 -0
  24. wml/iotoolkit/coco_toolkit.py +397 -0
  25. wml/iotoolkit/coco_wholebody.py +269 -0
  26. wml/iotoolkit/common.py +108 -0
  27. wml/iotoolkit/crowd_pose.py +146 -0
  28. wml/iotoolkit/fast_labelme.py +110 -0
  29. wml/iotoolkit/image_folder.py +95 -0
  30. wml/iotoolkit/imgs_cache.py +58 -0
  31. wml/iotoolkit/imgs_reader_mt.py +73 -0
  32. wml/iotoolkit/labelme_base.py +102 -0
  33. wml/iotoolkit/labelme_json_to_img.py +49 -0
  34. wml/iotoolkit/labelme_toolkit.py +117 -0
  35. wml/iotoolkit/labelme_toolkit_fwd.py +733 -0
  36. wml/iotoolkit/labelmemckeypoints_dataset.py +169 -0
  37. wml/iotoolkit/lspet.py +48 -0
  38. wml/iotoolkit/mapillary_vistas_toolkit.py +269 -0
  39. wml/iotoolkit/mat_data.py +90 -0
  40. wml/iotoolkit/mckeypoints_statistics.py +28 -0
  41. wml/iotoolkit/mot_datasets.py +62 -0
  42. wml/iotoolkit/mpii.py +108 -0
  43. wml/iotoolkit/npmckeypoints_dataset.py +164 -0
  44. wml/iotoolkit/o365_to_coco.py +136 -0
  45. wml/iotoolkit/object365_toolkit.py +156 -0
  46. wml/iotoolkit/object365v2_toolkit.py +71 -0
  47. wml/iotoolkit/pascal_voc_data.py +51 -0
  48. wml/iotoolkit/pascal_voc_toolkit.py +194 -0
  49. wml/iotoolkit/pascal_voc_toolkit_fwd.py +473 -0
  50. wml/iotoolkit/penn_action.py +57 -0
  51. wml/iotoolkit/rawframe_dataset.py +129 -0
  52. wml/iotoolkit/rewrite_pascal_voc.py +28 -0
  53. wml/iotoolkit/semantic_data.py +49 -0
  54. wml/iotoolkit/split_file_by_type.py +29 -0
  55. wml/iotoolkit/sports_mot_datasets.py +78 -0
  56. wml/iotoolkit/vis_objectdetection_dataset.py +70 -0
  57. wml/iotoolkit/vis_torch_data.py +39 -0
  58. wml/iotoolkit/yolo_toolkit.py +38 -0
  59. wml/object_detection2/__init__.py +4 -0
  60. wml/object_detection2/basic_visualization.py +37 -0
  61. wml/object_detection2/bboxes.py +812 -0
  62. wml/object_detection2/data_process_toolkit.py +146 -0
  63. wml/object_detection2/keypoints.py +292 -0
  64. wml/object_detection2/mask.py +120 -0
  65. wml/object_detection2/metrics/__init__.py +3 -0
  66. wml/object_detection2/metrics/build.py +15 -0
  67. wml/object_detection2/metrics/classifier_toolkit.py +440 -0
  68. wml/object_detection2/metrics/common.py +71 -0
  69. wml/object_detection2/metrics/mckps_toolkit.py +338 -0
  70. wml/object_detection2/metrics/toolkit.py +1953 -0
  71. wml/object_detection2/npod_toolkit.py +361 -0
  72. wml/object_detection2/odtools.py +243 -0
  73. wml/object_detection2/standard_names.py +75 -0
  74. wml/object_detection2/visualization.py +956 -0
  75. wml/object_detection2/wmath.py +34 -0
  76. wml/semantic/__init__.py +0 -0
  77. wml/semantic/basic_toolkit.py +65 -0
  78. wml/semantic/mask_utils.py +156 -0
  79. wml/semantic/semantic_test.py +21 -0
  80. wml/semantic/structures.py +1 -0
  81. wml/semantic/toolkit.py +105 -0
  82. wml/semantic/visualization_utils.py +658 -0
  83. wml/threadtoolkit.py +50 -0
  84. wml/walgorithm.py +228 -0
  85. wml/wcollections.py +212 -0
  86. wml/wfilesystem.py +487 -0
  87. wml/wml_utils.py +657 -0
  88. wml/wstructures/__init__.py +4 -0
  89. wml/wstructures/common.py +9 -0
  90. wml/wstructures/keypoints_train_toolkit.py +149 -0
  91. wml/wstructures/kps_structures.py +579 -0
  92. wml/wstructures/mask_structures.py +1161 -0
  93. wml/wtorch/__init__.py +8 -0
  94. wml/wtorch/bboxes.py +104 -0
  95. wml/wtorch/classes_suppression.py +24 -0
  96. wml/wtorch/conv_module.py +181 -0
  97. wml/wtorch/conv_ws.py +144 -0
  98. wml/wtorch/data/__init__.py +16 -0
  99. wml/wtorch/data/_utils/__init__.py +45 -0
  100. wml/wtorch/data/_utils/collate.py +183 -0
  101. wml/wtorch/data/_utils/fetch.py +47 -0
  102. wml/wtorch/data/_utils/pin_memory.py +121 -0
  103. wml/wtorch/data/_utils/signal_handling.py +72 -0
  104. wml/wtorch/data/_utils/worker.py +227 -0
  105. wml/wtorch/data/base_data_loader_iter.py +93 -0
  106. wml/wtorch/data/dataloader.py +501 -0
  107. wml/wtorch/data/datapipes/__init__.py +1 -0
  108. wml/wtorch/data/datapipes/iter/__init__.py +12 -0
  109. wml/wtorch/data/datapipes/iter/batch.py +126 -0
  110. wml/wtorch/data/datapipes/iter/callable.py +92 -0
  111. wml/wtorch/data/datapipes/iter/listdirfiles.py +37 -0
  112. wml/wtorch/data/datapipes/iter/loadfilesfromdisk.py +30 -0
  113. wml/wtorch/data/datapipes/iter/readfilesfromtar.py +60 -0
  114. wml/wtorch/data/datapipes/iter/readfilesfromzip.py +63 -0
  115. wml/wtorch/data/datapipes/iter/sampler.py +94 -0
  116. wml/wtorch/data/datapipes/utils/__init__.py +0 -0
  117. wml/wtorch/data/datapipes/utils/common.py +65 -0
  118. wml/wtorch/data/dataset.py +354 -0
  119. wml/wtorch/data/datasets/__init__.py +4 -0
  120. wml/wtorch/data/datasets/common.py +53 -0
  121. wml/wtorch/data/datasets/listdirfilesdataset.py +36 -0
  122. wml/wtorch/data/datasets/loadfilesfromdiskdataset.py +30 -0
  123. wml/wtorch/data/distributed.py +135 -0
  124. wml/wtorch/data/multi_processing_data_loader_iter.py +866 -0
  125. wml/wtorch/data/sampler.py +267 -0
  126. wml/wtorch/data/single_process_data_loader_iter.py +24 -0
  127. wml/wtorch/data/test_data_loader.py +26 -0
  128. wml/wtorch/dataset_toolkit.py +67 -0
  129. wml/wtorch/depthwise_separable_conv_module.py +98 -0
  130. wml/wtorch/dist.py +591 -0
  131. wml/wtorch/dropblock/__init__.py +6 -0
  132. wml/wtorch/dropblock/dropblock.py +228 -0
  133. wml/wtorch/dropblock/dropout.py +40 -0
  134. wml/wtorch/dropblock/scheduler.py +48 -0
  135. wml/wtorch/ema.py +61 -0
  136. wml/wtorch/fc_module.py +73 -0
  137. wml/wtorch/functional.py +34 -0
  138. wml/wtorch/iter_dataset.py +26 -0
  139. wml/wtorch/loss.py +69 -0
  140. wml/wtorch/nets/__init__.py +0 -0
  141. wml/wtorch/nets/ckpt_toolkit.py +219 -0
  142. wml/wtorch/nets/fpn.py +276 -0
  143. wml/wtorch/nets/hrnet/__init__.py +0 -0
  144. wml/wtorch/nets/hrnet/config.py +2 -0
  145. wml/wtorch/nets/hrnet/hrnet.py +494 -0
  146. wml/wtorch/nets/misc.py +249 -0
  147. wml/wtorch/nets/resnet/__init__.py +0 -0
  148. wml/wtorch/nets/resnet/layers/__init__.py +17 -0
  149. wml/wtorch/nets/resnet/layers/aspp.py +144 -0
  150. wml/wtorch/nets/resnet/layers/batch_norm.py +231 -0
  151. wml/wtorch/nets/resnet/layers/blocks.py +111 -0
  152. wml/wtorch/nets/resnet/layers/wrappers.py +110 -0
  153. wml/wtorch/nets/resnet/r50_config.py +38 -0
  154. wml/wtorch/nets/resnet/resnet.py +691 -0
  155. wml/wtorch/nets/shape_spec.py +20 -0
  156. wml/wtorch/nets/simple_fpn.py +101 -0
  157. wml/wtorch/nms.py +109 -0
  158. wml/wtorch/nn.py +896 -0
  159. wml/wtorch/ocr_block.py +193 -0
  160. wml/wtorch/summary.py +331 -0
  161. wml/wtorch/train_toolkit.py +603 -0
  162. wml/wtorch/transformer_blocks.py +266 -0
  163. wml/wtorch/utils.py +719 -0
  164. wml/wtorch/wlr_scheduler.py +100 -0
@@ -0,0 +1,812 @@
1
+ #coding=utf-8
2
+ import numpy as np
3
+ import os
4
+ import sys
5
+ import random
6
+ from collections import Iterable
7
+ import math
8
+ from .wmath import npsafe_divide
9
+ import cv2 as cv
10
+ import torch
11
+
12
+ '''
13
+ bbox_ref:[1,4]/[N,4], [[ymin,xmin,ymax,xmax]]
14
+ bboxes:[N,4],[[ymin,xmin,ymax,xmax],...]
15
+ return:
16
+ [N]
17
+ '''
18
+ def npbboxes_jaccard(bbox_ref, bboxes, name=None):
19
+
20
+ bboxes = np.transpose(bboxes)
21
+ bbox_ref = np.transpose(bbox_ref)
22
+ int_ymin = np.maximum(bboxes[0], bbox_ref[0])
23
+ int_xmin = np.maximum(bboxes[1], bbox_ref[1])
24
+ int_ymax = np.minimum(bboxes[2], bbox_ref[2])
25
+ int_xmax = np.minimum(bboxes[3], bbox_ref[3])
26
+ h = np.maximum(int_ymax - int_ymin, 0.)
27
+ w = np.maximum(int_xmax - int_xmin, 0.)
28
+ inter_vol = h * w
29
+ union_vol = -inter_vol \
30
+ + (bboxes[2] - bboxes[0]) * (bboxes[3] - bboxes[1]) \
31
+ + (bbox_ref[2] - bbox_ref[0]) * (bbox_ref[3] - bbox_ref[1])
32
+ jaccard = npsafe_divide(inter_vol, union_vol, 'jaccard')
33
+ return jaccard
34
+
35
+ '''
36
+ box0:[N,4], or [1,4],[ymin,xmin,ymax,xmax],...
37
+ box1:[N,4], or [1,4]
38
+ return:
39
+ [N],返回box0,box1交叉面积占box0的百分比
40
+ '''
41
+ def npbboxes_intersection_of_box0(box0,box1):
42
+
43
+ bbox_ref= np.transpose(box0)
44
+ bboxes = np.transpose(box1)
45
+ int_ymin = np.maximum(bboxes[0], bbox_ref[0])
46
+ int_xmin = np.maximum(bboxes[1], bbox_ref[1])
47
+ int_ymax = np.minimum(bboxes[2], bbox_ref[2])
48
+ int_xmax = np.minimum(bboxes[3], bbox_ref[3])
49
+ h = np.maximum(int_ymax - int_ymin, 0.)
50
+ w = np.maximum(int_xmax - int_xmin, 0.)
51
+ inter_vol = h * w
52
+ union_vol = (bbox_ref[2] - bbox_ref[0]) * (bbox_ref[3] - bbox_ref[1])
53
+ union_vol = np.maximum(union_vol,1e-6)
54
+ jaccard = inter_vol/union_vol
55
+ return jaccard
56
+
57
+ '''
58
+ 将以ymin,xmin,ymax,xmax表示的box转换为以cy,cx,size,ratio表示的box
59
+ '''
60
+ def to_cxysa(data):
61
+ data = np.reshape(data,[-1,4])
62
+ new_shape = data.shape
63
+ res_data = np.zeros_like(data)
64
+ for i in range(new_shape[0]):
65
+ cy = (data[i][0]+data[i][2])*0.5
66
+ cx= (data[i][1] + data[i][3]) * 0.5
67
+ width = (data[i][3]-data[i][1])
68
+ height = (data[i][2]-data[i][0])
69
+ size = math.sqrt(width*height)
70
+ if width>0.0:
71
+ ratio = height/width
72
+ else:
73
+ ratio = 0
74
+ res_data[i][0] = cy
75
+ res_data[i][1] = cx
76
+ res_data[i][2] = size
77
+ res_data[i][3] = ratio
78
+
79
+ return res_data
80
+
81
+ '''
82
+ data:[X,4] (ymin,xmin,ymax,xmax)
83
+ return:
84
+ [X,4] (cy,cx,h,w)
85
+ '''
86
+ def npto_cyxhw(data):
87
+ data = np.transpose(data)
88
+ ymin,xmin,ymax,xmax = data[0],data[1],data[2],data[3]
89
+ cy = (ymin+ymax)/2
90
+ cx = (xmin+xmax)/2
91
+ h = ymax-ymin
92
+ w = xmax-xmin
93
+ data = np.stack([cy,cx,h,w],axis=1)
94
+ return data
95
+
96
+ '''
97
+ data:[X,4] (cy,cx,h,w)
98
+ return:
99
+ [X,4] (ymin,xmin,ymax,xmax)
100
+ '''
101
+ def npto_yminxminymaxxmax(data):
102
+ data = np.transpose(data)
103
+ cy,cx,h,w= data[0],data[1],data[2],data[3]
104
+ ymin = cy-h/2
105
+ xmin = cx-w/2
106
+ ymax = cy+h/2
107
+ xmax = cx+w/2
108
+ data = np.stack([ymin,xmin,ymax,xmax],axis=1)
109
+ return data
110
+
111
+ '''
112
+ data:[X,4] (ymin,xmin,ymax,xmax)
113
+ return:
114
+ [X,4] (minx,miny,w,h)
115
+ '''
116
+ def npto_ctlwh(data):
117
+ ymin,xmin,ymax,xmax = data[...,0],data[...,1],data[...,2],data[...,3]
118
+ h = (ymax-ymin)
119
+ w = (xmax-xmin)
120
+ data = np.stack([xmin,ymin,w,h],axis=-1)
121
+ return data
122
+
123
+ def npminxywh_toyxminmax(data):
124
+ if not isinstance(data,np.ndarray):
125
+ data = np.array(data)
126
+ x = data[...,0]
127
+ y = data[...,1]
128
+ w = data[...,2]
129
+ h = data[...,3]
130
+ xmax = x+w
131
+ ymax = y+h
132
+ return np.stack([y,x,ymax,xmax],axis=-1)
133
+
134
+ '''
135
+ input:[4]/[N,4] [ymin,xmin,ymax,xmax]
136
+ output:[xmin,ymin,width,height]
137
+ '''
138
+ def to_xyminwh(bbox,is_absolute_coordinate=True):
139
+ if not isinstance(bbox,np.ndarray):
140
+ bbox = np.array(bbox)
141
+ if len(bbox.shape)>= 2:
142
+ ymin = bbox[...,0]
143
+ xmin = bbox[...,1]
144
+ ymax = bbox[...,2]
145
+ xmax = bbox[...,3]
146
+ w = xmax-xmin
147
+ h = ymax-ymin
148
+ return np.stack([xmin,ymin,w,h],axis=-1)
149
+
150
+ else:
151
+ if is_absolute_coordinate:
152
+ return (bbox[1],bbox[0],bbox[3]-bbox[1]+1,bbox[2]-bbox[0]+1)
153
+ else:
154
+ return (bbox[1],bbox[0],bbox[3]-bbox[1],bbox[2]-bbox[0])
155
+
156
+ '''
157
+ boxes:[...,4] ymin,xmin,ymax,xmax
158
+ scale:[hscale,wscale]
159
+ max_size: [H,W]
160
+ 缩放后中心点位置不变
161
+ '''
162
+ def npscale_bboxes(bboxes,scale,correct=False,max_size=None):
163
+ if not isinstance(scale,Iterable):
164
+ scale = [scale,scale]
165
+ ymin,xmin,ymax,xmax = bboxes[...,0],bboxes[...,1],bboxes[...,2],bboxes[...,3]
166
+ cy = (ymin+ymax)/2.
167
+ cx = (xmin+xmax)/2.
168
+ h = ymax-ymin
169
+ w = xmax-xmin
170
+ h = scale[0]*h
171
+ w = scale[1]*w
172
+ ymin = cy - h / 2.
173
+ ymax = cy + h / 2.
174
+ xmin = cx - w / 2.
175
+ xmax = cx + w / 2.
176
+ xmin = np.maximum(xmin,0)
177
+ ymin = np.maximum(ymin,0)
178
+ if max_size is not None:
179
+ xmax = np.minimum(xmax,max_size[1]-1)
180
+ ymax = np.minimum(ymax,max_size[0]-1)
181
+ data = np.stack([ymin, xmin, ymax, xmax], axis=-1)
182
+ return data
183
+
184
+ '''
185
+ boxes:[...,4] ymin,xmin,ymax,xmax
186
+ scale:[hscale,wscale]
187
+ '''
188
+ def npclip_bboxes(bboxes,max_size):
189
+ ymin,xmin,ymax,xmax = bboxes[...,0],bboxes[...,1],bboxes[...,2],bboxes[...,3]
190
+ xmin = np.maximum(xmin,0)
191
+ ymin = np.maximum(ymin,0)
192
+ if max_size is not None:
193
+ xmax = np.minimum(xmax,max_size[1]-1)
194
+ ymax = np.minimum(ymax,max_size[0]-1)
195
+ data = np.stack([ymin, xmin, ymax, xmax], axis=-1)
196
+ return data
197
+
198
+ def npchangexyorder(bboxes):
199
+ if len(bboxes)==0:
200
+ return bboxes
201
+ bboxes = np.array(bboxes)
202
+ ymin,xmin,ymax,xmax = bboxes[...,0],bboxes[...,1],bboxes[...,2],bboxes[...,3]
203
+ data = np.stack([xmin, ymin, xmax, ymax], axis=-1)
204
+ return data
205
+
206
+ '''
207
+ data:[N,4]
208
+ 校正ymin,xmin,ymax,xmax表示的box中的不合法数据
209
+ '''
210
+ def correct_yxminmax_boxes(data,keep_size=False):
211
+ if not keep_size:
212
+ data = np.minimum(data,1.)
213
+ data = np.maximum(data,0.)
214
+ else:
215
+ nr = data.shape[0]
216
+ for i in range(nr):
217
+ if data[i][0]<0.:
218
+ data[i][2] -= data[i][0]
219
+ data[i][0] = 0.
220
+ if data[i][1]<0.:
221
+ data[i][3] -= data[i][1]
222
+ data[i][1] = 0.
223
+
224
+ if data[i][2] > 1.:
225
+ data[i][0] -= (data[i][2]-1.)
226
+ data[i][2] = 1.
227
+ if data[i][3] > 1.:
228
+ data[i][1] -= (data[i][3]-1.)
229
+ data[i][3] = 1.
230
+
231
+ return data
232
+
233
+
234
+ '''
235
+ 获取bboxes在box中的相对坐标
236
+ 如:box=[5,5,10,10,]
237
+ bboxes=[[7,7,8,9]]
238
+ return:
239
+ [[2,2,3,4]]
240
+ '''
241
+ def get_boxes_relative_to_box(box,bboxes,remove_zero_size_box=False):
242
+ if not isinstance(bboxes,np.ndarray):
243
+ bboxes = np.array(bboxes)
244
+ if bboxes.shape[0] == 0:
245
+ return bboxes
246
+ ymin,xmin,ymax,xmax = np.transpose(bboxes,[1,0])
247
+ ymin = ymin-box[0]
248
+ xmin = xmin-box[1]
249
+ ymax = ymax-box[0]
250
+ xmax = xmax-box[1]
251
+ if remove_zero_size_box:
252
+ mask = np.logical_and((ymax-ymin)>0,(xmax-xmin)>0)
253
+ ymin = ymin[mask]
254
+ xmin = xmin[mask]
255
+ ymax = ymax[mask]
256
+ xmax = xmax[mask]
257
+ bboxes = np.stack([ymin,xmin,ymax,xmax],axis=1)
258
+ return bboxes
259
+
260
+
261
+ '''
262
+ cnt:[[x,y],[x,y],...]
263
+ return the bbox of a contour
264
+ '''
265
+ def bbox_of_contour(cnt):
266
+ all_points = np.array(cnt)
267
+ points = np.transpose(all_points)
268
+ x,y = np.vsplit(points,2)
269
+ xmin = np.min(x)
270
+ xmax = np.max(x)
271
+ ymin = np.min(y)
272
+ ymax = np.max(y)
273
+ return (ymin,xmin,ymax,xmax)
274
+
275
+ '''
276
+ bbox:(xmin,ymin,width,height)
277
+ '''
278
+ def random_int_in_bbox(bbox):
279
+ x = random.randint(int(bbox[0]),int(bbox[0]+bbox[2]-1))
280
+ y = random.randint(int(bbox[1]),int(bbox[1]+bbox[3]-1))
281
+ return x,y
282
+
283
+ '''
284
+ bbox:(xmin,ymin,width,height)
285
+ size:(width,height) the size of return bbox
286
+ random return a box with center point in the input bbox
287
+ output:
288
+ [xmin,ymin,width,height]
289
+ '''
290
+ def random_bbox_in_bbox(bbox,size):
291
+ x,y = random_int_in_bbox(bbox)
292
+ xmin,ymin = max(0,x-size[0]//2),max(0,y-size[1]//2)
293
+ return [xmin,ymin,size[0],size[1]]
294
+
295
+ '''
296
+ weights [2,x],[0] values,[1]:labels
297
+ bboxes:[N,4],[xmin,ymin,width,height]
298
+ '''
299
+ def random_bbox_in_bboxes(bboxes,size,weights=None,labels=None):
300
+ if len(bboxes) == 0:
301
+ return (0,0,size[0],size[1])
302
+ if weights is not None:
303
+ old_v = 0.0
304
+ values = []
305
+
306
+ for v in weights[0]:
307
+ old_v += v
308
+ values.append(old_v)
309
+ random_v = random.uniform(0.,old_v)
310
+ index = 0
311
+ for i,v in enumerate(values):
312
+ if random_v<v:
313
+ index = i
314
+ break
315
+ label = weights[1][index]
316
+ _bboxes = []
317
+ for l,bbox in zip(labels,bboxes):
318
+ if l==label:
319
+ _bboxes.append(bbox)
320
+
321
+ if len(_bboxes) == 0:
322
+ return random_bbox_in_bboxes(bboxes,size)
323
+ else:
324
+ return random_bbox_in_bboxes(_bboxes,size)
325
+ else:
326
+ index = random.randint(0,len(bboxes)-1)
327
+ return random_bbox_in_bbox(bboxes[index],size)
328
+
329
+ '''
330
+ bbox:[(xmin,ymin,width,height),....] (format="xyminwh") or [(ymin,xmin,ymax,xmax),...] (format="yxminmax")
331
+ return a list of new bbox with the size scale times of the input
332
+ '''
333
+ def expand_bbox(bboxes,scale=2,format="xyminwh"):
334
+ if format == "xyminwh":
335
+ res_bboxes = []
336
+ for bbox in bboxes:
337
+ cx,cy = bbox[0]+bbox[2]//2,bbox[1]+bbox[3]//2
338
+ new_width = bbox[2]*scale
339
+ new_height = bbox[3]*scale
340
+ min_x = cx-new_width//2
341
+ min_y = cy-new_height//2
342
+ res_bboxes.append((min_x,min_y,new_width,new_height))
343
+
344
+ return res_bboxes
345
+ elif format == "yxminmax":
346
+ if not isinstance(bboxes,np.ndarray):
347
+ bboxes = np.array(bboxes)
348
+ ymin = bboxes[...,0]
349
+ xmin = bboxes[...,1]
350
+ ymax = bboxes[...,2]
351
+ xmax = bboxes[...,3]
352
+ h = ymax-ymin
353
+ cy = (ymax+ymin)/2
354
+ w = xmax-xmin
355
+ cx = (xmax+xmin)/2
356
+ nh = h*scale/2
357
+ nw = w*scale/2
358
+ nymin = cy-nh
359
+ nymax = cy+nh
360
+ nxmin = cx-nw
361
+ nxmax = cx+nw
362
+
363
+ return np.stack([nymin,nxmin,nymax,nxmax],axis=-1)
364
+
365
+ '''
366
+ bbox:[(xmin,ymin,width,height),....] (format="xyminwh") or [(ymin,xmin,ymax,xmax),...] (format="yxminmax")
367
+ size:[H,W]
368
+ return a list of new bbox with the size 'size'
369
+ '''
370
+ def expand_bbox_by_size(bboxes,size,format="xyminwh"):
371
+ res_bboxes = []
372
+ if format == "xyminwh":
373
+ for bbox in bboxes:
374
+ cx,cy = bbox[0]+bbox[2]//2,bbox[1]+bbox[3]//2
375
+ new_width = size[1]
376
+ new_height = size[0]
377
+ min_x = max(cx-new_width//2,0)
378
+ min_y = max(cy-new_height//2,0)
379
+ res_bboxes.append((min_x,min_y,new_width,new_height))
380
+
381
+ return res_bboxes
382
+ elif format == "yxminmax":
383
+ if not isinstance(bboxes,np.ndarray):
384
+ bboxes = np.array(bboxes)
385
+ ymin = bboxes[...,0]
386
+ xmin = bboxes[...,1]
387
+ ymax = bboxes[...,2]
388
+ xmax = bboxes[...,3]
389
+ cy = (ymax + ymin) / 2
390
+ cx = (xmax + xmin) / 2
391
+ nh = size[0]//2
392
+ nw = size[1]//2
393
+ nymin = cy-nh
394
+ nymax = cy+nh
395
+ nxmin = cx-nw
396
+ nxmax = cx+nw
397
+
398
+ return np.stack([nymin,nxmin,nymax,nxmax],axis=-1)
399
+
400
+ '''
401
+ bbox:[N,4] (x0,y0,x1,y1)
402
+ size:[W,H]
403
+
404
+ or
405
+
406
+ bbox:[N,4] (y0,x0,y1,x1)
407
+ size:[H,W]
408
+
409
+ return a list of new bbox with the minimum size 'size' and same center point
410
+ '''
411
+ def clamp_bboxes(bboxes,min_size):
412
+ if not isinstance(min_size,Iterable):
413
+ min_size = (min_size,min_size)
414
+ if not isinstance(bboxes,np.ndarray):
415
+ bboxes = np.array(bboxes)
416
+ xmin = bboxes[...,0]
417
+ ymin = bboxes[...,1]
418
+ xmax = bboxes[...,2]
419
+ ymax = bboxes[...,3]
420
+ cy = (ymax + ymin) / 2
421
+ cx = (xmax + xmin) / 2
422
+ h = ymax-ymin
423
+ w = xmax-xmin
424
+ nh = np.maximum(h,min_size[1])/2
425
+ nw = np.maximum(w,min_size[0])/2
426
+ nymin = cy-nh
427
+ nymax = cy+nh
428
+ nxmin = cx-nw
429
+ nxmax = cx+nw
430
+
431
+ return np.stack([nxmin,nymin,nxmax,nymax],axis=-1)
432
+
433
+ '''
434
+ bbox:[N,4] (x0,y0,x1,y1)
435
+ size:[W,H]
436
+
437
+ or
438
+
439
+ bbox:[N,4] (y0,x0,y1,x1)
440
+ size:[H,W]
441
+
442
+ return a list of new bbox with the minimum size 'size' and same center point
443
+ '''
444
+ def set_bboxes_size(bboxes,size):
445
+ if not isinstance(size,Iterable):
446
+ size = (size,size)
447
+ if not isinstance(bboxes,np.ndarray):
448
+ bboxes = np.array(bboxes)
449
+ xmin = bboxes[...,0]
450
+ ymin = bboxes[...,1]
451
+ xmax = bboxes[...,2]
452
+ ymax = bboxes[...,3]
453
+ cy = (ymax + ymin) / 2
454
+ cx = (xmax + xmin) / 2
455
+ nh = np.full_like(ymin,size[1]//2)
456
+ nw = np.full_like(xmin,size[0]//2)
457
+ nymin = cy-nh
458
+ nymax = cy+nh
459
+ nxmin = cx-nw
460
+ nxmax = cx+nw
461
+
462
+ return np.stack([nxmin,nymin,nxmax,nymax],axis=-1)
463
+ '''
464
+ bbox:[N,4](x0,y0,x1,y1)
465
+ min_size:[W,H]
466
+ return a list of new bbox with the minimum size 'size'
467
+ '''
468
+ def torch_clamp_bboxes(bboxes,min_size,ignore_zero_size_bboxes=True):
469
+ if not isinstance(min_size,Iterable):
470
+ min_size = (min_size,min_size)
471
+ xmin = bboxes[...,0]
472
+ ymin = bboxes[...,1]
473
+ xmax = bboxes[...,2]
474
+ ymax = bboxes[...,3]
475
+ cy = (ymax + ymin) / 2
476
+ cx = (xmax + xmin) / 2
477
+ h = ymax-ymin
478
+ w = xmax-xmin
479
+ nh = torch.clamp(h,min=min_size[1])/2
480
+ nw = torch.clamp(w,min=min_size[0])/2
481
+ if ignore_zero_size_bboxes:
482
+ nh = torch.where(h>0,nh,h)
483
+ nw = torch.where(w>0,nw,w)
484
+ nymin = cy-nh
485
+ nymax = cy+nh
486
+ nxmin = cx-nw
487
+ nxmax = cx+nw
488
+
489
+ return torch.stack([nxmin,nymin,nxmax,nymax],dim=-1)
490
+ '''
491
+ bboxes:[N,4]
492
+ '''
493
+ def shrink_box(bboxes,shrink_value=[0,0,0,0]):
494
+ if not isinstance(bboxes,np.ndarray):
495
+ bboxes = np.array(bboxes)
496
+ if not isinstance(shrink_value,list):
497
+ shrink_value = [shrink_value]*4
498
+ ymin,xmin,ymax,xmax = np.transpose(bboxes)
499
+ ymin = ymin+shrink_value[0]
500
+ xmin = xmin+shrink_value[1]
501
+ ymax = ymax-shrink_value[2]
502
+ xmax = xmax-shrink_value[3]
503
+ return np.stack([ymin,xmin,ymax,xmax],axis=1)
504
+
505
+ '''
506
+ boxes:[N,4],[ymin,xmin,ymax,xmax]
507
+ return:[ymin,xmin,ymax,xmax]
508
+ '''
509
+ def bbox_of_boxes(boxes):
510
+ if not isinstance(boxes,np.ndarray):
511
+ boxes = np.array(boxes)
512
+ boxes = np.transpose(boxes)
513
+ ymin = np.min(boxes[0])
514
+ xmin = np.min(boxes[1])
515
+ ymax = np.max(boxes[2])
516
+ xmax = np.max(boxes[3])
517
+ return np.array([ymin,xmin,ymax,xmax])
518
+
519
+ '''
520
+ bbox:[ymin,xmin,ymax,xmax]
521
+ '''
522
+ def get_bboxes_wh(bboxes):
523
+ return bboxes[...,2:]-bboxes[...,:2]
524
+
525
+
526
+ '''
527
+ boxes:[N,4],[ymin,xmin,ymax,xmax]
528
+ '''
529
+ def absolutely_boxes_to_relative_boxes(boxes,width,height):
530
+ boxes = np.transpose(boxes)
531
+ ymin = boxes[0]/height
532
+ xmin = boxes[1]/width
533
+ ymax = boxes[2]/height
534
+ xmax = boxes[3]/width
535
+
536
+ return np.stack([ymin,xmin,ymax,xmax],axis=1)
537
+
538
+ '''
539
+ boxes:[N,4],[ymin,xmin,ymax,xmax]
540
+ '''
541
+ def relative_boxes_to_absolutely_boxes(boxes,width,height):
542
+ boxes = np.transpose(boxes)
543
+ ymin = boxes[0]*(height-1)
544
+ xmin = boxes[1]*(width-1)
545
+ ymax = boxes[2]*(height-1)
546
+ xmax = boxes[3]*(width-1)
547
+
548
+ return np.stack([ymin,xmin,ymax,xmax],axis=1)
549
+ '''
550
+ boxes:[N,4],[ymin,xmin,ymax,xmax]
551
+ '''
552
+ def relative_boxes_to_absolutely_boxesi(boxes,width,height):
553
+ return relative_boxes_to_absolutely_boxes(boxes=boxes,width=width,height=height).astype(np.int32)
554
+
555
+ '''
556
+ box0:[ymin,xmin,ymax,xmax]
557
+ box1:[N,4],[ymin,xmin,ymax,xmax]
558
+ 用box0裁box1,也就是说box1仅取与box0有重叠的部分
559
+ '''
560
+ def cut_boxes_by_box0(box0,box1):
561
+ if not isinstance(box1,np.ndarray):
562
+ box1 = np.array(box1)
563
+ ymin,xmin,ymax,xmax = np.transpose(box1)
564
+ ymin = np.minimum(np.maximum(box0[0],ymin),box0[2])
565
+ xmin = np.minimum(np.maximum(box0[1],xmin),box0[3])
566
+ ymax = np.maximum(np.minimum(box0[2],ymax),box0[0])
567
+ xmax = np.maximum(np.minimum(box0[3],xmax),box0[1])
568
+ box1 = np.stack([ymin,xmin,ymax,xmax],axis=0)
569
+ return np.transpose(box1)
570
+
571
+ def change_bboxes_nr(bboxes0,labels0,bboxes1,labels1,threshold=0.8):
572
+ if not isinstance(labels0,np.ndarray):
573
+ labels0 = np.array(labels0)
574
+ if not isinstance(labels1,np.ndarray):
575
+ labels1 = np.array(labels1)
576
+ nr = labels0.shape[0]
577
+ same_ids = 0
578
+ for i in range(nr):
579
+ box0 = np.array([bboxes0[i]])
580
+ ious = npbboxes_jaccard(box0,bboxes1)
581
+ index = np.argmax(ious)
582
+ if ious[index]>threshold and labels0[i] == labels1[index]:
583
+ same_ids += 1
584
+ return labels0.shape[0]+labels1.shape[0]-2*same_ids
585
+
586
+
587
+ def merge_bboxes(bboxes0,labels0,bboxes1,labels1,iou_threshold=0.5,class_agnostic=True):
588
+ labels1 = np.array(labels1)
589
+ labels0 = np.array(labels0)
590
+ mask = np.ones(labels1.shape,dtype=np.bool)
591
+
592
+ for i in range(labels1.shape[0]):
593
+ if class_agnostic:
594
+ ref_bboxes = bboxes0
595
+ else:
596
+ mask = labels0==labels1[i]
597
+ ref_bboxes = bboxes0[mask]
598
+ if len(ref_bboxes)==0:
599
+ continue
600
+
601
+ #ious = npbboxes_jaccard([bboxes1[i]],ref_bboxes)
602
+ ious0 = npbboxes_intersection_of_box0([bboxes1[i]],ref_bboxes)
603
+ ious1 = npbboxes_intersection_of_box0(ref_bboxes,[bboxes1[i]])
604
+ ious = np.concatenate([ious0,ious1],axis=0)
605
+
606
+ if np.any(ious>iou_threshold):
607
+ mask[i] = False
608
+
609
+ mask = mask.tolist()
610
+ bboxes1 = bboxes1[mask]
611
+ labels1 = labels1[mask]
612
+
613
+ bboxes = np.concatenate([bboxes0,bboxes1],axis=0)
614
+ labels = np.concatenate([labels0,labels1],axis=0)
615
+
616
+ return bboxes,labels
617
+
618
+ '''
619
+ bboxes0: [N,4]/[1,4] [ymin,xmin,ymax,xmax)
620
+ bboxes1: [N,4]/[1,4]ymin,xmin,ymax,xmax)
621
+ return:
622
+ [-1,1]
623
+ '''
624
+ def npgiou(bboxes0, bboxes1):
625
+ # 1. calulate intersection over union
626
+ bboxes0 = np.array(bboxes0)
627
+ bboxes1 = np.array(bboxes1)
628
+ area_1 = (bboxes0[..., 2] - bboxes0[..., 0]) * (bboxes0[..., 3] - bboxes0[..., 1])
629
+ area_2 = (bboxes1[..., 2] - bboxes1[..., 0]) * (bboxes1[..., 3] - bboxes1[..., 1])
630
+
631
+ intersection_wh = np.minimum(bboxes0[..., 2:], bboxes1[..., 2:]) - np.maximum(bboxes0[..., :2], bboxes1[..., :2])
632
+ intersection_wh = np.maximum(intersection_wh, 0)
633
+
634
+ intersection = intersection_wh[..., 0] * intersection_wh[..., 1]
635
+ union = (area_1 + area_2) - intersection
636
+
637
+ ious = intersection / np.maximum(union, 1e-10)
638
+
639
+ # 2. (C - (A U B))/C
640
+ C_wh = np.maximum(bboxes0[..., 2:], bboxes1[..., 2:]) - np.minimum(bboxes0[..., :2], bboxes1[..., :2])
641
+ C_wh = np.maximum(C_wh, 1e-10)
642
+ C = C_wh[..., 0] * C_wh[..., 1]
643
+
644
+ giou = ious - (C - union) /C
645
+ return giou
646
+
647
+ '''
648
+ bboxes: [N,4] (ymin,xmin,ymax,xmax)
649
+ '''
650
+ def npbbxoes_nms(bboxes,nms_thrsh=0.5):
651
+ bboxes_nr = len(bboxes)
652
+ bboxes = np.array(bboxes)
653
+ if bboxes_nr<=1:
654
+ return bboxes,[True]
655
+ mask = np.ones([bboxes_nr],dtype=np.bool)
656
+ for i in range(bboxes_nr-1):
657
+ ious = npbboxes_jaccard([bboxes[i]],bboxes[i+1:])
658
+ for j in range(len(ious)):
659
+ if ious[j]>nms_thrsh:
660
+ mask[i+1+j] = False
661
+ mask = mask.tolist()
662
+ bboxes = bboxes[mask]
663
+ return bboxes,mask
664
+
665
+ '''
666
+ bboxes0: [N,4],(x0,y0,x1,y1)
667
+ bboxes1: [M,4],(x0,y0,x1,y1)
668
+ return:
669
+ [N,M]
670
+ '''
671
+ def iou_matrix(bboxes0,bboxes1):
672
+ if bboxes0.size==0 or bboxes1.size==0:
673
+ return np.zeros([bboxes0.shape[0],bboxes1.shape[0]],dtype=np.float32)
674
+ bboxes0 = np.array(bboxes0)
675
+ bboxes1 = np.array(bboxes1)
676
+ bboxes0 = np.expand_dims(bboxes0,axis=1)
677
+ bboxes1 = np.expand_dims(bboxes1,axis=0)
678
+
679
+ x_int_min = np.maximum(bboxes0[...,0],bboxes1[...,0])
680
+ x_int_max = np.minimum(bboxes0[...,2],bboxes1[...,2])
681
+ y_int_min = np.maximum(bboxes0[...,1],bboxes1[...,1])
682
+ y_int_max = np.minimum(bboxes0[...,3],bboxes1[...,3])
683
+
684
+ int_w = np.maximum(x_int_max-x_int_min,0.0)
685
+ int_h = np.maximum(y_int_max-y_int_min,0.0)
686
+ inter_vol = int_w*int_h
687
+ areas0 = np.prod(bboxes0[...,2:]-bboxes0[...,:2],axis=-1)
688
+ areas1 = np.prod(bboxes1[...,2:]-bboxes1[...,:2],axis=-1)
689
+ union_vol = areas0+areas1-inter_vol
690
+
691
+ return npsafe_divide(inter_vol,union_vol)
692
+
693
+ def giou_matrix(atlbrs, btlbrs):
694
+ ious = np.zeros((len(atlbrs), len(btlbrs)), dtype=np.float32)
695
+ if ious.size == 0:
696
+ return ious
697
+
698
+ for i in range(len(atlbrs)):
699
+ bbox0 = atlbrs[i]
700
+ _gious = npgiou([bbox0], btlbrs)
701
+ ious[i] = _gious
702
+ return ious
703
+
704
+ def is_point_in_bbox(p,bbox):
705
+ '''
706
+
707
+ Args:
708
+ p: (x,y)
709
+ bbox: (x0,y0,x1,y1)
710
+
711
+ Returns:
712
+ '''
713
+ if p[0]>=bbox[0] and p[0]<=bbox[2] and p[1]>=bbox[1] and p[1]<=bbox[3]:
714
+ return True
715
+ return False
716
+
717
+ def is_points_in_bbox(p,bbox):
718
+ '''
719
+
720
+ Args:
721
+ p: [N,2] (x,y)
722
+ bbox: (x0,y0,x1,y1)
723
+
724
+ Returns:
725
+ '''
726
+ b0 = p[...,0]>=bbox[0]
727
+ b1 = p[...,0]<=bbox[2]
728
+ b2 = p[...,1]>=bbox[1]
729
+ b3 = p[...,1]<=bbox[3]
730
+ b01 = np.logical_and(b0,b1)
731
+ b23 = np.logical_and(b2,b3)
732
+ return np.logical_and(b01,b23)
733
+
734
+ def make_yolo_target(bboxes,labels):
735
+ '''
736
+ bboxes: list[[N,4]]
737
+ labels: list[[N]]
738
+ '''
739
+ max_nr = max(*[len(x) for x in labels])
740
+ batch_size = len(labels)
741
+ res = np.zeros([batch_size,max_nr, 5], dtype=np.float32)
742
+ if max_nr == 0:
743
+ return res
744
+ for i,bbox in enumerate(bboxes):
745
+ l = labels[i]
746
+ nr = len(l)
747
+ res[i,:nr,0] = l
748
+ res[i,:nr,1:] = bbox
749
+ return res
750
+
751
+ def trans_mmdet_result(results,labels_trans=None):
752
+ '''
753
+ results: list[np.[X,5]], x0,y0,x1,y1,score, list idx is classes id
754
+ '''
755
+ bboxes = []
756
+ scores = []
757
+ labels = []
758
+ for i in range(len(results)):
759
+ if len(results[i]) == 0:
760
+ continue
761
+ bboxes.append(results[i][:,:4])
762
+ scores.append(results[i][:,4])
763
+ l = i
764
+ if labels_trans is not None:
765
+ l = labels_trans(l)
766
+ l = [l]*results[i].shape[0]
767
+ labels.extend(l)
768
+
769
+ if len(bboxes) == 0:
770
+ return np.zeros([0,4],dtype=np.float32),np.zeros([0],dtype=np.int32),np.zeros([0],dtype=np.float32)
771
+ bboxes = np.concatenate(bboxes,axis=0)
772
+ scores = np.concatenate(scores,axis=0)
773
+ labels = np.array(labels)
774
+
775
+ return bboxes,labels,scores
776
+
777
+ def area(bboxes):
778
+ '''
779
+ bboxes: [...,4] (x0,y0,x1,y1) or (y0,x0,y1,x1)
780
+ '''
781
+
782
+ s0 = np.maximum(bboxes[...,2]-bboxes[...,0],0)
783
+ s1 = np.maximum(bboxes[...,3]-bboxes[...,1],0)
784
+ return s0*s1
785
+
786
+
787
+ def torch_area(bboxes):
788
+ '''
789
+ bboxes: [...,4] (x0,y0,x1,y1) or (y0,x0,y1,x1)
790
+ '''
791
+
792
+ s0 = torch.clamp(bboxes[...,2]-bboxes[...,0],min=0)
793
+ s1 = torch.clamp(bboxes[...,3]-bboxes[...,1],min=0)
794
+ return s0*s1
795
+
796
+ def correct_bboxes(bboxes,size):
797
+ '''
798
+ bboxes: [N,4] (x0,y0,x1,y1)
799
+ size: [W,H]
800
+
801
+ or
802
+ bboxes: [N,4] (y0,x0,y1,x1)
803
+ size: [H,W]
804
+
805
+ '''
806
+ old_type = bboxes.dtype
807
+ bboxes = np.maximum(bboxes,0)
808
+ bboxes = np.minimum(bboxes,np.array([[size[0],size[1],size[0],size[1]]]))
809
+ return bboxes.astype(old_type)
810
+
811
+ def equal_bboxes(bbox0,bbox1):
812
+ return np.all(bbox0==bbox1)