def setup(args): cfg = get_cfg() if args.config_file: cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) cfg.freeze() return cfg
def test_default_anchor_generator_centered(self): cfg = get_cfg() cfg.MODEL.ANCHOR_GENERATOR.SIZES = [[32, 64]] cfg.MODEL.ANCHOR_GENERATOR.ASPECT_RATIOS = [[0.25, 1, 4]] cfg.MODEL.ANCHOR_GENERATOR.OFFSET = 0.5 anchor_generator = DefaultAnchorGenerator(cfg, [ShapeSpec(stride=4)]) # only the last two dimensions of features matter here num_images = 2 features = {"stage3": torch.rand(num_images, 96, 1, 2)} anchors = anchor_generator([features["stage3"]]) expected_anchor_tensor = torch.tensor([ [-30.0, -6.0, 34.0, 10.0], [-14.0, -14.0, 18.0, 18.0], [-6.0, -30.0, 10.0, 34.0], [-62.0, -14.0, 66.0, 18.0], [-30.0, -30.0, 34.0, 34.0], [-14.0, -62.0, 18.0, 66.0], [-26.0, -6.0, 38.0, 10.0], [-10.0, -14.0, 22.0, 18.0], [-2.0, -30.0, 14.0, 34.0], [-58.0, -14.0, 70.0, 18.0], [-26.0, -30.0, 38.0, 34.0], [-10.0, -62.0, 22.0, 66.0], ]) for i in range(num_images): assert torch.allclose(anchors[i][0].tensor, expected_anchor_tensor)
def test_default_anchor_generator(self): cfg = get_cfg() cfg.MODEL.ANCHOR_GENERATOR.SIZES = [[32, 64]] cfg.MODEL.ANCHOR_GENERATOR.ASPECT_RATIOS = [[0.25, 1, 4]] anchor_generator = DefaultAnchorGenerator(cfg, [ShapeSpec(stride=4)]) # only the last two dimensions of features matter here num_images = 2 features = {"stage3": torch.rand(num_images, 96, 1, 2)} anchors = anchor_generator([features["stage3"]]) expected_anchor_tensor = torch.tensor([ [-32.0, -8.0, 32.0, 8.0], [-16.0, -16.0, 16.0, 16.0], [-8.0, -32.0, 8.0, 32.0], [-64.0, -16.0, 64.0, 16.0], [-32.0, -32.0, 32.0, 32.0], [-16.0, -64.0, 16.0, 64.0], [-28.0, -8.0, 36.0, 8.0], # -28.0 == -32.0 + STRIDE (4) [-12.0, -16.0, 20.0, 16.0], [-4.0, -32.0, 12.0, 32.0], [-60.0, -16.0, 68.0, 16.0], [-28.0, -32.0, 36.0, 32.0], [-12.0, -64.0, 20.0, 64.0], ]) for i in range(num_images): assert torch.allclose(anchors[i][0].tensor, expected_anchor_tensor)
def get(config_path, trained: bool = False): """ Get a model specified by relative path under mydl's official ``configs/`` directory. Args: config_path (str): config file name relative to mydl's "configs/" directory, e.g., "COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml" trained (bool): If True, will initialize the model with the trained model zoo weights. If False, the checkpoint specified in the config file's ``MODEL.WEIGHTS`` is used instead; this will typically (though not always) initialize a subset of weights using an ImageNet pre-trained model, while randomly initializing the other weights. Example: .. code-block:: python from mydl import model_zoo model = model_zoo.get("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml", trained=True) """ cfg_file = get_config_file(config_path) cfg = get_cfg() cfg.merge_from_file(cfg_file) if trained: cfg.MODEL.WEIGHTS = get_checkpoint_url(config_path) if not torch.cuda.is_available(): cfg.MODEL.DEVICE = "cpu" model = build_model(cfg) DetectionCheckpointer(model).load(cfg.MODEL.WEIGHTS) return model
def test_upgrade_downgrade_consistency(self): cfg = get_cfg() # check that custom is preserved cfg.USER_CUSTOM = 1 down = downgrade_config(cfg, to_version=0) up = upgrade_config(down) self.assertTrue(up == cfg)
def setup(args): cfg = get_cfg() cfg.merge_from_file(args.config_file) cfg.SOLVER.BASE_LR = 0.001 # Avoid NaNs. Not useful in this script anyway. cfg.merge_from_list(args.opts) cfg.freeze() setup_logger(distributed_rank=comm.get_rank()) return cfg
def setup_cfg(args): cfg = get_cfg() # cuda context is initialized before creating dataloader, so we don't fork anymore cfg.DATALOADER.NUM_WORKERS = 0 cfg = add_export_config(cfg) cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) cfg.freeze() return cfg
def test_auto_upgrade(self): cfg = get_cfg() latest_ver = cfg.VERSION cfg.USER_CUSTOM = 1 self._merge_cfg_str(cfg, _V0_CFG) self.assertEqual(cfg.MODEL.RPN.HEAD_NAME, "TEST") self.assertEqual(cfg.VERSION, latest_ver)
def setup(args): """ Create configs and perform basic setups. """ cfg = get_cfg() cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) cfg.freeze() default_setup(cfg, args) return cfg
def get_model_zoo(config_path): """ Like model_zoo.get, but do not load any weights (even pretrained) """ cfg_file = model_zoo.get_config_file(config_path) cfg = get_cfg() cfg.merge_from_file(cfg_file) if not torch.cuda.is_available(): cfg.MODEL.DEVICE = "cpu" return build_model(cfg)
def setup_config(cls: type, config_fpath: str, model_fpath: str, args: argparse.Namespace, opts: List[str]): cfg = get_cfg() add_densepose_config(cfg) cfg.merge_from_file(config_fpath) cfg.merge_from_list(args.opts) if opts: cfg.merge_from_list(opts) cfg.MODEL.WEIGHTS = model_fpath cfg.freeze() return cfg
def setup_cfg(args): # load config from file and command-line arguments cfg = get_cfg() cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) # Set score_threshold for builtin models cfg.MODEL.RETINANET.SCORE_THRESH_TEST = args.confidence_threshold cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = args.confidence_threshold cfg.MODEL.PANOPTIC_FPN.COMBINE.INSTANCES_CONFIDENCE_THRESH = args.confidence_threshold cfg.freeze() return cfg
def setup(args): """ Create configs and perform basic setups. """ cfg = get_cfg() cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) cfg.freeze() default_setup( cfg, args ) # if you don't like any of the default setup, write your own setup code return cfg
def test_rroi_heads(self): torch.manual_seed(121) cfg = get_cfg() cfg.MODEL.PROPOSAL_GENERATOR.NAME = "RRPN" cfg.MODEL.ANCHOR_GENERATOR.NAME = "RotatedAnchorGenerator" cfg.MODEL.ROI_HEADS.NAME = "RROIHeads" cfg.MODEL.ROI_BOX_HEAD.NAME = "FastRCNNConvFCHead" cfg.MODEL.ROI_BOX_HEAD.NUM_FC = 2 cfg.MODEL.RPN.BBOX_REG_WEIGHTS = (1, 1, 1, 1, 1) cfg.MODEL.RPN.HEAD_NAME = "StandardRPNHead" cfg.MODEL.ROI_BOX_HEAD.POOLER_TYPE = "ROIAlignRotated" cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5, 1) backbone = build_backbone(cfg) num_images = 2 images_tensor = torch.rand(num_images, 20, 30) image_sizes = [(10, 10), (20, 30)] images = ImageList(images_tensor, image_sizes) num_channels = 1024 features = {"res4": torch.rand(num_images, num_channels, 1, 2)} image_shape = (15, 15) gt_boxes0 = torch.tensor([[2, 2, 2, 2, 30], [4, 4, 4, 4, 0]], dtype=torch.float32) gt_instance0 = Instances(image_shape) gt_instance0.gt_boxes = RotatedBoxes(gt_boxes0) gt_instance0.gt_classes = torch.tensor([2, 1]) gt_boxes1 = torch.tensor([[1.5, 5.5, 1, 3, 0], [8.5, 4, 3, 2, -50]], dtype=torch.float32) gt_instance1 = Instances(image_shape) gt_instance1.gt_boxes = RotatedBoxes(gt_boxes1) gt_instance1.gt_classes = torch.tensor([1, 2]) gt_instances = [gt_instance0, gt_instance1] proposal_generator = build_proposal_generator(cfg, backbone.output_shape()) roi_heads = build_roi_heads(cfg, backbone.output_shape()) with EventStorage(): # capture events in a new storage to discard them proposals, proposal_losses = proposal_generator( images, features, gt_instances) _, detector_losses = roi_heads(images, features, proposals, gt_instances) expected_losses = { "loss_cls": torch.tensor(4.381443977355957), "loss_box_reg": torch.tensor(0.0011560433777049184), } for name in expected_losses.keys(): err_msg = "detector_losses[{}] = {}, expected losses = {}".format( name, detector_losses[name], expected_losses[name]) self.assertTrue( torch.allclose(detector_losses[name], expected_losses[name]), err_msg)
def setup(args): cfg = get_cfg() add_densepose_config(cfg) cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) cfg.freeze() default_setup(cfg, args) # Setup logger for "densepose" module setup_logger(output=cfg.OUTPUT_DIR, distributed_rank=comm.get_rank(), name="densepose") return cfg
def test_apply_rotated_boxes(self): np.random.seed(125) cfg = get_cfg() is_train = True transform_gen = detection_utils.build_transform_gen(cfg, is_train) image = np.random.rand(200, 300) image, transforms = T.apply_transform_gens(transform_gen, image) image_shape = image.shape[:2] # h, w assert image_shape == (800, 1200) annotation = {"bbox": [179, 97, 62, 40, -56]} boxes = np.array([annotation["bbox"]], dtype=np.float64) # boxes.shape = (1, 5) transformed_bbox = transforms.apply_rotated_box(boxes)[0] expected_bbox = np.array([484, 388, 248, 160, 56], dtype=np.float64) err_msg = "transformed_bbox = {}, expected {}".format(transformed_bbox, expected_bbox) assert np.allclose(transformed_bbox, expected_bbox), err_msg
def test_roi_heads(self): torch.manual_seed(121) cfg = get_cfg() cfg.MODEL.ROI_HEADS.NAME = "StandardROIHeads" cfg.MODEL.ROI_BOX_HEAD.NAME = "FastRCNNConvFCHead" cfg.MODEL.ROI_BOX_HEAD.NUM_FC = 2 cfg.MODEL.ROI_BOX_HEAD.POOLER_TYPE = "ROIAlignV2" cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5) backbone = build_backbone(cfg) num_images = 2 images_tensor = torch.rand(num_images, 20, 30) image_sizes = [(10, 10), (20, 30)] images = ImageList(images_tensor, image_sizes) num_channels = 1024 features = {"res4": torch.rand(num_images, num_channels, 1, 2)} image_shape = (15, 15) gt_boxes0 = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6]], dtype=torch.float32) gt_instance0 = Instances(image_shape) gt_instance0.gt_boxes = Boxes(gt_boxes0) gt_instance0.gt_classes = torch.tensor([2, 1]) gt_boxes1 = torch.tensor([[1, 5, 2, 8], [7, 3, 10, 5]], dtype=torch.float32) gt_instance1 = Instances(image_shape) gt_instance1.gt_boxes = Boxes(gt_boxes1) gt_instance1.gt_classes = torch.tensor([1, 2]) gt_instances = [gt_instance0, gt_instance1] proposal_generator = build_proposal_generator(cfg, backbone.output_shape()) roi_heads = build_roi_heads(cfg, backbone.output_shape()) with EventStorage(): # capture events in a new storage to discard them proposals, proposal_losses = proposal_generator( images, features, gt_instances) _, detector_losses = roi_heads(images, features, proposals, gt_instances) expected_losses = { "loss_cls": torch.tensor(4.4236516953), "loss_box_reg": torch.tensor(0.0091214813), } for name in expected_losses.keys(): self.assertTrue( torch.allclose(detector_losses[name], expected_losses[name]))
def test_fast_rcnn_empty_batch(self): cfg = get_cfg() cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5) box2box_transform = Box2BoxTransform(weights=cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS) logits = torch.randn(0, 100, requires_grad=True) deltas = torch.randn(0, 4, requires_grad=True) outputs = FastRCNNOutputs(box2box_transform, logits, deltas, [], 0.5) losses = outputs.losses() for value in losses.values(): self.assertTrue(torch.allclose(value, torch.zeros_like(value))) sum(losses.values()).backward() self.assertTrue(logits.grad is not None) self.assertTrue(deltas.grad is not None) predictions, _ = outputs.inference(0.05, 0.5, 100) self.assertEqual(len(predictions), 0)
def test_fast_rcnn_rotated(self): torch.manual_seed(132) cfg = get_cfg() cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5, 1) box2box_transform = Box2BoxTransformRotated(weights=cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS) box_head_output_size = 8 num_classes = 5 cls_agnostic_bbox_reg = False box_predictor = FastRCNNOutputLayers( box_head_output_size, num_classes, cls_agnostic_bbox_reg, box_dim=5 ) feature_pooled = torch.rand(2, box_head_output_size) pred_class_logits, pred_proposal_deltas = box_predictor(feature_pooled) image_shape = (10, 10) proposal_boxes = torch.tensor( [[2, 1.95, 2.4, 1.7, 0], [4.65, 5.25, 4.7, 5.5, 0]], dtype=torch.float32 ) gt_boxes = torch.tensor([[2, 2, 2, 2, 0], [4, 4, 4, 4, 0]], dtype=torch.float32) result = Instances(image_shape) result.proposal_boxes = RotatedBoxes(proposal_boxes) result.gt_boxes = RotatedBoxes(gt_boxes) result.gt_classes = torch.tensor([1, 2]) proposals = [] proposals.append(result) smooth_l1_beta = cfg.MODEL.ROI_BOX_HEAD.SMOOTH_L1_BETA outputs = RotatedFastRCNNOutputs( box2box_transform, pred_class_logits, pred_proposal_deltas, proposals, smooth_l1_beta ) with EventStorage(): # capture events in a new storage to discard them losses = outputs.losses() # Note: the expected losses are slightly different even if # the boxes are essentially the same as in the FastRCNNOutput test, because # bbox_pred in FastRCNNOutputLayers have different Linear layers/initialization # between the two cases. expected_losses = { "loss_cls": torch.tensor(1.7920907736), "loss_box_reg": torch.tensor(4.0410838127), } for name in expected_losses.keys(): assert torch.allclose(losses[name], expected_losses[name])
def test_rrpn_anchor_generator(self): cfg = get_cfg() cfg.MODEL.ANCHOR_GENERATOR.SIZES = [[32, 64]] cfg.MODEL.ANCHOR_GENERATOR.ASPECT_RATIOS = [[0.25, 1, 4]] cfg.MODEL.ANCHOR_GENERATOR.ANGLES = [[0, 45]] anchor_generator = RotatedAnchorGenerator(cfg, [ShapeSpec(stride=4)]) # only the last two dimensions of features matter here num_images = 2 features = {"stage3": torch.rand(num_images, 96, 1, 2)} anchors = anchor_generator([features["stage3"]]) expected_anchor_tensor = torch.tensor([ [0.0, 0.0, 64.0, 16.0, 0.0], [0.0, 0.0, 64.0, 16.0, 45.0], [0.0, 0.0, 32.0, 32.0, 0.0], [0.0, 0.0, 32.0, 32.0, 45.0], [0.0, 0.0, 16.0, 64.0, 0.0], [0.0, 0.0, 16.0, 64.0, 45.0], [0.0, 0.0, 128.0, 32.0, 0.0], [0.0, 0.0, 128.0, 32.0, 45.0], [0.0, 0.0, 64.0, 64.0, 0.0], [0.0, 0.0, 64.0, 64.0, 45.0], [0.0, 0.0, 32.0, 128.0, 0.0], [0.0, 0.0, 32.0, 128.0, 45.0], [4.0, 0.0, 64.0, 16.0, 0.0], # 4.0 == 0.0 + STRIDE (4) [4.0, 0.0, 64.0, 16.0, 45.0], [4.0, 0.0, 32.0, 32.0, 0.0], [4.0, 0.0, 32.0, 32.0, 45.0], [4.0, 0.0, 16.0, 64.0, 0.0], [4.0, 0.0, 16.0, 64.0, 45.0], [4.0, 0.0, 128.0, 32.0, 0.0], [4.0, 0.0, 128.0, 32.0, 45.0], [4.0, 0.0, 64.0, 64.0, 0.0], [4.0, 0.0, 64.0, 64.0, 45.0], [4.0, 0.0, 32.0, 128.0, 0.0], [4.0, 0.0, 32.0, 128.0, 45.0], ]) for i in range(num_images): assert torch.allclose(anchors[i][0].tensor, expected_anchor_tensor)
def test_fast_rcnn(self): torch.manual_seed(132) cfg = get_cfg() cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5) box2box_transform = Box2BoxTransform(weights=cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS) box_head_output_size = 8 num_classes = 5 cls_agnostic_bbox_reg = False box_predictor = FastRCNNOutputLayers( box_head_output_size, num_classes, cls_agnostic_bbox_reg, box_dim=4 ) feature_pooled = torch.rand(2, box_head_output_size) pred_class_logits, pred_proposal_deltas = box_predictor(feature_pooled) image_shape = (10, 10) proposal_boxes = torch.tensor([[0.8, 1.1, 3.2, 2.8], [2.3, 2.5, 7, 8]], dtype=torch.float32) gt_boxes = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6]], dtype=torch.float32) result = Instances(image_shape) result.proposal_boxes = Boxes(proposal_boxes) result.gt_boxes = Boxes(gt_boxes) result.gt_classes = torch.tensor([1, 2]) proposals = [] proposals.append(result) smooth_l1_beta = cfg.MODEL.ROI_BOX_HEAD.SMOOTH_L1_BETA outputs = FastRCNNOutputs( box2box_transform, pred_class_logits, pred_proposal_deltas, proposals, smooth_l1_beta ) with EventStorage(): # capture events in a new storage to discard them losses = outputs.losses() expected_losses = { "loss_cls": torch.tensor(1.7951188087), "loss_box_reg": torch.tensor(4.0357131958), } for name in expected_losses.keys(): assert torch.allclose(losses[name], expected_losses[name])
def test_guess_v1(self): cfg = get_cfg() latest_ver = cfg.VERSION self._merge_cfg_str(cfg, _V1_CFG) self.assertEqual(cfg.VERSION, latest_ver)
def test_rpn(self): torch.manual_seed(121) cfg = get_cfg() cfg.MODEL.PROPOSAL_GENERATOR.NAME = "RPN" cfg.MODEL.ANCHOR_GENERATOR.NAME = "DefaultAnchorGenerator" cfg.MODEL.RPN.BBOX_REG_WEIGHTS = (1, 1, 1, 1) backbone = build_backbone(cfg) proposal_generator = build_proposal_generator(cfg, backbone.output_shape()) num_images = 2 images_tensor = torch.rand(num_images, 20, 30) image_sizes = [(10, 10), (20, 30)] images = ImageList(images_tensor, image_sizes) image_shape = (15, 15) num_channels = 1024 features = {"res4": torch.rand(num_images, num_channels, 1, 2)} gt_boxes = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6]], dtype=torch.float32) gt_instances = Instances(image_shape) gt_instances.gt_boxes = Boxes(gt_boxes) with EventStorage(): # capture events in a new storage to discard them proposals, proposal_losses = proposal_generator( images, features, [gt_instances[0], gt_instances[1]]) expected_losses = { "loss_rpn_cls": torch.tensor(0.0804563984), "loss_rpn_loc": torch.tensor(0.0990132466), } for name in expected_losses.keys(): self.assertTrue( torch.allclose(proposal_losses[name], expected_losses[name])) expected_proposal_boxes = [ Boxes(torch.tensor([[0, 0, 10, 10], [7.3365392685, 0, 10, 10]])), Boxes( torch.tensor([ [0, 0, 30, 20], [0, 0, 16.7862777710, 13.1362524033], [0, 0, 30, 13.3173446655], [0, 0, 10.8602609634, 20], [7.7165775299, 0, 27.3875980377, 20], ])), ] expected_objectness_logits = [ torch.tensor([0.1225359365, -0.0133192837]), torch.tensor([ 0.1415634006, 0.0989848152, 0.0565387346, -0.0072308783, -0.0428492837 ]), ] for proposal, expected_proposal_box, im_size, expected_objectness_logit in zip( proposals, expected_proposal_boxes, image_sizes, expected_objectness_logits): self.assertEqual(len(proposal), len(expected_proposal_box)) self.assertEqual(proposal.image_size, im_size) self.assertTrue( torch.allclose(proposal.proposal_boxes.tensor, expected_proposal_box.tensor)) self.assertTrue( torch.allclose(proposal.objectness_logits, expected_objectness_logit))
def test_rrpn(self): torch.manual_seed(121) cfg = get_cfg() cfg.MODEL.PROPOSAL_GENERATOR.NAME = "RRPN" cfg.MODEL.ANCHOR_GENERATOR.NAME = "RotatedAnchorGenerator" cfg.MODEL.ANCHOR_GENERATOR.SIZES = [[32, 64]] cfg.MODEL.ANCHOR_GENERATOR.ASPECT_RATIOS = [[0.25, 1]] cfg.MODEL.ANCHOR_GENERATOR.ANGLES = [[0, 60]] cfg.MODEL.RPN.BBOX_REG_WEIGHTS = (1, 1, 1, 1, 1) cfg.MODEL.RPN.HEAD_NAME = "StandardRPNHead" backbone = build_backbone(cfg) proposal_generator = build_proposal_generator(cfg, backbone.output_shape()) num_images = 2 images_tensor = torch.rand(num_images, 20, 30) image_sizes = [(10, 10), (20, 30)] images = ImageList(images_tensor, image_sizes) image_shape = (15, 15) num_channels = 1024 features = {"res4": torch.rand(num_images, num_channels, 1, 2)} gt_boxes = torch.tensor([[2, 2, 2, 2, 0], [4, 4, 4, 4, 0]], dtype=torch.float32) gt_instances = Instances(image_shape) gt_instances.gt_boxes = RotatedBoxes(gt_boxes) with EventStorage(): # capture events in a new storage to discard them proposals, proposal_losses = proposal_generator( images, features, [gt_instances[0], gt_instances[1]]) expected_losses = { "loss_rpn_cls": torch.tensor(0.0432923734), "loss_rpn_loc": torch.tensor(0.1552739739), } for name in expected_losses.keys(): self.assertTrue( torch.allclose(proposal_losses[name], expected_losses[name])) expected_proposal_boxes = [ RotatedBoxes( torch.tensor([ [ 0.60189795, 1.24095452, 61.98131943, 18.03621292, -4.07244873 ], [ 15.64940453, 1.69624567, 59.59749603, 16.34339333, 2.62692475 ], [ -3.02982378, -2.69752932, 67.90952301, 59.62455750, 59.97010040 ], [ 16.71863365, 1.98309708, 35.61507797, 32.81484985, 62.92267227 ], [ 0.49432933, -7.92979717, 67.77606201, 62.93098450, -1.85656738 ], [ 8.00880814, 1.36017394, 121.81007385, 32.74150467, 50.44297409 ], [ 16.44299889, -4.82221127, 63.39775848, 61.22503662, 54.12270737 ], [ 5.00000000, 5.00000000, 10.00000000, 10.00000000, -0.76943970 ], [ 17.64130402, -0.98095351, 61.40377808, 16.28918839, 55.53118134 ], [ 0.13016054, 4.60568953, 35.80157471, 32.30180359, 62.52872086 ], [ -4.26460743, 0.39604485, 124.30079651, 31.84611320, -1.58203125 ], [ 7.52815342, -0.91636634, 62.39784622, 15.45565224, 60.79549789 ], ])), RotatedBoxes( torch.tensor([ [ 0.07734215, 0.81635046, 65.33510590, 17.34688377, -1.51821899 ], [ -3.41833067, -3.11320257, 64.17595673, 60.55617905, 58.27033234 ], [ 20.67383385, -6.16561556, 63.60531998, 62.52315903, 54.85546494 ], [ 15.00000000, 10.00000000, 30.00000000, 20.00000000, -0.18218994 ], [ 9.22646523, -6.84775209, 62.09895706, 65.46472931, -2.74307251 ], [ 15.00000000, 4.93451595, 30.00000000, 9.86903191, -0.60272217 ], [ 8.88342094, 2.65560246, 120.95362854, 32.45022202, 55.75970078 ], [ 16.39088631, 2.33887148, 34.78761292, 35.61492920, 60.81977463 ], [ 9.78298569, 10.00000000, 19.56597137, 20.00000000, -0.86660767 ], [ 1.28576660, 5.49873352, 34.93610382, 33.22600174, 60.51599884 ], [ 17.58912468, -1.63270092, 62.96052551, 16.45713997, 52.91245270 ], [ 5.64749718, -1.90428460, 62.37649155, 16.19474792, 61.09543991 ], [ 0.82255805, 2.34931135, 118.83985901, 32.83671188, 56.50753784 ], [ -5.33874989, 1.64404404, 125.28501892, 33.35424042, -2.80731201 ], ])), ] expected_objectness_logits = [ torch.tensor([ 0.10111768, 0.09112845, 0.08466332, 0.07589971, 0.06650183, 0.06350251, 0.04299347, 0.01864817, 0.00986163, 0.00078543, -0.04573630, -0.04799230, ]), torch.tensor([ 0.11373727, 0.09377633, 0.05281663, 0.05143715, 0.04040275, 0.03250912, 0.01307789, 0.01177734, 0.00038105, -0.00540255, -0.01194804, -0.01461012, -0.03061717, -0.03599222, ]), ] torch.set_printoptions(precision=8, sci_mode=False) for proposal, expected_proposal_box, im_size, expected_objectness_logit in zip( proposals, expected_proposal_boxes, image_sizes, expected_objectness_logits): self.assertEqual(len(proposal), len(expected_proposal_box)) self.assertEqual(proposal.image_size, im_size) # It seems that there's some randomness in the result across different machines: # This test can be run on a local machine for 100 times with exactly the same result, # However, a different machine might produce slightly different results, # thus the atol here. err_msg = "computed proposal boxes = {}, expected {}".format( proposal.proposal_boxes.tensor, expected_proposal_box.tensor) self.assertTrue( torch.allclose(proposal.proposal_boxes.tensor, expected_proposal_box.tensor, atol=1e-5), err_msg, ) err_msg = "computed objectness logits = {}, expected {}".format( proposal.objectness_logits, expected_objectness_logit) self.assertTrue( torch.allclose(proposal.objectness_logits, expected_objectness_logit, atol=1e-5), err_msg, )