77from torchvision .ops import RoIPool
88
99from 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+ """
1019
1120__all__ = ["ROIPooler" ]
1221
1322
1423def 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 ,
1629):
1730 """
1831 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(
3548 `self.min_level`, for the corresponding box (so value i means the box is at
3649 `self.min_level + i`).
3750 """
38- eps = sys .float_info .epsilon
3951 box_sizes = torch .sqrt (cat ([boxes .area () for boxes in box_lists ]))
4052 # Eqn.(1) in FPN paper
4153 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 )
4355 )
4456 # clamp level to (min, max), in case the box size is too large or too small
4557 # for the available feature maps
4658 level_assignments = torch .clamp (level_assignments , min = min_level , max = max_level )
4759 return level_assignments .to (torch .int64 ) - min_level
4860
4961
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 ]):
5170 """
5271 Convert all boxes in `box_lists` to the low-level format used by ROI pooling ops
5372 (see description under Returns).
@@ -70,15 +89,8 @@ def convert_boxes_to_pooler_format(box_lists):
7089 where batch index is the index in [0, N) identifying which batch image the
7190 rotated box (x_ctr, y_ctr, width, height, angle_degrees) comes from.
7291 """
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-
8092 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
8294 )
8395
8496 return pooler_fmt_boxes
@@ -176,7 +188,7 @@ def __init__(
176188 assert canonical_box_size > 0
177189 self .canonical_box_size = canonical_box_size
178190
179- def forward (self , x : List [torch .Tensor ], box_lists ):
191+ def forward (self , x : List [torch .Tensor ], box_lists : List [ Boxes ] ):
180192 """
181193 Args:
182194 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):
226238 (num_boxes , num_channels , output_size , output_size ), dtype = dtype , device = device
227239 )
228240
229- for level , ( x_level , pooler ) in enumerate (zip ( x , self .level_poolers ) ):
241+ for level , pooler in enumerate (self .level_poolers ):
230242 inds = nonzero_tuple (level_assignments == level )[0 ]
231243 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 )
233245
234246 return output
0 commit comments