Repository: tensorflow/models
File: research/object_detection/meta_architectures/faster_rcnn_meta_arch.py (Python)

Code before:
    `tf.image.crop_and_resize` to create the feature map to be passed to the
    second stage box classifier for each proposal.

    Args:
      features_to_crop: A float32 tensor with shape
        [batch_size, height, width, depth]
      proposal_boxes_normalized: A float32 tensor with shape [batch_size,
        num_proposals, box_code_size] containing proposal boxes in
        normalized coordinates.
      **side_inputs: additional tensors that are required by the network.

    Returns:
      A float32 tensor with shape [K, new_height, new_width, depth].
    """
    num_levels = len(features_to_crop)
    box_levels = None
    if num_levels != 1:
      # If there are mutiple levels to select, get the box levels
      box_levels = ops.fpn_feature_levels(
          num_levels, num_levels - 2,
          tf.sqrt(self._resize_shape[1] * self._resize_shape[2] * 1.0) / 224.0,
          proposal_boxes_normalized)

    cropped_regions = self._flatten_first_two_dimensions(
        self._crop_and_resize_fn(
            features_to_crop, proposal_boxes_normalized, box_levels,
            [self._initial_crop_size, self._initial_crop_size]))
    return self._maxpool_layer(cropped_regions)

  def _postprocess_box_classifier(self,
                                  refined_box_encodings,
                                  class_predictions_with_background,
                                  proposal_boxes,
                                  num_proposals,
                                  image_shapes,
                                  mask_predictions=None):
    """Converts predictions from the second stage box classifier to detections.

    Args:
      refined_box_encodings: a 3-D float tensor with shape
        [total_num_padded_proposals, num_classes, self._box_coder.code_size]
        representing predicted (final) refined box encodings. If using a shared
        box across classes the shape will instead be
        [total_num_padded_proposals, 1, 4]
      class_predictions_with_background: a 2-D tensor float with shape
        [total_num_padded_proposals, num_classes + 1] containing class
        predictions (logits) for each of the proposals.  Note that this tensor
        *includes* background class predictions (at class index 0).
      proposal_boxes: a 3-D float tensor with shape
        [batch_size, self.max_num_proposals, 4] representing decoded proposal
        bounding boxes in absolute coordinates.

Review comment (refactor):
Add a note here that `num_levels-2` is chosen based on section 4.2 of https://arxiv.org/pdf/1612.03144.pdf and works best for Resnet Based feature extractor. 

Code after:

    Helper function for self._postprocess_rpn. This function calls
    `tf.image.crop_and_resize` to create the feature map to be passed to the
    second stage box classifier for each proposal.

    Args:
      features_to_crop: A float32 tensor with shape
        [batch_size, height, width, depth]
      proposal_boxes_normalized: A float32 tensor with shape [batch_size,
        num_proposals, box_code_size] containing proposal boxes in
        normalized coordinates.
      image_shape: A 1D int32 tensors of size [4] containing the image shape.
      **side_inputs: additional tensors that are required by the network.

    Returns:
      A float32 tensor with shape [K, new_height, new_width, depth].
    """
    num_levels = len(features_to_crop)
    box_levels = None
    if num_levels != 1:
      # If there are mutiple levels to select, get the box levels
      # unit_scale_index: num_levels-2 is chosen based on section 4.2 of
      # https://arxiv.org/pdf/1612.03144.pdf and works best for Resnet based
      # feature extractor.
      box_levels = ops.fpn_feature_levels(
          num_levels, num_levels - 2,
          tf.sqrt(
            tf.cast(image_shape[1] * image_shape[2], tf.float32)) / 224.0,
          proposal_boxes_normalized)

    cropped_regions = self._flatten_first_two_dimensions(
        self._crop_and_resize_fn(
            features_to_crop, proposal_boxes_normalized, box_levels,
            [self._initial_crop_size, self._initial_crop_size]))
    return self._maxpool_layer(cropped_regions)

  def _postprocess_box_classifier(self,
                                  refined_box_encodings,
                                  class_predictions_with_background,
                                  proposal_boxes,
                                  num_proposals,
                                  image_shapes,
                                  mask_predictions=None):
    """Converts predictions from the second stage box classifier to detections.

    Args:
      refined_box_encodings: a 3-D float tensor with shape
        [total_num_padded_proposals, num_classes, self._box_coder.code_size]
        representing predicted (final) refined box encodings. If using a shared
        box across classes the shape will instead be
        [total_num_padded_proposals, 1, 4]