r""" Main method for ROI head that does the following: 1. If training assign target boxes and labels to all proposals 2. If training sample positive and negative proposals 3. If training get bbox transformation targets for all proposals based on assignments 4.
(self, feat, proposals, image_shape, target)
| 585 | return labels, matched_gt_boxes_for_proposals |
| 586 | |
| 587 | def forward(self, feat, proposals, image_shape, target): |
| 588 | r""" |
| 589 | Main method for ROI head that does the following: |
| 590 | 1. If training assign target boxes and labels to all proposals |
| 591 | 2. If training sample positive and negative proposals |
| 592 | 3. If training get bbox transformation targets for all proposals based on assignments |
| 593 | 4. Get ROI Pooled features for all proposals |
| 594 | 5. Call fc6, fc7 and classification and bbox transformation fc layers |
| 595 | 6. Compute classification and localization loss |
| 596 | |
| 597 | :param feat: |
| 598 | :param proposals: |
| 599 | :param image_shape: |
| 600 | :param target: |
| 601 | :return: |
| 602 | """ |
| 603 | if self.training and target is not None: |
| 604 | # Add ground truth to proposals |
| 605 | proposals = torch.cat([proposals, target['bboxes'][0]], dim=0) |
| 606 | |
| 607 | gt_boxes = target['bboxes'][0] |
| 608 | gt_labels = target['labels'][0] |
| 609 | |
| 610 | labels, matched_gt_boxes_for_proposals = self.assign_target_to_proposals(proposals, gt_boxes, gt_labels) |
| 611 | |
| 612 | sampled_neg_idx_mask, sampled_pos_idx_mask = sample_positive_negative(labels, |
| 613 | positive_count=self.roi_pos_count, |
| 614 | total_count=self.roi_batch_size) |
| 615 | |
| 616 | sampled_idxs = torch.where(sampled_pos_idx_mask | sampled_neg_idx_mask)[0] |
| 617 | |
| 618 | # Keep only sampled proposals |
| 619 | proposals = proposals[sampled_idxs] |
| 620 | labels = labels[sampled_idxs] |
| 621 | matched_gt_boxes_for_proposals = matched_gt_boxes_for_proposals[sampled_idxs] |
| 622 | regression_targets = boxes_to_transformation_targets(matched_gt_boxes_for_proposals, proposals) |
| 623 | # regression_targets -> (sampled_training_proposals, 4) |
| 624 | # matched_gt_boxes_for_proposals -> (sampled_training_proposals, 4) |
| 625 | |
| 626 | # Get desired scale to pass to roi pooling function |
| 627 | # For vgg16 case this would be 1/16 (0.0625) |
| 628 | size = feat.shape[-2:] |
| 629 | possible_scales = [] |
| 630 | for s1, s2 in zip(size, image_shape): |
| 631 | approx_scale = float(s1) / float(s2) |
| 632 | scale = 2 ** float(torch.tensor(approx_scale).log2().round()) |
| 633 | possible_scales.append(scale) |
| 634 | assert possible_scales[0] == possible_scales[1] |
| 635 | |
| 636 | # ROI pooling and call all layers for prediction |
| 637 | proposal_roi_pool_feats = torchvision.ops.roi_pool(feat, [proposals], |
| 638 | output_size=self.pool_size, |
| 639 | spatial_scale=possible_scales[0]) |
| 640 | proposal_roi_pool_feats = proposal_roi_pool_feats.flatten(start_dim=1) |
| 641 | box_fc_6 = torch.nn.functional.relu(self.fc6(proposal_roi_pool_feats)) |
| 642 | box_fc_7 = torch.nn.functional.relu(self.fc7(box_fc_6)) |
| 643 | cls_scores = self.cls_layer(box_fc_7) |
| 644 | box_transform_pred = self.bbox_reg_layer(box_fc_7) |
nothing calls this directly
no test coverage detected