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,579 @@
1
+ import numpy as np
2
+ import copy
3
+ import cv2
4
+ from wml.semantic.mask_utils import get_bboxes_by_contours,npresize_mask
5
+ import wml.object_detection2.bboxes as odb
6
+ import wml.basic_img_utils as bwmli
7
+ import wml.object_detection2.bboxes as odb
8
+ from .common import WBaseMaskLike
9
+
10
+
11
+ class WMCKeypointsItem(WBaseMaskLike):
12
+ '''
13
+ 每个WMCKeypointsItem共享同一个标签(label)
14
+ '''
15
+ def __init__(self,points,*,width=None,height=None):
16
+ '''
17
+ points: [points_nr,2]
18
+ '''
19
+ self.points = points.copy()
20
+ self.width = width
21
+ self.height = height
22
+
23
+ def copy(self):
24
+ return WMCKeypointsItem(self.points,width=self.width,height=self.height)
25
+
26
+ def bitmap(self,width=None,height=None):
27
+ '''
28
+ return: [H,W]
29
+ '''
30
+ raise RuntimeError(f"Not implement bitmap")
31
+
32
+ def resize(self,size,width=None,height=None):
33
+ '''
34
+ size:[w,h]
35
+ '''
36
+ if len(self.points)==0:
37
+ return self
38
+ if width is None:
39
+ width = self.width
40
+ if height is None:
41
+ height = self.height
42
+
43
+ w_scale = size[0]/width
44
+ h_scale = size[1]/height
45
+ scale = np.array([[w_scale,h_scale]],dtype=np.float32)
46
+ ori_type = self.points.dtype
47
+ points = self.points.astype(np.float32)*scale
48
+ points = points.astype(ori_type)
49
+ width = size[0]
50
+ height = size[1]
51
+
52
+ return WMCKeypointsItem(points=points,width=width,height=height)
53
+
54
+ def flip(self,direction,width=None,height=None):
55
+ if len(self.points)==0:
56
+ return self
57
+ if width is None:
58
+ width = self.width
59
+ if height is None:
60
+ height = self.height
61
+
62
+ if direction == WBaseMaskLike.HORIZONTAL:
63
+ self.points[:,0] = width-self.points[:,0]
64
+ elif direction == WBaseMaskLike.VERTICAL:
65
+ self.points[:,1] = height-self.points[:,1]
66
+ elif direction == WBaseMaskLike.DIAGONAL:
67
+ self.points[:,0] = width-self.points[:,0]
68
+ self.points[:,1] = height-self.points[:,1]
69
+ else:
70
+ info = f"unknow flip direction {direction}"
71
+ print(f"ERROR: {info}")
72
+ raise RuntimeError(info)
73
+
74
+ return self
75
+
76
+ def crop(self, bbox):
77
+ '''
78
+ bbox: [x0,y0,x1,y1], 包含边界
79
+ offset: [xoffset,yoffset]
80
+ 如果offset is not None, 先offset再用bbox crop
81
+ '''
82
+ if not isinstance(bbox,np.ndarray):
83
+ bbox = np.array(bbox)
84
+ assert bbox.ndim == 1
85
+
86
+ # clip the boundary
87
+ bbox = bbox.copy()
88
+ bbox[0::2] = np.clip(bbox[0::2], 0, self.width-1)
89
+ bbox[1::2] = np.clip(bbox[1::2], 0, self.height-1)
90
+ x1, y1, x2, y2 = bbox
91
+ w = np.maximum(x2 - x1+1, 1)
92
+ h = np.maximum(y2 - y1+1, 1)
93
+
94
+ if len(self.points)>0:
95
+ keep = odb.is_points_in_bbox(self.points,bbox)
96
+ points = self.points[keep]
97
+ offset = np.reshape(np.array([x1,y1]),[1,2])
98
+ points = points-offset
99
+ else:
100
+ points = np.zeros([0,2],dtype=np.int32)
101
+
102
+
103
+ cropped_kps = WMCKeypointsItem(points, width=w,height=h)
104
+ return cropped_kps
105
+
106
+ def filter_out_of_range(self):
107
+ bbox = [0,0,self.width-1,self.height-1]
108
+ n_kps = self.crop(bbox)
109
+ self.points = n_kps.points
110
+ return self
111
+
112
+
113
+ def rotate(self, out_shape, angle, center=None, scale=1.0, fill_val=0):
114
+ #out_shape: [h,w]
115
+ """See :func:`BaseInstancepoints.rotate`."""
116
+ if len(self.points) == 0:
117
+ rotated_points = WMCKeypointsItem([], width=out_shape[1],height=out_shape[0])
118
+ else:
119
+ rotate_matrix = cv2.getRotationMatrix2D(center, -angle, scale)
120
+ coords = self.points.copy()
121
+ # pad 1 to convert from format [x, y] to homogeneous
122
+ # coordinates format [x, y, 1]
123
+ coords = np.concatenate(
124
+ (coords, np.ones((coords.shape[0], 1), coords.dtype)),
125
+ axis=1) # [n, 3]
126
+ rotated_coords = np.matmul(
127
+ rotate_matrix[None, :, :],
128
+ coords[:, :, None])[..., 0] # [n, 2, 1] -> [n, 2]
129
+ rotated_points = WMCKeypointsItem(rotated_coords, width=out_shape[1],height=out_shape[0])
130
+ rotated_points = rotated_points.crop(np.array([0,0,out_shape[1]-1,out_shape[0]-1]))
131
+ return rotated_points
132
+
133
+ def warp_affine(self,M,out_shape,fill_val=0):
134
+ #out_shape: [h,w]
135
+ """See :func:`BaseInstancepoints.rotate`."""
136
+ if len(self.points) == 0:
137
+ affined_points = WMCKeypointsItem([], width=out_shape[1],height=out_shape[0])
138
+ else:
139
+ coords = self.points.copy()
140
+ # pad 1 to convert from format [x, y] to homogeneous
141
+ # coordinates format [x, y, 1]
142
+ coords = np.concatenate(
143
+ (coords, np.ones((coords.shape[0], 1), coords.dtype)),
144
+ axis=1) # [n, 3]
145
+ affined_coords = np.matmul(
146
+ M[None, :, :],
147
+ coords[:, :, None])[..., 0] # [n, 2, 1] -> [n, 2]
148
+ affined_points = WMCKeypointsItem(affined_coords, width=out_shape[1],height=out_shape[0])
149
+ affined_points = affined_points.crop(np.array([0,0,out_shape[1]-1,out_shape[0]-1]))
150
+ return affined_points
151
+
152
+ def shear(self,
153
+ out_shape,
154
+ magnitude,
155
+ direction='horizontal',
156
+ border_value=0,
157
+ interpolation='bilinear'):
158
+ #out_shape: [h,w]
159
+ if len(self.points) == 0:
160
+ sheared_points = WMCKeypointsItem([], width=out_shape[1],height=out_shape[0])
161
+ else:
162
+ if direction == 'horizontal':
163
+ shear_matrix = np.stack([[1, magnitude],
164
+ [0, 1]]).astype(np.float32)
165
+ elif direction == 'vertical':
166
+ shear_matrix = np.stack([[1, 0], [magnitude,
167
+ 1]]).astype(np.float32)
168
+ p = self.points.copy()
169
+ new_coords = np.matmul(shear_matrix, p.T) # [2, n]
170
+ new_coords[0, :] = np.clip(new_coords[0, :], 0,
171
+ out_shape[1])
172
+ new_coords[1, :] = np.clip(new_coords[1, :], 0,
173
+ out_shape[0])
174
+ sheared_points = new_coords.transpose((1, 0))
175
+ sheared_points = WMCKeypointsItem(sheared_points, width=out_shape[1],height=out_shape[0])
176
+ sheared_points.filter_out_of_range()
177
+ return sheared_points
178
+
179
+ def translate(self,
180
+ out_shape,
181
+ offset,
182
+ direction='horizontal',
183
+ fill_val=None,
184
+ interpolation=None):
185
+ """Translate the Polygonpoints.
186
+
187
+ Example:
188
+ >>> self = Polygonpoints.random(dtype=np.int)
189
+ >>> out_shape = (self.height, self.width)
190
+ >>> new = self.translate(out_shape, 4., direction='horizontal')
191
+ >>> assert np.all(new.points[0][0][1::2] == self.points[0][0][1::2])
192
+ >>> assert np.all(new.points[0][0][0::2] == self.points[0][0][0::2] + 4) # noqa: E501
193
+ """
194
+ if len(self.points) == 0:
195
+ res_points = WMCKeypointsItem([], width=out_shape[1],height=out_shape[0])
196
+ else:
197
+ p = self.points.copy()
198
+ if direction == WBaseMaskLike.HORIZONTAL:
199
+ p[:,0] = np.clip(p[:,0] + offset, 0, out_shape[1])
200
+ elif direction == WBaseMaskLike.VERTICAL:
201
+ p[:,1] = np.clip(p[:,1] + offset, 0, out_shape[0])
202
+ else:
203
+ info = f"error direction {direction}"
204
+ print(f"ERROR: {type(self).__name__} {info}")
205
+ raise RuntimeError(info)
206
+ res_points = WMCKeypointsItem(p, width=out_shape[1],height=out_shape[0])
207
+ res_points.filter_out_of_range()
208
+
209
+ return res_points
210
+
211
+ def offset(self,
212
+ offset):
213
+ '''
214
+ offset: [xoffset,yoffset]
215
+ '''
216
+ w = self.width+offset[0] if self.width is not None else None
217
+ h = self.height+offset[1] if self.height is not None else None
218
+ offset = np.reshape(np.array(offset),[1,2])
219
+ if len(self.points) == 0:
220
+ res_masks = WMCKeypointsItem([], width=w,height=h)
221
+ else:
222
+ p = self.points.copy()+offset
223
+ res_masks = WMCKeypointsItem(p, width=w,height=h)
224
+ res_masks.filter_out_of_range()
225
+ return res_masks
226
+
227
+ def valid(self):
228
+ if len(self.points) == 0:
229
+ return False
230
+ bbox = np.array([0,0,self.width,self.height])
231
+ try:
232
+ keep = odb.is_points_in_bbox(self.points,bbox)
233
+ except Exception as e:
234
+ print(e)
235
+ pass
236
+ self.points = self.points[keep]
237
+ return len(self.points)>0
238
+
239
+ def split2single_point(self):
240
+ '''
241
+ 把多个点组成的Item拆分成由单个点组成的Item
242
+ '''
243
+ if len(self.points) <= 1:
244
+ return [copy.deepcopy(self)]
245
+ else:
246
+ return [WMCKeypointsItem(np.expand_dims(p,axis=0),width=self.width,height=self.height) for p in self.points]
247
+
248
+ @property
249
+ def shape(self):
250
+ return [len(self.points),self.height,self.width]
251
+
252
+ def numel(self):
253
+ return len(self.points)
254
+
255
+ def _update_shape(self,*,width=None,height=None):
256
+ if width is not None:
257
+ self.width = width
258
+ if height is not None:
259
+ self.height = height
260
+
261
+
262
+
263
+
264
+ class WMCKeypoints(WBaseMaskLike):
265
+ '''
266
+ 每个WMCKeypoints包含多个WMCKeypointsItem, 每个Item与一个label相对应
267
+ WMCKeypoints与多个标签相对应
268
+ '''
269
+ def __init__(self,points,*,width=None,height=None) -> None:
270
+ assert width is not None, f"ERROR: width is None"
271
+ assert height is not None, f"ERROR: height is None"
272
+ super().__init__()
273
+ n_points = []
274
+ for p in points:
275
+ if not isinstance(p,WMCKeypointsItem):
276
+ n_points.append(WMCKeypointsItem(p,width=width,height=height))
277
+ else:
278
+ n_points.append(WMCKeypointsItem(p.points,width=width,height=height))
279
+ self.points = copy.deepcopy(n_points)
280
+ self.width = width
281
+ self.height = height
282
+ if self.width<5 or self.height<5:
283
+ print(f"WARNING: {self.__class__.__name__}: unnormal mask size, width={self.width}, height={self.height}")
284
+
285
+ @classmethod
286
+ def zeros(cls,*,width=None,height=None,shape=None):
287
+ '''
288
+ shape: [points_nr,H,W]
289
+ '''
290
+ if shape is not None:
291
+ width = shape[-1]
292
+ height = shape[-2]
293
+ return cls([],width=width,height=height)
294
+
295
+ @classmethod
296
+ def from_ndarray(cls,points,*,width=None,height=None):
297
+ raise RuntimeError(f"Unimplement from ndarray")
298
+
299
+ def copy(self):
300
+ return WMCKeypoints(self.points,width=self.width,height=self.height)
301
+
302
+ def __getitem__(self,idxs):
303
+ if isinstance(idxs,(list,tuple)) and (len(idxs)==2 or len(idxs)==3) and isinstance(idxs[0],slice):
304
+ sx = idxs[-1]
305
+ sy = idxs[-2]
306
+ if self.is_none_slice(sy) and self.is_flip_slice(sx):
307
+ return self.flip(WBaseMaskLike.HORIZONTAL)
308
+ elif self.is_none_slice(sx) and self.is_flip_slice(sy):
309
+ return self.flip(WBaseMaskLike.VERTICAL)
310
+ elif self.is_flip_slice(sx) and self.is_flip_slice(sy):
311
+ return self.flip(WBaseMaskLike.DIAGONAL)
312
+ bbox = self.slice2bbox(sx=sx,sy=sy)
313
+ return self.crop(bbox)
314
+ elif isinstance(idxs,(list,np.ndarray,tuple)):
315
+ idxs = np.array(idxs)
316
+ if idxs.dtype == np.bool:
317
+ idxs = np.where(idxs)[0]
318
+ try:
319
+ points = [self.points[idx] for idx in idxs]
320
+ except Exception as e:
321
+ print(e)
322
+ pass
323
+ return WMCKeypoints(points,width=self.width,height=self.height)
324
+ else:
325
+ return self.points[idxs]
326
+
327
+ def __setitem__(self,idxs,value):
328
+ if isinstance(idxs,(list,tuple)) and (len(idxs)==2 or len(idxs)==3) and isinstance(idxs[0],slice):
329
+ sx = idxs[-1]
330
+ sy = idxs[-2]
331
+ bbox = self.slice2bbox(sx=sx,sy=sy)
332
+ self.copy_from(value,bbox)
333
+ elif isinstance(idxs,(list,np.ndarray,tuple)):
334
+ idxs = np.array(idxs)
335
+ if idxs.dtype == np.bool:
336
+ idxs = np.where(idxs)[0]
337
+ if len(value) != len(idxs):
338
+ info = f"idxs size not equal value's size {len(idxs)} vs {len(value)}"
339
+ print(f"ERROR: {type(self).__name__}: {info}")
340
+ raise RuntimeError(info)
341
+ for i in idxs:
342
+ self.points[i] = value[i]
343
+ else:
344
+ info = f"unknow idxs type {type(idxs)}"
345
+ print(f"ERROR: {type(self).__name__}: {info}")
346
+ raise RuntimeError(info)
347
+
348
+ def __len__(self):
349
+ return len(self.points)
350
+
351
+ def __repr__(self):
352
+ s = self.__class__.__name__ + '('
353
+ s += f'num_keypoints={len(self.points)}, '
354
+ s += f'height={self.height}, '
355
+ s += f'width={self.width})'
356
+ return s
357
+
358
+ def bitmap(self,exclusion=None):
359
+ raise RuntimeError(f"Not implement bitmap")
360
+
361
+ def resize(self,size):
362
+ '''
363
+ size:[w,h]
364
+ '''
365
+ points = [m.resize(size,width=self.width,height=self.height) for m in self.points]
366
+ width = size[0]
367
+ height = size[1]
368
+ return WMCKeypoints(points=points,width=width,height=height)
369
+
370
+ def flip(self,direction=WBaseMaskLike.HORIZONTAL):
371
+ [m.flip(direction,width=self.width,height=self.height) for m in self.points]
372
+ return self
373
+
374
+ def crop(self,bbox):
375
+ '''
376
+ bbox: [x0,y0,x1,y1]
377
+ '''
378
+ bbox = np.array(bbox)
379
+ bbox = bbox.copy()
380
+ bbox[0::2] = np.clip(bbox[0::2], 0, self.width)
381
+ bbox[1::2] = np.clip(bbox[1::2], 0, self.height)
382
+ x1, y1, x2, y2 = bbox
383
+ w = np.maximum(x2 - x1+1, 1)
384
+ h = np.maximum(y2 - y1+1, 1)
385
+ points = [m.crop(bbox) for m in self.points]
386
+ return WMCKeypoints(points,width=w,height=h)
387
+
388
+ def slice2bbox(self,*,sx:slice,sy:slice):
389
+ x0 = sx.start if sx.start is not None else 0
390
+ x1 = sx.stop-1 if sx.stop is not None else self.width-1
391
+ y0 = sy.start if sy.start is not None else 0
392
+ y1 = sy.stop-1 if sy.stop is not None else self.height-1
393
+ return np.array([x0,y0,x1,y1],dtype=np.int)
394
+
395
+ @staticmethod
396
+ def is_flip_slice(s:slice):
397
+ return s.start is None and s.stop is None and s.step==-1
398
+
399
+ @staticmethod
400
+ def is_none_slice(s:slice):
401
+ return s.start is None and s.stop is None and s.step is None
402
+
403
+ @staticmethod
404
+ def get_bbox_size(bbox):
405
+ x1, y1, x2, y2 = bbox
406
+ w = np.maximum(x2 - x1, 1)
407
+ h = np.maximum(y2 - y1, 1)
408
+ return w,h
409
+
410
+ def copy_from(self,points,dst_bbox=None,src_bbox=None,update_size=False):
411
+ if src_bbox is not None:
412
+ points = points.crop(src_bbox)
413
+ if dst_bbox is not None:
414
+ w0,h0 = self.get_bbox_size(src_bbox)
415
+ w1,h1 = self.get_bbox_size(dst_bbox)
416
+ if w0!=w1 or h0!=h1:
417
+ info = f"dst_bbox and src_bbox expected to be equal."
418
+ print(f"ERROR: {info}")
419
+ raise RuntimeError(info)
420
+
421
+ if dst_bbox is not None:
422
+ if update_size:
423
+ w,h = self.get_bbox_size(dst_bbox)
424
+ self.width = w
425
+ self.height = h
426
+ self.points = [m.offset(dst_bbox[:2]) for m in points]
427
+ else:
428
+ self.points = points
429
+ if update_size:
430
+ self.width = points.width
431
+ self.height = points.height
432
+ [p._update_shape(width=self.width,height=self.height) for p in self.points]
433
+ return self
434
+
435
+
436
+ @classmethod
437
+ def from_bitmap_masks(cls,bitmap_masks):
438
+ raise RuntimeError(f"Not implement from bitmap masks")
439
+
440
+ @staticmethod
441
+ def concatenate(points):
442
+ ws = [m.width for m in points]
443
+ hs = [m.height for m in points]
444
+ ws = list(filter(lambda x:x is not None,ws))
445
+ hs = list(filter(lambda x:x is not None,hs))
446
+ if len(ws)>0:
447
+ nw = np.max(ws)
448
+ else:
449
+ nw = None
450
+
451
+ if len(hs)>0:
452
+ nh = np.max(hs)
453
+ else:
454
+ nh = None
455
+ new_points = []
456
+ for m in points:
457
+ new_points.extend(m.points)
458
+ return WMCKeypoints(new_points,width=nw,height=nh)
459
+
460
+ def rotate(self, out_shape, angle, center=None, scale=1.0, fill_val=0):
461
+ #out_shape: [h,w]
462
+ points = [m.rotate(out_shape, angle, center, scale, fill_val) for m in self.points]
463
+ width = out_shape[1]
464
+ height = out_shape[0]
465
+ return WMCKeypoints(points,width=width,height=height)
466
+
467
+ def warp_affine(self,M,out_shape,fill_val=0):
468
+ points = [m.warp_affine(M,out_shape,fill_val) for m in self.points]
469
+ width = out_shape[1]
470
+ height = out_shape[0]
471
+ return WMCKeypoints(points,width=width,height=height)
472
+
473
+
474
+ def shear(self,
475
+ out_shape,
476
+ magnitude,
477
+ direction='horizontal',
478
+ border_value=0,
479
+ interpolation='bilinear'):
480
+ #out_shape: [h,w]
481
+ points = [m.shear(out_shape, magnitude, direction, border_value, interpolation) for m in self.points]
482
+ width = out_shape[1]
483
+ height = out_shape[0]
484
+ return WMCKeypoints(points,width=width,height=height)
485
+
486
+ def translate(self,
487
+ out_shape,
488
+ offset,
489
+ direction=WBaseMaskLike.HORIZONTAL,
490
+ fill_val=None,
491
+ interpolation=None):
492
+ '''
493
+ out_shape: [H,W]
494
+ '''
495
+ points = [m.translate(out_shape, offset, direction, fill_val,interpolation) for m in self.points]
496
+ width = out_shape[1]
497
+ height = out_shape[0]
498
+ return WMCKeypoints(points,width=width,height=height)
499
+
500
+ def pad(self, out_shape, pad_val=0):
501
+ '''
502
+ out_shape: [H,W]
503
+ '''
504
+ """padding has no effect on polygons`"""
505
+ return WMCKeypoints(self.points, height=out_shape[0],width=out_shape[1])
506
+
507
+ @property
508
+ def shape(self):
509
+ return (len(self.points),self.height,self.width)
510
+
511
+ def resize_mask_in_bboxes(self,bboxes,size=None,r=None):
512
+ '''
513
+ mask: [N,H,W]
514
+ bboxes: [N,4](x0,y0,x1,y1)
515
+ size: (new_w,new_h)
516
+ '''
517
+ return self.resize(size),None
518
+
519
+ def to_ndarray(self):
520
+ """See :func:`BaseInstancepoints.to_ndarray`."""
521
+ return self.bitmap()
522
+
523
+ def get_bboxes(self):
524
+ gt_bboxes = [m.get_bbox() for m in self.points]
525
+ if len(gt_bboxes) == 0:
526
+ return np.zeros([0,4],dtype=np.float32)
527
+ gt_bboxes = np.stack(gt_bboxes,axis=0)
528
+
529
+ return gt_bboxes
530
+
531
+ def valid(self):
532
+ mask = [m.valid() for m in self.points]
533
+ return mask
534
+
535
+ @staticmethod
536
+ def split2single_point(kps,labels):
537
+ '''
538
+ 让每个WMCKeypointsItem仅包含一个点
539
+ '''
540
+ res_kps = []
541
+ res_labels = []
542
+ for kp,l in zip(kps,labels):
543
+ n_kp = kp.split2single_point()
544
+ l = [l]*len(n_kp)
545
+ res_kps.extend(n_kp)
546
+ res_labels.extend(l)
547
+
548
+ if len(res_labels)>0 and isinstance(res_labels[0],(int,float)):
549
+ res_labels = np.array(res_labels,dtype=np.int32)
550
+
551
+ return WMCKeypoints(res_kps,width=kps.width,height=kps.height),res_labels
552
+
553
+ @staticmethod
554
+ def split2single_nppoint(kps,labels):
555
+ points,labels = WMCKeypoints.split2single_point(kps,labels)
556
+ res_points = []
557
+ for p in points:
558
+ res_points.append(p.points)
559
+ if len(res_points)>0:
560
+ res = np.concatenate(res_points,axis=0)
561
+ else:
562
+ res = np.zeros([0,2],dtype=np.float32)
563
+ labels = np.zeros([0],dtype=np.int32)
564
+ return res,labels
565
+
566
+ def check_consistency(self):
567
+ for kp in self.points:
568
+ if kp.width != self.width or kp.height != self.height:
569
+ info = f"Unmatch size WMCKeypoints shape {self.shape} vs WMCKeypointsItem shape {kp.shape}"
570
+ print(info)
571
+ raise RuntimeError(info)
572
+
573
+ def update_shape(self,*,width=None,height=None):
574
+ if width is not None:
575
+ self.width = width
576
+ if height is not None:
577
+ self.height = height
578
+ for mask in self.points:
579
+ mask._update_shape(width=width,height=height)