def forward(self, x, box_lists): """ Args: x (list[Tensor]): A list of feature maps of NCHW shape, with scales matching those used to construct this module. box_lists (list[Boxes] | list[RotatedBoxes]): A list of N Boxes or N RotatedBoxes, where N is the number of images in the batch. The box coordinates are defined on the original image and will be scaled by the `scales` argument of :class:`ROIPooler`. Returns: Tensor: A tensor of shape (M, C, output_size, output_size) where M is the total number of boxes aggregated over all N batch images and C is the number of channels in `x`. """ num_level_assignments = len(self.level_poolers) assert isinstance(x, list) and isinstance( box_lists, list), "Arguments to pooler must be lists" assert ( len(x) == num_level_assignments ), "unequal value, num_level_assignments={}, but x is list of {} Tensors".format( num_level_assignments, len(x)) assert len(box_lists) == x[0].size( 0 ), "unequal value, x[0] batch dim 0 is {}, but box_list has length {}".format( x[0].size(0), len(box_lists)) pooler_fmt_boxes = convert_boxes_to_pooler_format(box_lists) if num_level_assignments == 1: return self.level_poolers[0](x[0], pooler_fmt_boxes) if self.assign_crit == "length": assign_method = assign_boxes_to_levels_by_length else: assign_method = assign_boxes_to_levels level_assignments = assign_method(box_lists, self.min_level, self.max_level, self.canonical_box_size, self.canonical_level) num_boxes = len(pooler_fmt_boxes) num_channels = x[0].shape[1] output_size = self.output_size[0] dtype, device = x[0].dtype, x[0].device output = torch.zeros( (num_boxes, num_channels, output_size, output_size), dtype=dtype, device=device) for level, (x_level, pooler) in enumerate(zip(x, self.level_poolers)): inds = torch.nonzero(level_assignments == level).squeeze(1) pooler_fmt_boxes_level = pooler_fmt_boxes[inds] output[inds] = pooler(x_level, pooler_fmt_boxes_level) return output
def c2_preprocess(box_lists): assert all(isinstance(x, Boxes) for x in box_lists) if all(isinstance(x, Caffe2Boxes) for x in box_lists): # input is pure-tensor based assert len(box_lists) == 1 pooler_fmt_boxes = box_lists[0].tensor else: pooler_fmt_boxes = poolers.convert_boxes_to_pooler_format(box_lists) return pooler_fmt_boxes
def forward(self, x, box_lists): """ see """ num_level_assignments = len(self.level_poolers) assert isinstance(x, list) and isinstance( box_lists, list ), "Arguments to pooler must be lists" assert ( len(x) == num_level_assignments ), "unequal value, num_level_assignments={}, but x is list of {} Tensors".format( num_level_assignments, len(x) ) assert len(box_lists) == x[0].size( 0 ), "unequal value, x[0] batch dim 0 is {}, but box_list has length {}".format( x[0].size(0), len(box_lists) ) if isinstance(box_lists[0], torch.Tensor): # TODO: use Beziers for data_mapper box_lists = [Beziers(x) for x in box_lists] pooler_fmt_boxes = convert_boxes_to_pooler_format(box_lists) if num_level_assignments == 1: return self.level_poolers[0](x[0], pooler_fmt_boxes) if self.assign_crit == "max": assign_method = assign_boxes_to_levels_max elif self.assign_crit == "bezier": assign_method = assign_boxes_to_levels_bezier else: assign_method = assign_boxes_to_levels level_assignments = assign_method( box_lists, self.min_level, self.max_level, self.canonical_box_size, self.canonical_level) num_boxes = len(pooler_fmt_boxes) num_channels = x[0].shape[1] output_size = self.output_size dtype, device = x[0].dtype, x[0].device output = torch.zeros( (num_boxes, num_channels, output_size[0], output_size[1]), dtype=dtype, device=device ) for level, (x_level, pooler) in enumerate(zip(x, self.level_poolers)): inds = torch.nonzero(level_assignments == level).squeeze(1) pooler_fmt_boxes_level = pooler_fmt_boxes[inds] output[inds] = pooler(x_level, pooler_fmt_boxes_level) return output
def _forward_csc(self, masks, pred_class_logits, proposals): if not self.training: return None, None, None, None if self.csc_cur_iter > self.csc_max_iter: PL = self.gt_classes_img_oh NL = torch.zeros( self.gt_classes_img_oh.size(), dtype=self.gt_classes_img_oh.dtype, device=self.gt_classes_img_oh.device, ) W_pos = torch.ones( pred_class_logits.size(), dtype=pred_class_logits.dtype, device=pred_class_logits.device, ) W_neg = torch.zeros( pred_class_logits.size(), dtype=pred_class_logits.dtype, device=pred_class_logits.device, ) return W_pos, W_neg, PL, NL pred_class_img_logits = torch.sum(pred_class_logits, dim=0, keepdim=True) pooler_fmt_boxes = convert_boxes_to_pooler_format( [x.proposal_boxes for x in proposals]) W, PL, NL = self.csc(masks, self.gt_classes_img_oh, pred_class_img_logits, pooler_fmt_boxes) W_pos = torch.clamp(W, min=0.0) W_neg = torch.clamp(W, max=0.0) W_pos.abs_() W_neg.abs_() return W_pos, W_neg, PL, NL
def forward(self, x: List[torch.Tensor], box_lists): """ Args: x (list[Tensor]): A list of feature maps of NCHW shape, with scales matching those used to construct this module. box_lists (list[Boxes] | list[RotatedBoxes]): A list of N Boxes or N RotatedBoxes, where N is the number of images in the batch. The box coordinates are defined on the original image and will be scaled by the `scales` argument of :class:`ROIPooler`. Returns: Tensor: A tensor of shape (N, M, C * output_size * output_size) N: batch_size M: max box num per image """ num_level_assignments = len(self.level_poolers) assert isinstance(x, list) and isinstance( box_lists, list ), "Arguments to pooler must be lists" assert ( len(x) == num_level_assignments ), "unequal value, num_level_assignments={}, but x is list of {} Tensors".format( num_level_assignments, len(x) ) assert len(box_lists) == x[0].size( 0 ), "unequal value, x[0] batch dim 0 is {}, but box_list has length {}".format( x[0].size(0), len(box_lists) ) pooler_fmt_boxes = convert_boxes_to_pooler_format(box_lists) if num_level_assignments == 1: return self.level_poolers[0](x[0], pooler_fmt_boxes) level_assignments = assign_boxes_to_levels( box_lists, self.min_level, self.max_level, self.canonical_box_size, self.canonical_level ) # num_boxes = len(pooler_fmt_boxes) num_proposals = [len(boxes.tensor) for boxes in box_lists] max_num_proposals = max(num_proposals) num_boxes = x[0].shape[0] * max_num_proposals num_channels = x[0].shape[1] output_size = self.output_size[0] dtype, device = x[0].dtype, x[0].device output = torch.zeros( (num_boxes, num_channels, output_size, output_size), dtype=dtype, device=device ) inds_to_padded_inds = torch.zeros((sum(num_proposals),), dtype=torch.int64, device=device) accumulated_proposals = 0 for batch_id in range(x[0].shape[0]): inds = torch.arange(start=0, end=num_proposals[batch_id], device=device) from_inds = inds + batch_id * max_num_proposals to_inds = inds + accumulated_proposals inds_to_padded_inds[to_inds] = from_inds accumulated_proposals += num_proposals[batch_id] for level, (x_level, pooler) in enumerate(zip(x, self.level_poolers)): inds = nonzero_tuple(level_assignments == level)[0] padded_inds = inds_to_padded_inds[inds] pooler_fmt_boxes_level = pooler_fmt_boxes[inds] output[padded_inds] = pooler(x_level, pooler_fmt_boxes_level) output = output.view(x[0].shape[0], max_num_proposals, num_channels, output_size, output_size) seq_lengths = torch.tensor(num_proposals, dtype=torch.int64, device=device) masks = torch.arange(max_num_proposals, device=device)[None, :] >= seq_lengths[:, None] return output, masks, inds_to_padded_inds
def forward(self, x, instances, is_train=False): """ Args: x (list[Tensor]): A list of feature maps of NCHW shape, with scales matching those used to construct this module. instances (list[Instances]): the per-image instances to train/predict masks. In training, they can be the proposals. In inference, they can be the predicted boxes. is_train (True/False) Returns: Tensor: A tensor of shape (M, C, output_size, output_size) where M is the total number of boxes aggregated over all N batch images and C is the number of channels in `x`. """ if is_train: box_lists = [x.proposal_boxes for x in instances] else: box_lists = [x.pred_boxes for x in instances] num_level_assignments = len(self.level_poolers) assert isinstance(x, list) and isinstance( box_lists, list), "Arguments to pooler must be lists" assert ( len(x) == num_level_assignments ), "unequal value, num_level_assignments={}, but x is list of {} Tensors".format( num_level_assignments, len(x)) assert len(box_lists) == x[0].size( 0 ), "unequal value, x[0] batch dim 0 is {}, but box_list has length {}".format( x[0].size(0), len(box_lists)) pooler_fmt_boxes = convert_boxes_to_pooler_format(box_lists) if num_level_assignments == 1: return self.level_poolers[0](x[0], pooler_fmt_boxes) if self.assign_crit == "ratio": level_assignments = assign_boxes_to_levels_by_ratio( instances, self.min_level, self.max_level, is_train) else: #default level_assignments = assign_boxes_to_levels(box_lists, self.min_level, self.max_level, self.canonical_box_size, self.canonical_level) num_boxes = len(pooler_fmt_boxes) num_channels = x[0].shape[1] output_size = self.output_size[0] dtype, device = x[0].dtype, x[0].device output = torch.zeros( (num_boxes, num_channels, output_size, output_size), dtype=dtype, device=device) for level, (x_level, pooler) in enumerate(zip(x, self.level_poolers)): inds = torch.nonzero(level_assignments == level).squeeze(1) pooler_fmt_boxes_level = pooler_fmt_boxes[inds] output[inds] = pooler(x_level, pooler_fmt_boxes_level) return output