Exemplo n.º 1
0
    def forward(self, x, box_lists):
        assert not self.training

        pooler_fmt_boxes = self.c2_preprocess(box_lists)
        num_level_assignments = len(self.level_poolers)

        if num_level_assignments == 1:
            out = torch.ops._caffe2.RoIAlign(
                x[0],
                pooler_fmt_boxes,
                order="NCHW",
                spatial_scale=float(self.level_poolers[0].spatial_scale),
                pooled_h=int(self.output_size[0]),
                pooled_w=int(self.output_size[1]),
                sampling_ratio=int(self.level_poolers[0].sampling_ratio),
                aligned=bool(self.level_poolers[0].aligned),
            )
            return out

        device = pooler_fmt_boxes.device
        assert (
            self.max_level - self.min_level +
            1 == 4), "Currently DistributeFpnProposals only support 4 levels"
        fpn_outputs = torch.ops._caffe2.DistributeFpnProposals(
            to_device(pooler_fmt_boxes, "cpu"),
            roi_canonical_scale=self.canonical_box_size,
            roi_canonical_level=self.canonical_level,
            roi_max_level=self.max_level,
            roi_min_level=self.min_level,
            legacy_plus_one=False,
        )
        fpn_outputs = [to_device(x, device) for x in fpn_outputs]

        rois_fpn_list = fpn_outputs[:-1]
        rois_idx_restore_int32 = fpn_outputs[-1]

        roi_feat_fpn_list = []
        for roi_fpn, x_level, pooler in zip(rois_fpn_list, x,
                                            self.level_poolers):
            roi_feat_fpn = torch.ops._caffe2.RoIAlign(
                x_level,
                roi_fpn,
                order="NCHW",
                spatial_scale=float(pooler.spatial_scale),
                pooled_h=int(self.output_size[0]),
                pooled_w=int(self.output_size[1]),
                sampling_ratio=int(pooler.sampling_ratio),
                aligned=bool(pooler.aligned),
            )
            roi_feat_fpn_list.append(roi_feat_fpn)

        roi_feat_shuffled = cat(roi_feat_fpn_list, dim=0)
        roi_feat = torch.ops._caffe2.BatchPermutation(roi_feat_shuffled,
                                                      rois_idx_restore_int32)
        return roi_feat
Exemplo n.º 2
0
 def __call__(self, pred_keypoint_logits, pred_instances):
     # just return the keypoint heatmap for now,
     # there will be option to call HeatmapMaxKeypointOp
     output = alias(pred_keypoint_logits, "kps_score")
     if all(isinstance(x, InstancesList) for x in pred_instances):
         assert len(pred_instances) == 1
         if self.use_heatmap_max_keypoint:
             device = output.device
             output = torch.ops._caffe2.HeatmapMaxKeypoint(
                 to_device(output, "cpu"),
                 pred_instances[0].pred_boxes.tensor,
                 should_output_softmax=True,  # worth make it configerable?
             )
             output = to_device(output, device)
             output = alias(output, "keypoints_out")
         pred_instances[0].pred_keypoints = output
     return pred_keypoint_logits
