class_docstr: Implements Region Proposal Network (RPN).
  
  Args:
      anchor_generator (AnchorGenerator): module that generates the anchors for a set of feature
          maps.
      head (nn.Module): module that computes the objectness and regression deltas
      fg_iou_thresh (float): minimum IoU between the anchor and the GT box so that they can be
          considered as positive during training of the RPN.
      bg_iou_thresh (float): maximum IoU between the anchor and the GT box so that they can be
          considered as negative during training of the RPN.
      batch_size_per_image (int): number of anchors that are sampled during training of the RPN
          for computing the loss
      positive_fraction (float): proportion of positive anchors in a mini-batch during training
          of the RPN
      pre_nms_top_n (Dict[str, int]): number of proposals to keep before applying NMS. It should
          contain two fields: training and testing, to allow for different values depending
          on training or evaluation
      post_nms_top_n (Dict[str, int]): number of proposals to keep after applying NMS. It should
          contain two fields: training and testing, to allow for different values depending
          on training or evaluation
      nms_thresh (float): NMS threshold used for postprocessing the RPN proposals
code: def filter_proposals(
      self,
      proposals: Tensor,
      objectness: Tensor,
      image_shapes: List[Tuple[int, int]],
      num_anchors_per_level: List[int],
  ) -> Tuple[List[Tensor], List[Tensor]]:
      num_images = proposals.shape[0]
      device = proposals.device
      # do not backprop through objectness
      objectness = objectness.detach()
      objectness = objectness.reshape(num_images, -1)
  
      levels = [
          torch.full((n,), idx, dtype=torch.int64, device=device)
          for idx, n in enumerate(num_anchors_per_level)
      ]
      levels = torch.cat(levels, 0)
      levels = levels.reshape(1, -1).expand_as(objectness)
  
      # select top_n boxes independently per level before applying nms
      top_n_idx = self._get_top_n_idx(objectness, num_anchors_per_level)
  
      image_range = torch.arange(num_images, device=device)
      batch_idx = image_range[:, None]
  
      objectness = objectness[batch_idx, top_n_idx]
      levels = levels[batch_idx, top_n_idx]
      proposals = proposals[batch_idx, top_n_idx]
  
      objectness_prob = torch.sigmoid(objectness)
  
      final_boxes = []
      final_scores = []
      for boxes, scores, lvl, img_shape in zip(
          proposals, objectness_prob, levels, image_shapes
      ):
          boxes = box_ops.clip_boxes_to_image(boxes, img_shape)
  
          # remove small boxes
          keep = box_ops.remove_small_boxes(boxes, self.min_size)
          boxes, scores, lvl = boxes[keep], scores[keep], lvl[keep]
  
          # remove low scoring boxes
          # use >= for Backwards compatibility
          keep = torch.where(scores >= self.score_thresh)[0]
          boxes, scores, lvl = boxes[keep], scores[keep], lvl[keep]
  
          # non-maximum suppression, independently done per level
          keep = box_ops.batched_nms(
              boxes, scores, lvl, self.nms_thresh
          )
  
          # keep only topk scoring predictions
          keep = keep[: self.post_nms_top_n()]
          boxes, scores = boxes[keep], scores[keep]
  
          final_boxes.append(boxes)
          final_scores.append(scores)
      return final_boxes, final_scores
  
imports: from typing import Dict, List, Optional, Tuple
  import torch
  from torch import nn, Tensor
  from torch.nn import functional
  from torchvision.ops import boxes, Conv2dNormActivation
  from .None import _utils
  from .anchor_utils import AnchorGenerator
  from .image_list import ImageList
label_desc: Use image node_id 6 for calling the RegionProposalNetwork obj's underlying member method code with example usage: obj.filter_proposals(proposals, objectness, image_shapes, num_anchors_per_level) and returns: final_boxes,  final_scores