code: def sample_fast_rcnn_targets(boxes, gt_boxes, gt_labels):
      """
      Sample some boxes from all proposals for training.
      #fg is guaranteed to be > 0, because ground truth boxes will be added as proposals.
  
      Args:
          boxes: nx4 region proposals, floatbox
          gt_boxes: mx4, floatbox
          gt_labels: m, int32
  
      Returns:
          A BoxProposals instance, with:
              sampled_boxes: tx4 floatbox, the rois
              sampled_labels: t int64 labels, in [0, #class). Positive means foreground.
              fg_inds_wrt_gt: #fg indices, each in range [0, m-1].
                  It contains the matching GT of each foreground roi.
      """
      iou = pairwise_iou(boxes, gt_boxes)  # nxm
      proposal_metrics(iou)
  
      # add ground truth as proposals as well
      boxes = tf.concat([boxes, gt_boxes], axis=0)  # (n+m) x 4
      iou = tf.concat(
          [iou, tf.eye(tf.shape(gt_boxes)[0])], axis=0
      )  # (n+m) x m
      # #proposal=n+m from now on
  
      def sample_fg_bg(iou):
          fg_mask = tf.cond(
              tf.shape(iou)[1] > 0,
              lambda: tf.reduce_max(iou, axis=1) >= cfg.FRCNN.FG_THRESH,
              lambda: tf.zeros(tf.shape(iou)[0], dtype=tf.bool),
          )
  
          fg_inds = tf.reshape(tf.where(fg_mask), [-1])
          num_fg = tf.minimum(
              int(cfg.FRCNN.BATCH_PER_IM * cfg.FRCNN.FG_RATIO),
              tf.size(fg_inds),
              name="num_fg",
          )
          fg_inds = tf.random.shuffle(fg_inds)[:num_fg]
  
          bg_inds = tf.reshape(tf.where(tf.logical_not(fg_mask)), [-1])
          num_bg = tf.minimum(
              cfg.FRCNN.BATCH_PER_IM - num_fg,
              tf.size(bg_inds),
              name="num_bg",
          )
          bg_inds = tf.random.shuffle(bg_inds)[:num_bg]
  
          add_moving_summary(num_fg, num_bg)
          return fg_inds, bg_inds
  
      fg_inds, bg_inds = sample_fg_bg(iou)
      # fg,bg indices w.r.t proposals
  
      best_iou_ind = tf.cond(
          tf.shape(iou)[1] > 0,
          lambda: tf.argmax(iou, axis=1),  # #proposal, each in 0~m-1
          lambda: tf.zeros(tf.shape(iou)[0], dtype=tf.int64),
      )
      fg_inds_wrt_gt = tf.gather(best_iou_ind, fg_inds)  # num_fg
  
      all_indices = tf.concat(
          [fg_inds, bg_inds], axis=0
      )  # indices w.r.t all n+m proposal boxes
      ret_boxes = tf.gather(boxes, all_indices)
  
      ret_labels = tf.concat(
          [
              tf.gather(gt_labels, fg_inds_wrt_gt),
              tf.zeros_like(bg_inds, dtype=tf.int64),
          ],
          axis=0,
      )
      # stop the gradient -- they are meant to be training targets
      return BoxProposals(
          tf.stop_gradient(ret_boxes, name="sampled_proposal_boxes"),
          tf.stop_gradient(ret_labels, name="sampled_labels"),
          tf.stop_gradient(fg_inds_wrt_gt),
      )
  
imports: import tensorflow
  from tensorpack import tfv1
  from tensorpack.models import Conv2D, FullyConnected, layer_register
  from tensorpack.tfutils.argscope import argscope
  from tensorpack.tfutils.scope_utils import under_name_scope
  from tensorpack.tfutils.summary import add_moving_summary
  from tensorpack.utils.argtools import memoized_method
  from config import config
  from utils.box_ops import pairwise_iou
  from .model_box import decode_bbox_target, encode_bbox_target
  from .backbone import GroupNorm
label_desc: Use image node_id 2 for calling a global function with example usage: sample_fast_rcnn_targets(boxes, gt_boxes, gt_labels) and returns: BoxProposals, fg_inds,  bg_inds