Exemplo n.º 3
0
    def __call__(self, fastrcnn_outputs, score_thresh, nms_thresh,
                 topk_per_image):
        """ equivalent to FastRCNNOutputs.inference """
        assert isinstance(fastrcnn_outputs.proposals, Boxes)
        input_tensor_mode = fastrcnn_outputs.proposals.tensor.shape[1] == 5

        class_logits = fastrcnn_outputs.pred_class_logits
        box_regression = fastrcnn_outputs.pred_proposal_deltas
        class_prob = F.softmax(class_logits, -1)

        assert box_regression.shape[1] % 4 == 0
        cls_agnostic_bbox_reg = box_regression.shape[1] // 4 == 1

        device = class_logits.device

        im_info = (torch.Tensor(
            [[sz[0], sz[1], torch.Tensor([1.0])]
             for sz in fastrcnn_outputs.image_shapes]).to(device) if
                   not input_tensor_mode else fastrcnn_outputs.image_shapes[0])

        rois_n4 = fastrcnn_outputs.proposals.tensor
        device, dtype = rois_n4.device, rois_n4.dtype
        if not input_tensor_mode:
            batch_ids = cat(
                [
                    torch.full((b, 1), i, dtype=dtype, device=device)
                    for i, b in enumerate(fastrcnn_outputs.num_preds_per_image)
                ],
                dim=0,
            )
            rois = torch.cat([batch_ids, rois_n4], dim=1)
        else:
            rois = fastrcnn_outputs.proposals.tensor

        roi_pred_bbox, roi_batch_splits = torch.ops._caffe2.BBoxTransform(
            to_device(rois, "cpu"),
            to_device(box_regression, "cpu"),
            to_device(im_info, "cpu"),
            weights=fastrcnn_outputs.box2box_transform.weights,
            apply_scale=True,
            rotated=False,
            angle_bound_on=True,
            angle_bound_lo=-90,
            angle_bound_hi=90,
            clip_angle_thresh=1.0,
            legacy_plus_one=False,
        )
        roi_pred_bbox = to_device(roi_pred_bbox, device)
        roi_batch_splits = to_device(roi_batch_splits, device)

        nms_outputs = torch.ops._caffe2.BoxWithNMSLimit(
            to_device(class_prob, "cpu"),
            to_device(roi_pred_bbox, "cpu"),
            to_device(roi_batch_splits, "cpu"),
            score_thresh=float(score_thresh),
            nms=float(nms_thresh),
            detections_per_im=int(topk_per_image),
            soft_nms_enabled=False,
            soft_nms_method="linear",
            soft_nms_sigma=0.5,
            soft_nms_min_score_thres=0.001,
            rotated=False,
            cls_agnostic_bbox_reg=cls_agnostic_bbox_reg,
            input_boxes_include_bg_cls=False,
            output_classes_include_bg_cls=False,
            legacy_plus_one=False,
        )
        roi_score_nms = to_device(nms_outputs[0], device)
        roi_bbox_nms = to_device(nms_outputs[1], device)
        roi_class_nms = to_device(nms_outputs[2], device)
        roi_batch_splits_nms = to_device(nms_outputs[3], device)
        roi_keeps_nms = to_device(nms_outputs[4], device)
        roi_keeps_size_nms = to_device(nms_outputs[5], device)
        if not self.tensor_mode:
            roi_class_nms = roi_class_nms.to(torch.int64)

        roi_batch_ids = cat(
            [
                torch.full((b, 1), i, dtype=dtype, device=device)
                for i, b in enumerate(
                    int(x.item()) for x in roi_batch_splits_nms)
            ],
            dim=0,
        )

        roi_class_nms = alias(roi_class_nms, "class_nms")
        roi_score_nms = alias(roi_score_nms, "score_nms")
        roi_bbox_nms = alias(roi_bbox_nms, "bbox_nms")
        roi_batch_splits_nms = alias(roi_batch_splits_nms, "batch_splits_nms")
        roi_keeps_nms = alias(roi_keeps_nms, "keeps_nms")
        roi_keeps_size_nms = alias(roi_keeps_size_nms, "keeps_size_nms")

        results = InstancesList(
            im_info=im_info,
            indices=roi_batch_ids[:, 0],
            extra_fields={
                "pred_boxes": Boxes4or5(roi_bbox_nms),
                "scores": roi_score_nms,
                "pred_classes": roi_class_nms,
            },
        )

        if not self.tensor_mode:
            results = InstancesList.to_d2_instances_list(results)
            batch_splits = roi_batch_splits_nms.int().tolist()
            kept_indices = list(
                roi_keeps_nms.to(torch.int64).split(batch_splits))
        else:
            results = [results]
            kept_indices = [roi_keeps_nms]

        return results, kept_indices
