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