code: def gt_anchor_matching(cf, anchors, gt_boxes, gt_class_ids=None):
      """Given the anchors and GT boxes, compute overlaps and identify positive
      anchors and deltas to refine them to match their corresponding GT boxes.
  
      anchors: [num_anchors, (y1, x1, y2, x2, (z1), (z2))]
      gt_boxes: [num_gt_boxes, (y1, x1, y2, x2, (z1), (z2))]
      gt_class_ids (optional): [num_gt_boxes] Integer class IDs for one stage detectors. in RPN case of Mask R-CNN,
      set all positive matches to 1 (foreground)
  
      Returns:
      anchor_class_matches: [N] (int32) matches between anchors and GT boxes.
                 1 = positive anchor, -1 = negative anchor, 0 = neutral.
                 In case of one stage detectors like RetinaNet/RetinaUNet this flag takes
                 class_ids as positive anchor values, i.e. values >= 1!
      anchor_delta_targets: [N, (dy, dx, (dz), log(dh), log(dw), (log(dd)))] Anchor bbox deltas.
      """
  
      anchor_class_matches = np.zeros(
          [anchors.shape[0]], dtype=np.int32
      )
      anchor_delta_targets = np.zeros(
          (cf.rpn_train_anchors_per_image, 2 * cf.dim)
      )
      anchor_matching_iou = cf.anchor_matching_iou
  
      if gt_boxes is None:
          anchor_class_matches = np.full(
              anchor_class_matches.shape, fill_value=-1
          )
          return anchor_class_matches, anchor_delta_targets
  
      # for mrcnn: anchor matching is done for RPN loss, so positive labels are all 1 (foreground)
      if gt_class_ids is None:
          gt_class_ids = np.array([1] * len(gt_boxes))
  
      # Compute overlaps [num_anchors, num_gt_boxes]
      overlaps = compute_overlaps(anchors, gt_boxes)
  
      # Match anchors to GT Boxes
      # If an anchor overlaps a GT box with IoU >= anchor_matching_iou then it's positive.
      # If an anchor overlaps a GT box with IoU < 0.1 then it's negative.
      # Neutral anchors are those that don't match the conditions above,
      # and they don't influence the loss function.
      # However, don't keep any GT box unmatched (rare, but happens). Instead,
      # match it to the closest anchor (even if its max IoU is < 0.1).
  
      # 1. Set negative anchors first. They get overwritten below if a GT box is
      # matched to them. Skip boxes in crowd areas.
      anchor_iou_argmax = np.argmax(overlaps, axis=1)
      anchor_iou_max = overlaps[
          np.arange(overlaps.shape[0]), anchor_iou_argmax
      ]
      if anchors.shape[1] == 4:
          anchor_class_matches[(anchor_iou_max < 0.1)] = -1
      elif anchors.shape[1] == 6:
          anchor_class_matches[(anchor_iou_max < 0.01)] = -1
      else:
          raise ValueError(
              "anchor shape wrong {}".format(anchors.shape)
          )
  
      # 2. Set an anchor for each GT box (regardless of IoU value).
      gt_iou_argmax = np.argmax(overlaps, axis=0)
      for ix, ii in enumerate(gt_iou_argmax):
          anchor_class_matches[ii] = gt_class_ids[ix]
  
      # 3. Set anchors with high overlap as positive.
      above_trhesh_ixs = np.argwhere(
          anchor_iou_max >= anchor_matching_iou
      )
      anchor_class_matches[above_trhesh_ixs] = gt_class_ids[
          anchor_iou_argmax[above_trhesh_ixs]
      ]
  
      # Subsample to balance positive anchors.
      ids = np.where(anchor_class_matches > 0)[0]
      extra = len(ids) - (cf.rpn_train_anchors_per_image // 2)
      if extra > 0:
          # Reset the extra ones to neutral
          ids = np.random.choice(ids, extra, replace=False)
          anchor_class_matches[ids] = 0
  
      # Leave all negative proposals negative now and sample from them in online hard example mining.
      # For positive anchors, compute shift and scale needed to transform them to match the corresponding GT boxes.
      ids = np.where(anchor_class_matches > 0)[0]
      ix = 0  # index into anchor_delta_targets
      for i, a in zip(ids, anchors[ids]):
          # closest gt box (it might have IoU < anchor_matching_iou)
          gt = gt_boxes[anchor_iou_argmax[i]]
  
          # convert coordinates to center plus width/height.
          gt_h = gt[2] - gt[0]
          gt_w = gt[3] - gt[1]
          gt_center_y = gt[0] + 0.5 * gt_h
          gt_center_x = gt[1] + 0.5 * gt_w
          # Anchor
          a_h = a[2] - a[0]
          a_w = a[3] - a[1]
          a_center_y = a[0] + 0.5 * a_h
          a_center_x = a[1] + 0.5 * a_w
  
          if cf.dim == 2:
              anchor_delta_targets[ix] = [
                  (gt_center_y - a_center_y) / a_h,
                  (gt_center_x - a_center_x) / a_w,
                  np.log(gt_h / a_h),
                  np.log(gt_w / a_w),
              ]
  
          else:
              gt_d = gt[5] - gt[4]
              gt_center_z = gt[4] + 0.5 * gt_d
              a_d = a[5] - a[4]
              a_center_z = a[4] + 0.5 * a_d
  
              anchor_delta_targets[ix] = [
                  (gt_center_y - a_center_y) / a_h,
                  (gt_center_x - a_center_x) / a_w,
                  (gt_center_z - a_center_z) / a_d,
                  np.log(gt_h / a_h),
                  np.log(gt_w / a_w),
                  np.log(gt_d / a_d),
              ]
  
          # normalize.
          anchor_delta_targets[ix] /= cf.rpn_bbox_std_dev
          ix += 1
  
      return anchor_class_matches, anchor_delta_targets
  
imports: import numpy
  import scipy.misc
  import scipy.ndimage
  import torch
  from torch.autograd import Variable
  import torch.nn
label_desc: Use image node_id 17 for calling a global function with example usage: gt_anchor_matching(cf, anchors, gt_boxes, gt_class_ids) and returns: anchor_class_matches,  anchor_delta_targets, anchor_class_matches,  anchor_delta_targets