docstr: Arguments:
      features (List[Tensor])
      proposals (List[Tensor[N, 4]])
      image_shapes (List[Tuple[H, W]])
      targets (List[Dict])
docstr_tok: ["Arguments",":","features","(","List","[","Tensor","]",")","proposals","(","List","[","Tensor","[","N",",","4","]","]",")","image_shapes","(","List","[","Tuple","[","H",",","W","]","]",")","targets","(","List","[","Dict","]",")"]
code: def forward(
      self,
      features,  # type: Dict[str, Tensor]
      proposals,  # type: List[Tensor]
      image_shapes,  # type: List[Tuple[int, int]]
      targets=None,  # type: Optional[List[Dict[str, Tensor]]]
  ):
      # type: (...) -> Tuple[List[Dict[str, Tensor]], Dict[str, Tensor]]
      """
      Arguments:
          features (List[Tensor])
          proposals (List[Tensor[N, 4]])
          image_shapes (List[Tuple[H, W]])
          targets (List[Dict])
      """
  
      # 检查targets的数据类型是否正确
      if targets is not None:
          for t in targets:
              floating_point_types = (
                  torch.float,
                  torch.double,
                  torch.half,
              )
              assert (
                  t["boxes"].dtype in floating_point_types
              ), "target boxes must of float type"
              assert (
                  t["labels"].dtype == torch.int64
              ), "target labels must of int64 type"
  
      if self.training:
          # 划分正负样本，统计对应gt的标签以及边界框回归信息
          (
              proposals,
              labels,
              regression_targets,
          ) = self.select_training_samples(proposals, targets)
      else:
          labels = None
          regression_targets = None
  
      # 将采集样本通过Multi-scale RoIAlign pooling层
      # box_features_shape: [num_proposals, channel, height, width]
      box_features = self.box_roi_pool(
          features, proposals, image_shapes
      )
  
      # 通过roi_pooling后的两层全连接层
      # box_features_shape: [num_proposals, representation_size]
      box_features = self.box_head(box_features)
  
      # 接着分别预测目标类别和边界框回归参数
      class_logits, box_regression = self.box_predictor(box_features)
  
      result = torch.jit.annotate(List[Dict[str, torch.Tensor]], [])
      losses = {}
      if self.training:
          assert labels is not None and regression_targets is not None
          loss_classifier, loss_box_reg = fastrcnn_loss(
              class_logits, box_regression, labels, regression_targets
          )
          losses = {
              "loss_classifier": loss_classifier,
              "loss_box_reg": loss_box_reg,
          }
      else:
          boxes, scores, labels = self.postprocess_detections(
              class_logits, box_regression, proposals, image_shapes
          )
          num_images = len(boxes)
          for i in range(num_images):
              result.append(
                  {
                      "boxes": boxes[i],
                      "labels": labels[i],
                      "scores": scores[i],
                  }
              )
  
      return result, losses
  
file_path: deep-learning-for-image-processing/pytorch_object_detection/train_coco_dataset/network_files/roi_head.py
imports: from typing import Optional, List, Dict, Tuple
  import torch
  from torch import Tensor
  import torch.nn.functional
  from .None import det_utils
  from .None import boxes
label_desc: Use image node_id 8 for calling the RoIHeads obj's underlying member method code with example usage: obj.forward(features, proposals, image_shapes, targets) and returns: result,  losses