class_docstr: Assign object detection proposals to ground-truth targets. Produces proposal
  classification labels and bounding-box regression targets.
class_docstr_tok: ["Assign","object","detection","proposals","to","ground-truth","targets",".","Produces","proposal","classification","labels","and","bounding-box","regression","targets","."]
code: def forward(
      self, arguments, outputs, device=None, outputs_to_retain=None
  ):
      bottom = arguments
  
      # Proposal ROIs (0, x1, y1, x2, y2) coming from RPN
      # (i.e., rpn.proposal_layer.ProposalLayer), or any other source
      all_rois = bottom[0][0, :]
      # remove zero padded proposals
      keep0 = np.where(
          ((all_rois[:, 2] - all_rois[:, 0]) > 0)
          & ((all_rois[:, 3] - all_rois[:, 1]) > 0)
      )
      all_rois = all_rois[keep0]
  
      # GT boxes (x1, y1, x2, y2, label)
      # TODO(rbg): it's annoying that sometimes I have extra info before
      # and other times after box coordinates -- normalize to one format
      gt_boxes = bottom[1][0, :]
      # remove zero padded ground truth boxes
      keep1 = np.where(
          ((gt_boxes[:, 2] - gt_boxes[:, 0]) > 0)
          & ((gt_boxes[:, 3] - gt_boxes[:, 1]) > 0)
      )
      gt_boxes = gt_boxes[keep1]
  
      assert gt_boxes.shape[0] > 0, "No ground truth boxes provided"
  
      # Include ground-truth boxes in the set of candidate rois
      # for CNTK: add batch index axis with all zeros to both inputs
      all_rois = np.vstack((all_rois, gt_boxes[:, :-1]))
      zeros = np.zeros((all_rois.shape[0], 1), dtype=all_rois.dtype)
      all_rois = np.hstack((zeros, all_rois))
  
      # Sanity check: single batch only
      assert np.all(
          all_rois[:, 0] == 0
      ), "Only single item batches are supported"
  
      rois_per_image = self._batch_size
      fg_rois_per_image = np.round(
          self._fg_fraction * rois_per_image
      ).astype(int)
  
      # Sample rois with classification labels and bounding box regression
      # targets
      (
          labels,
          rois,
          bbox_targets,
          bbox_inside_weights,
      ) = self._sample_rois(
          all_rois,
          gt_boxes,
          fg_rois_per_image,
          rois_per_image,
          self._num_classes,
          deterministic=self._determininistic_mode,
      )
  
      if DEBUG:
          print("num rois: {}".format(rois_per_image))
          print("num fg: {}".format((labels > 0).sum()))
          print("num bg: {}".format((labels == 0).sum()))
          self._count += 1
          self._fg_num += (labels > 0).sum()
          self._bg_num += (labels == 0).sum()
          print("num fg avg: {}".format(self._fg_num / self._count))
          print("num bg avg: {}".format(self._bg_num / self._count))
          print(
              "ratio: {:.3f}".format(
                  float(self._fg_num) / float(self._bg_num)
              )
          )
  
      # pad with zeros if too few rois were found
      num_found_rois = rois.shape[0]
      if num_found_rois < rois_per_image:
          rois_padded = np.zeros(
              (rois_per_image, rois.shape[1]), dtype=np.float32
          )
          rois_padded[:num_found_rois, :] = rois
          rois = rois_padded
  
          labels_padded = np.zeros((rois_per_image), dtype=np.float32)
          labels_padded[:num_found_rois] = labels
          labels = labels_padded
  
          bbox_targets_padded = np.zeros(
              (rois_per_image, bbox_targets.shape[1]), dtype=np.float32
          )
          bbox_targets_padded[:num_found_rois, :] = bbox_targets
          bbox_targets = bbox_targets_padded
  
          bbox_inside_weights_padded = np.zeros(
              (rois_per_image, bbox_inside_weights.shape[1]),
              dtype=np.float32,
          )
          bbox_inside_weights_padded[
              :num_found_rois, :
          ] = bbox_inside_weights
          bbox_inside_weights = bbox_inside_weights_padded
  
      # for CNTK: get rid of batch ind zeros and add batch axis
      rois = rois[:, 1:]
  
      # sampled rois
      rois.shape = (1,) + rois.shape
      outputs[self.outputs[0]] = np.ascontiguousarray(rois)
  
      # classification labels
      labels_as_int = [i.item() for i in labels.astype(int)]
      labels_dense = np.eye(self._num_classes, dtype=np.float32)[
          labels_as_int
      ]
      labels_dense.shape = (1,) + labels_dense.shape  # batch axis
      outputs[self.outputs[1]] = labels_dense
  
      # bbox_targets
      bbox_targets.shape = (1,) + bbox_targets.shape  # batch axis
      outputs[self.outputs[2]] = np.ascontiguousarray(bbox_targets)
  
      # bbox_inside_weights
      bbox_inside_weights.shape = (
          1,
      ) + bbox_inside_weights.shape  # batch axis
      outputs[self.outputs[3]] = np.ascontiguousarray(
          bbox_inside_weights
      )
  
file_path: CNTK/Examples/Image/Detection/utils/rpn/proposal_target_layer.py
imports: from cntk import output_variable, FreeDimension
  from cntk.ops.functions import UserFunction
  import yaml
  import numpy
  import numpy.random
  from utils.rpn.bbox_transform import bbox_transform
  from utils.cython_modules.cython_bbox import bbox_overlaps
label_desc: Use image node_id 3 for calling the ProposalTargetLayer obj's underlying member method code with example usage: obj.forward(arguments, outputs, device, outputs_to_retain) without return types