class_docstr: The mapper to preprocess the input data for training.
  
  Since the mapping may run in other processes, we write a new class and
  explicitly pass cfg to it, in the spirit of "explicitly pass resources to subprocess".
class_docstr_tok: ["The","mapper","to","preprocess","the","input","data","for","training",".","Since","the","mapping","may","run","in","other","processes",",","we","write","a","new","class","and","explicitly","pass","cfg","to","it",",","in","the","spirit","of","``","explicitly","pass","resources","to","subprocess","''","."]
docstr: Label each anchor as fg/bg/ignore.
  Args:
      anchors: Ax4 float
      gt_boxes: Bx4 float, non-crowd
      crowd_boxes: Cx4 float
  
  Returns:
      anchor_labels: (A,) int. Each element is {-1, 0, 1}
      anchor_boxes: Ax4. Contains the target gt_box for each anchor when the anchor is fg.
docstr_tok: ["Label","each","anchor","as","fg\/bg\/ignore",".","Args",":","anchors",":","Ax4","float","gt_boxes",":","Bx4","float",",","non-crowd","crowd_boxes",":","Cx4","float","Returns",":","anchor_labels",":","(","A",",",")","int",".","Each","element","is","{","-1",",","0",",","1","}","anchor_boxes",":","Ax4",".","Contains","the","target","gt_box","for","each","anchor","when","the","anchor","is","fg","."]
code: def get_anchor_labels(self, anchors, gt_boxes, crowd_boxes):
      """
      Label each anchor as fg/bg/ignore.
      Args:
          anchors: Ax4 float
          gt_boxes: Bx4 float, non-crowd
          crowd_boxes: Cx4 float
  
      Returns:
          anchor_labels: (A,) int. Each element is {-1, 0, 1}
          anchor_boxes: Ax4. Contains the target gt_box for each anchor when the anchor is fg.
      """
  
      # This function will modify labels and return the filtered inds
      def filter_box_label(labels, value, max_num):
          curr_inds = np.where(labels == value)[0]
          if len(curr_inds) > max_num:
              disable_inds = np.random.choice(
                  curr_inds,
                  size=(len(curr_inds) - max_num),
                  replace=False,
              )
              labels[disable_inds] = -1  # ignore them
              curr_inds = np.where(labels == value)[0]
          return curr_inds
  
      NA, NB = len(anchors), len(gt_boxes)
      if NB == 0:
          # No groundtruth. All anchors are either background or ignored.
          anchor_labels = np.zeros((NA,), dtype="int32")
          filter_box_label(anchor_labels, 0, self.cfg.RPN.BATCH_PER_IM)
          return anchor_labels, np.zeros((NA, 4), dtype="float32")
  
      box_ious = np_iou(anchors, gt_boxes)  # NA x NB
      ious_argmax_per_anchor = box_ious.argmax(axis=1)  # NA,
      ious_max_per_anchor = box_ious.max(axis=1)
      ious_max_per_gt = np.amax(box_ious, axis=0, keepdims=True)  # 1xNB
      # for each gt, find all those anchors (including ties) that has the max ious with it
      anchors_with_max_iou_per_gt = np.where(
          box_ious == ious_max_per_gt
      )[0]
  
      # Setting NA labels: 1--fg 0--bg -1--ignore
      anchor_labels = -np.ones((NA,), dtype="int32")  # NA,
  
      # the order of setting neg/pos labels matter
      anchor_labels[anchors_with_max_iou_per_gt] = 1
      anchor_labels[
          ious_max_per_anchor >= self.cfg.RPN.POSITIVE_ANCHOR_THRESH
      ] = 1
      anchor_labels[
          ious_max_per_anchor < self.cfg.RPN.NEGATIVE_ANCHOR_THRESH
      ] = 0
  
      # label all non-ignore candidate boxes which overlap crowd as ignore
      if crowd_boxes.size > 0:
          cand_inds = np.where(anchor_labels >= 0)[0]
          cand_anchors = anchors[cand_inds]
          ioas = np_ioa(crowd_boxes, cand_anchors)
          overlap_with_crowd = cand_inds[
              ioas.max(axis=0) > self.cfg.RPN.CROWD_OVERLAP_THRESH
          ]
          anchor_labels[overlap_with_crowd] = -1
  
      # Subsample fg labels: ignore some fg if fg is too many
      target_num_fg = int(
          self.cfg.RPN.BATCH_PER_IM * self.cfg.RPN.FG_RATIO
      )
      fg_inds = filter_box_label(anchor_labels, 1, target_num_fg)
      # Keep an image even if there is no foreground anchors
      # if len(fg_inds) == 0:
      #     raise MalformedData("No valid foreground for RPN!")
  
      # Subsample bg labels. num_bg is not allowed to be too many
      old_num_bg = np.sum(anchor_labels == 0)
      if old_num_bg == 0:
          # No valid bg in this image, skip.
          raise MalformedData("No valid background for RPN!")
      target_num_bg = self.cfg.RPN.BATCH_PER_IM - len(fg_inds)
      filter_box_label(
          anchor_labels, 0, target_num_bg
      )  # ignore return values
  
      # Set anchor boxes: the best gt_box for each fg anchor
      anchor_boxes = np.zeros((NA, 4), dtype="float32")
      fg_boxes = gt_boxes[ious_argmax_per_anchor[fg_inds], :]
      anchor_boxes[fg_inds, :] = fg_boxes
      # assert len(fg_inds) + np.sum(anchor_labels == 0) == self.cfg.RPN.BATCH_PER_IM
      return anchor_labels, anchor_boxes
  
imports: import copy
  import itertools
  import numpy
  import cv2
  from tabulate import tabulate
  from termcolor import colored
  from tensorpack.dataflow import DataFromList, MapData, MapDataComponent, MultiProcessMapData, MultiThreadMapData, TestDataSpeed, imgaug
  from tensorpack.utils import logger
  from tensorpack.utils.argtools import log_once
  from modeling.model_rpn import get_all_anchors
  from modeling.model_fpn import get_all_anchors_fpn
  from common import CustomResize, DataFromListOfDict, box_to_point4, filter_boxes_inside_shape, np_iou, point4_to_box, polygons_to_mask
  from config import config
  from dataset import DatasetRegistry, register_coco
  from utils.np_box_ops import area
  from utils.np_box_ops import ioa
label_desc: Use image node_id 5 for calling the TrainingDataPreprocessor obj's underlying member method code with example usage: obj.get_anchor_labels(anchors, gt_boxes, crowd_boxes) and returns: anchor_labels,  anchor_boxes, curr_inds, anchor_labels,  np