9
9
import numpy as np
10
10
from numpy import random
11
11
12
- from mmdet .core import PolygonMasks
12
+ from mmdet .core import PolygonMasks , find_inside_bboxes
13
13
from mmdet .core .evaluation .bbox_overlaps import bbox_overlaps
14
14
from ..builder import PIPELINES
15
15
@@ -54,8 +54,10 @@ class Resize:
54
54
ratio_range (tuple[float]): (min_ratio, max_ratio)
55
55
keep_ratio (bool): Whether to keep the aspect ratio when resizing the
56
56
image.
57
- bbox_clip_border (bool, optional): Whether clip the objects outside
58
- the border of the image. Defaults to True.
57
+ bbox_clip_border (bool, optional): Whether to clip the objects outside
58
+ the border of the image. In some dataset like MOT17, the gt bboxes
59
+ are allowed to cross the border of images. Therefore, we don't
60
+ need to clip the gt bboxes in these cases. Defaults to True.
59
61
backend (str): Image resize backend, choices are 'cv2' and 'pillow'.
60
62
These two backends generates slightly different results. Defaults
61
63
to 'cv2'.
@@ -1982,6 +1984,10 @@ class Mosaic:
1982
1984
output. Default to (0.5, 1.5).
1983
1985
min_bbox_size (int | float): The minimum pixel for filtering
1984
1986
invalid bboxes after the mosaic pipeline. Default to 0.
1987
+ bbox_clip_border (bool, optional): Whether to clip the objects outside
1988
+ the border of the image. In some dataset like MOT17, the gt bboxes
1989
+ are allowed to cross the border of images. Therefore, we don't
1990
+ need to clip the gt bboxes in these cases. Defaults to True.
1985
1991
skip_filter (bool): Whether to skip filtering rules. If it
1986
1992
is True, the filter rule will not be applied, and the
1987
1993
`min_bbox_size` is invalid. Default to True.
@@ -1992,12 +1998,14 @@ def __init__(self,
1992
1998
img_scale = (640 , 640 ),
1993
1999
center_ratio_range = (0.5 , 1.5 ),
1994
2000
min_bbox_size = 0 ,
2001
+ bbox_clip_border = True ,
1995
2002
skip_filter = True ,
1996
2003
pad_val = 114 ):
1997
2004
assert isinstance (img_scale , tuple )
1998
2005
self .img_scale = img_scale
1999
2006
self .center_ratio_range = center_ratio_range
2000
2007
self .min_bbox_size = min_bbox_size
2008
+ self .bbox_clip_border = bbox_clip_border
2001
2009
self .skip_filter = skip_filter
2002
2010
self .pad_val = pad_val
2003
2011
@@ -2099,16 +2107,24 @@ def _mosaic_transform(self, results):
2099
2107
2100
2108
if len (mosaic_labels ) > 0 :
2101
2109
mosaic_bboxes = np .concatenate (mosaic_bboxes , 0 )
2102
- mosaic_bboxes [:, 0 ::2 ] = np .clip (mosaic_bboxes [:, 0 ::2 ], 0 ,
2103
- 2 * self .img_scale [1 ])
2104
- mosaic_bboxes [:, 1 ::2 ] = np .clip (mosaic_bboxes [:, 1 ::2 ], 0 ,
2105
- 2 * self .img_scale [0 ])
2106
2110
mosaic_labels = np .concatenate (mosaic_labels , 0 )
2107
2111
2112
+ if self .bbox_clip_border :
2113
+ mosaic_bboxes [:, 0 ::2 ] = np .clip (mosaic_bboxes [:, 0 ::2 ], 0 ,
2114
+ 2 * self .img_scale [1 ])
2115
+ mosaic_bboxes [:, 1 ::2 ] = np .clip (mosaic_bboxes [:, 1 ::2 ], 0 ,
2116
+ 2 * self .img_scale [0 ])
2117
+
2108
2118
if not self .skip_filter :
2109
2119
mosaic_bboxes , mosaic_labels = \
2110
2120
self ._filter_box_candidates (mosaic_bboxes , mosaic_labels )
2111
2121
2122
+ # remove outside bboxes
2123
+ inside_inds = find_inside_bboxes (mosaic_bboxes , 2 * self .img_scale [0 ],
2124
+ 2 * self .img_scale [1 ])
2125
+ mosaic_bboxes = mosaic_bboxes [inside_inds ]
2126
+ mosaic_labels = mosaic_labels [inside_inds ]
2127
+
2112
2128
results ['img' ] = mosaic_img
2113
2129
results ['img_shape' ] = mosaic_img .shape
2114
2130
results ['gt_bboxes' ] = mosaic_bboxes
@@ -2243,6 +2259,10 @@ class MixUp:
2243
2259
max_aspect_ratio (float): Aspect ratio of width and height
2244
2260
threshold to filter bboxes. If max(h/w, w/h) larger than this
2245
2261
value, the box will be removed. Default: 20.
2262
+ bbox_clip_border (bool, optional): Whether to clip the objects outside
2263
+ the border of the image. In some dataset like MOT17, the gt bboxes
2264
+ are allowed to cross the border of images. Therefore, we don't
2265
+ need to clip the gt bboxes in these cases. Defaults to True.
2246
2266
skip_filter (bool): Whether to skip filtering rules. If it
2247
2267
is True, the filter rule will not be applied, and the
2248
2268
`min_bbox_size` and `min_area_ratio` and `max_aspect_ratio`
@@ -2258,6 +2278,7 @@ def __init__(self,
2258
2278
min_bbox_size = 5 ,
2259
2279
min_area_ratio = 0.2 ,
2260
2280
max_aspect_ratio = 20 ,
2281
+ bbox_clip_border = True ,
2261
2282
skip_filter = True ):
2262
2283
assert isinstance (img_scale , tuple )
2263
2284
self .dynamic_scale = img_scale
@@ -2268,6 +2289,7 @@ def __init__(self,
2268
2289
self .min_bbox_size = min_bbox_size
2269
2290
self .min_area_ratio = min_area_ratio
2270
2291
self .max_aspect_ratio = max_aspect_ratio
2292
+ self .bbox_clip_border = bbox_clip_border
2271
2293
self .skip_filter = skip_filter
2272
2294
2273
2295
def __call__ (self , results ):
@@ -2371,21 +2393,29 @@ def _mixup_transform(self, results):
2371
2393
2372
2394
# 6. adjust bbox
2373
2395
retrieve_gt_bboxes = retrieve_results ['gt_bboxes' ]
2374
- retrieve_gt_bboxes [:, 0 ::2 ] = np .clip (
2375
- retrieve_gt_bboxes [:, 0 ::2 ] * scale_ratio , 0 , origin_w )
2376
- retrieve_gt_bboxes [:, 1 ::2 ] = np .clip (
2377
- retrieve_gt_bboxes [:, 1 ::2 ] * scale_ratio , 0 , origin_h )
2396
+ retrieve_gt_bboxes [:, 0 ::2 ] = retrieve_gt_bboxes [:, 0 ::2 ] * scale_ratio
2397
+ retrieve_gt_bboxes [:, 1 ::2 ] = retrieve_gt_bboxes [:, 1 ::2 ] * scale_ratio
2398
+ if self .bbox_clip_border :
2399
+ retrieve_gt_bboxes [:, 0 ::2 ] = np .clip (retrieve_gt_bboxes [:, 0 ::2 ],
2400
+ 0 , origin_w )
2401
+ retrieve_gt_bboxes [:, 1 ::2 ] = np .clip (retrieve_gt_bboxes [:, 1 ::2 ],
2402
+ 0 , origin_h )
2378
2403
2379
2404
if is_filp :
2380
2405
retrieve_gt_bboxes [:, 0 ::2 ] = (
2381
2406
origin_w - retrieve_gt_bboxes [:, 0 ::2 ][:, ::- 1 ])
2382
2407
2383
2408
# 7. filter
2384
2409
cp_retrieve_gt_bboxes = retrieve_gt_bboxes .copy ()
2385
- cp_retrieve_gt_bboxes [:, 0 ::2 ] = np .clip (
2386
- cp_retrieve_gt_bboxes [:, 0 ::2 ] - x_offset , 0 , target_w )
2387
- cp_retrieve_gt_bboxes [:, 1 ::2 ] = np .clip (
2388
- cp_retrieve_gt_bboxes [:, 1 ::2 ] - y_offset , 0 , target_h )
2410
+ cp_retrieve_gt_bboxes [:, 0 ::2 ] = \
2411
+ cp_retrieve_gt_bboxes [:, 0 ::2 ] - x_offset
2412
+ cp_retrieve_gt_bboxes [:, 1 ::2 ] = \
2413
+ cp_retrieve_gt_bboxes [:, 1 ::2 ] - y_offset
2414
+ if self .bbox_clip_border :
2415
+ cp_retrieve_gt_bboxes [:, 0 ::2 ] = np .clip (
2416
+ cp_retrieve_gt_bboxes [:, 0 ::2 ], 0 , target_w )
2417
+ cp_retrieve_gt_bboxes [:, 1 ::2 ] = np .clip (
2418
+ cp_retrieve_gt_bboxes [:, 1 ::2 ], 0 , target_h )
2389
2419
2390
2420
# 8. mix up
2391
2421
ori_img = ori_img .astype (np .float32 )
@@ -2405,6 +2435,11 @@ def _mixup_transform(self, results):
2405
2435
mixup_gt_labels = np .concatenate (
2406
2436
(results ['gt_labels' ], retrieve_gt_labels ), axis = 0 )
2407
2437
2438
+ # remove outside bbox
2439
+ inside_inds = find_inside_bboxes (mixup_gt_bboxes , target_h , target_w )
2440
+ mixup_gt_bboxes = mixup_gt_bboxes [inside_inds ]
2441
+ mixup_gt_labels = mixup_gt_labels [inside_inds ]
2442
+
2408
2443
results ['img' ] = mixup_img .astype (np .uint8 )
2409
2444
results ['img_shape' ] = mixup_img .shape
2410
2445
results ['gt_bboxes' ] = mixup_gt_bboxes
@@ -2471,6 +2506,10 @@ class RandomAffine:
2471
2506
max_aspect_ratio (float): Aspect ratio of width and height
2472
2507
threshold to filter bboxes. If max(h/w, w/h) larger than this
2473
2508
value, the box will be removed.
2509
+ bbox_clip_border (bool, optional): Whether to clip the objects outside
2510
+ the border of the image. In some dataset like MOT17, the gt bboxes
2511
+ are allowed to cross the border of images. Therefore, we don't
2512
+ need to clip the gt bboxes in these cases. Defaults to True.
2474
2513
skip_filter (bool): Whether to skip filtering rules. If it
2475
2514
is True, the filter rule will not be applied, and the
2476
2515
`min_bbox_size` and `min_area_ratio` and `max_aspect_ratio`
@@ -2487,6 +2526,7 @@ def __init__(self,
2487
2526
min_bbox_size = 2 ,
2488
2527
min_area_ratio = 0.2 ,
2489
2528
max_aspect_ratio = 20 ,
2529
+ bbox_clip_border = True ,
2490
2530
skip_filter = True ):
2491
2531
assert 0 <= max_translate_ratio <= 1
2492
2532
assert scaling_ratio_range [0 ] <= scaling_ratio_range [1 ]
@@ -2500,6 +2540,7 @@ def __init__(self,
2500
2540
self .min_bbox_size = min_bbox_size
2501
2541
self .min_area_ratio = min_area_ratio
2502
2542
self .max_aspect_ratio = max_aspect_ratio
2543
+ self .bbox_clip_border = bbox_clip_border
2503
2544
self .skip_filter = skip_filter
2504
2545
2505
2546
def __call__ (self , results ):
@@ -2560,20 +2601,25 @@ def __call__(self, results):
2560
2601
warp_bboxes = np .vstack (
2561
2602
(xs .min (1 ), ys .min (1 ), xs .max (1 ), ys .max (1 ))).T
2562
2603
2563
- warp_bboxes [:, [0 , 2 ]] = warp_bboxes [:, [0 , 2 ]].clip (0 , width )
2564
- warp_bboxes [:, [1 , 3 ]] = warp_bboxes [:, [1 , 3 ]].clip (0 , height )
2604
+ if self .bbox_clip_border :
2605
+ warp_bboxes [:, [0 , 2 ]] = \
2606
+ warp_bboxes [:, [0 , 2 ]].clip (0 , width )
2607
+ warp_bboxes [:, [1 , 3 ]] = \
2608
+ warp_bboxes [:, [1 , 3 ]].clip (0 , height )
2565
2609
2610
+ # remove outside bbox
2611
+ valid_index = find_inside_bboxes (warp_bboxes , height , width )
2566
2612
if not self .skip_filter :
2567
2613
# filter bboxes
2568
- valid_index = self .filter_gt_bboxes (
2614
+ filter_index = self .filter_gt_bboxes (
2569
2615
bboxes * scaling_ratio , warp_bboxes )
2570
- results [ key ] = warp_bboxes [ valid_index ]
2571
- if key in [ 'gt_bboxes' ]:
2572
- if 'gt_labels' in results :
2573
- results [ 'gt_labels' ] = results [ 'gt_labels' ][
2574
- valid_index ]
2575
- else :
2576
- results [ key ] = warp_bboxes
2616
+ valid_index = valid_index & filter_index
2617
+
2618
+ results [ key ] = warp_bboxes [ valid_index ]
2619
+ if key in [ 'gt_bboxes' ]:
2620
+ if 'gt_labels' in results :
2621
+ results [ 'gt_labels' ] = results [ 'gt_labels' ][
2622
+ valid_index ]
2577
2623
2578
2624
if 'gt_masks' in results :
2579
2625
raise NotImplementedError (
0 commit comments