Exemplo n.º 4
0
    def forward(self, images, features, gt_instances=None):
        assert not self.training

        features = [features[f] for f in self.in_features]
        objectness_logits_pred, anchor_deltas_pred = self.rpn_head(features)

        # TODO is the needed?
        # objectness_logits_pred = [t.sigmoid() for t in objectness_logits_pred]

        assert isinstance(images, ImageList)
        if self.tensor_mode:
            im_info = images.image_sizes
        else:
            im_info = torch.Tensor([[im_sz[0], im_sz[1],
                                     torch.Tensor([1.0])]
                                    for im_sz in images.image_sizes
                                    ]).to(images.tensor.device)
        assert isinstance(im_info, torch.Tensor)

        rpn_rois_list = []
        rpn_roi_probs_list = []
        for scores, bbox_deltas, cell_anchors_tensor, feat_stride in zip(
                objectness_logits_pred,
                anchor_deltas_pred,
                iter(self.anchor_generator.cell_anchors),
                self.anchor_generator.strides,
        ):
            scores = scores.detach()
            bbox_deltas = bbox_deltas.detach()

            rpn_rois, rpn_roi_probs = torch.ops._caffe2.GenerateProposals(
                scores,
                bbox_deltas,
                im_info,
                cell_anchors_tensor,
                spatial_scale=1.0 / feat_stride,
                pre_nms_topN=self.pre_nms_topk[self.training],
                post_nms_topN=self.post_nms_topk[self.training],
                nms_thresh=self.nms_thresh,
                min_size=self.min_box_side_len,
                # correct_transform_coords=True,  # deprecated argument
                angle_bound_on=True,  # Default
                angle_bound_lo=-90,  # Default
                angle_bound_hi=90,  # Default
                clip_angle_thresh=1.0,  # Default
                legacy_plus_one=False,
            )
            rpn_rois_list.append(rpn_rois)
            rpn_roi_probs_list.append(rpn_roi_probs)

        # For FPN in D2, in RPN all proposals from different levels are concated
        # together, ranked and picked by top post_nms_topk. Then in ROIPooler
        # it calculates level_assignments and calls the RoIAlign from
        # the corresponding level.

        if len(objectness_logits_pred) == 1:
            rpn_rois = rpn_rois_list[0]
            rpn_roi_probs = rpn_roi_probs_list[0]
        else:
            assert len(rpn_rois_list) == len(rpn_roi_probs_list)
            rpn_post_nms_topN = self.post_nms_topk[self.training]

            device = rpn_rois_list[0].device
            input_list = [
                to_device(x, "cpu")
                for x in (rpn_rois_list + rpn_roi_probs_list)
            ]

            # TODO remove this after confirming rpn_max_level/rpn_min_level
            # is not needed in CollectRpnProposals.
            feature_strides = list(self.anchor_generator.strides)
            rpn_min_level = int(math.log2(feature_strides[0]))
            rpn_max_level = int(math.log2(feature_strides[-1]))
            assert (
                rpn_max_level - rpn_min_level +
                1) == len(rpn_rois_list
                          ), "CollectRpnProposals requires continuous levels"

            rpn_rois = torch.ops._caffe2.CollectRpnProposals(
                input_list,
                # NOTE: in current implementation, rpn_max_level and rpn_min_level
                # are not needed, only the subtraction of two matters and it
                # can be infer from the number of inputs. Keep them now for
                # consistency.
                rpn_max_level=2 + len(rpn_rois_list) - 1,
                rpn_min_level=2,
                rpn_post_nms_topN=rpn_post_nms_topN,
            )
            rpn_rois = to_device(rpn_rois, device)
            rpn_roi_probs = []

        proposals = self.c2_postprocess(im_info, rpn_rois, rpn_roi_probs,
                                        self.tensor_mode)
        return proposals, {}