7
7
from torchvision .ops import RoIPool
8
8
9
9
from detectron2 .layers import ROIAlign , ROIAlignRotated , cat , nonzero_tuple
10
+ from detectron2 .structures import Boxes
11
+
12
+ """
13
+ To export ROIPooler to torchscript, in this file, variables that should be annotated with
14
+ `Union[List[Boxes], List[RotatedBoxes]]` are only annotated with `List[Boxes]`.
15
+
16
+ TODO: Correct these annotations when torchscript support `Union`.
17
+ https://github.com/pytorch/pytorch/issues/41412
18
+ """
10
19
11
20
__all__ = ["ROIPooler" ]
12
21
13
22
14
23
def assign_boxes_to_levels (
15
- box_lists , min_level : int , max_level : int , canonical_box_size : int , canonical_level : int
24
+ box_lists : List [Boxes ],
25
+ min_level : int ,
26
+ max_level : int ,
27
+ canonical_box_size : int ,
28
+ canonical_level : int ,
16
29
):
17
30
"""
18
31
Map each box in `box_lists` to a feature map level index and return the assignment
@@ -35,19 +48,25 @@ def assign_boxes_to_levels(
35
48
`self.min_level`, for the corresponding box (so value i means the box is at
36
49
`self.min_level + i`).
37
50
"""
38
- eps = sys .float_info .epsilon
39
51
box_sizes = torch .sqrt (cat ([boxes .area () for boxes in box_lists ]))
40
52
# Eqn.(1) in FPN paper
41
53
level_assignments = torch .floor (
42
- canonical_level + torch .log2 (box_sizes / canonical_box_size + eps )
54
+ canonical_level + torch .log2 (box_sizes / canonical_box_size + 1e-8 )
43
55
)
44
56
# clamp level to (min, max), in case the box size is too large or too small
45
57
# for the available feature maps
46
58
level_assignments = torch .clamp (level_assignments , min = min_level , max = max_level )
47
59
return level_assignments .to (torch .int64 ) - min_level
48
60
49
61
50
- def convert_boxes_to_pooler_format (box_lists ):
62
+ def _fmt_box_list (box_tensor , batch_index : int ):
63
+ repeated_index = torch .full (
64
+ (len (box_tensor ), 1 ), batch_index , dtype = box_tensor .dtype , device = box_tensor .device
65
+ )
66
+ return cat ((repeated_index , box_tensor ), dim = 1 )
67
+
68
+
69
+ def convert_boxes_to_pooler_format (box_lists : List [Boxes ]):
51
70
"""
52
71
Convert all boxes in `box_lists` to the low-level format used by ROI pooling ops
53
72
(see description under Returns).
@@ -70,15 +89,8 @@ def convert_boxes_to_pooler_format(box_lists):
70
89
where batch index is the index in [0, N) identifying which batch image the
71
90
rotated box (x_ctr, y_ctr, width, height, angle_degrees) comes from.
72
91
"""
73
-
74
- def fmt_box_list (box_tensor , batch_index ):
75
- repeated_index = torch .full (
76
- (len (box_tensor ), 1 ), batch_index , dtype = box_tensor .dtype , device = box_tensor .device
77
- )
78
- return cat ((repeated_index , box_tensor ), dim = 1 )
79
-
80
92
pooler_fmt_boxes = cat (
81
- [fmt_box_list (box_list .tensor , i ) for i , box_list in enumerate (box_lists )], dim = 0
93
+ [_fmt_box_list (box_list .tensor , i ) for i , box_list in enumerate (box_lists )], dim = 0
82
94
)
83
95
84
96
return pooler_fmt_boxes
@@ -176,7 +188,7 @@ def __init__(
176
188
assert canonical_box_size > 0
177
189
self .canonical_box_size = canonical_box_size
178
190
179
- def forward (self , x : List [torch .Tensor ], box_lists ):
191
+ def forward (self , x : List [torch .Tensor ], box_lists : List [ Boxes ] ):
180
192
"""
181
193
Args:
182
194
x (list[Tensor]): A list of feature maps of NCHW shape, with scales matching those
@@ -226,9 +238,9 @@ def forward(self, x: List[torch.Tensor], box_lists):
226
238
(num_boxes , num_channels , output_size , output_size ), dtype = dtype , device = device
227
239
)
228
240
229
- for level , ( x_level , pooler ) in enumerate (zip ( x , self .level_poolers ) ):
241
+ for level , pooler in enumerate (self .level_poolers ):
230
242
inds = nonzero_tuple (level_assignments == level )[0 ]
231
243
pooler_fmt_boxes_level = pooler_fmt_boxes [inds ]
232
- output [inds ] = pooler (x_level , pooler_fmt_boxes_level )
244
+ output [inds ] = pooler (x [ level ] , pooler_fmt_boxes_level )
233
245
234
246
return output
0 commit comments