docstr: Tests shapes are consistent with anchor generation.
          
code: def testBasic(self):
      """Tests shapes are consistent with anchor generation."""
      model = RPN(self.num_anchors, self.config, debug=True)
      # (plus the batch number)
      pretrained_output_shape = (1, 32, 32, 512)
      pretrained_output = tf.placeholder(
          tf.float32, shape=pretrained_output_shape
      )
  
      # Estimate image shape from the pretrained output and the anchor stride
      image_shape_val = (
          int(pretrained_output_shape[1] * self.stride),
          int(pretrained_output_shape[2] * self.stride),
      )
  
      # Use 4 ground truth boxes.
      gt_boxes_shape = (4, 4)
      gt_boxes = tf.placeholder(tf.float32, shape=gt_boxes_shape)
      image_shape_shape = (2,)
      image_shape = tf.placeholder(tf.float32, shape=image_shape_shape)
      # Total anchors depends on the pretrained output shape and the total
      # number of anchors per point.
      total_anchors = (
          pretrained_output_shape[1]
          * pretrained_output_shape[2]
          * self.num_anchors
      )
      all_anchors_shape = (total_anchors, 4)
      all_anchors = tf.placeholder(tf.float32, shape=all_anchors_shape)
      layers = model(
          pretrained_output, image_shape, all_anchors, gt_boxes=gt_boxes
      )
  
      with self.test_session() as sess:
          # As in the case of a real session we need to initialize the
          # variables.
          sess.run(tf.global_variables_initializer())
          layers_inst = sess.run(
              layers,
              feed_dict={
                  # We don't really care about the value of the pretrained output
                  # only that has the correct shape.
                  pretrained_output: np.random.rand(
                      *pretrained_output_shape
                  ),
                  # Generate random but valid ground truth boxes.
                  gt_boxes: generate_gt_boxes(
                      gt_boxes_shape[0], image_shape_val
                  ),
                  # Generate anchors from a reference and the shape of the
                  # pretrained_output.
                  all_anchors: generate_anchors(
                      generate_anchors_reference(
                          self.base_size, self.ratios, self.scales
                      ),
                      16,
                      pretrained_output_shape[1:3],
                  ),
                  image_shape: image_shape_val,
              },
          )
  
      # Class score generates 2 values per anchor.
      rpn_cls_score_shape = layers_inst["rpn_cls_score"].shape
      rpn_cls_score_true_shape = (total_anchors, 2)
      self.assertEqual(rpn_cls_score_shape, rpn_cls_score_true_shape)
  
      # Probs have the same shape as cls scores.
      rpn_cls_prob_shape = layers_inst["rpn_cls_prob"].shape
      self.assertEqual(rpn_cls_prob_shape, rpn_cls_score_true_shape)
  
      # We check softmax with the sum of the output.
      rpn_cls_prob_sum = layers_inst["rpn_cls_prob"].sum(axis=1)
      self.assertAllClose(rpn_cls_prob_sum, np.ones(total_anchors))
  
      # Proposals and scores are related to the output of the NMS with
      # limits.
      total_proposals = layers_inst["proposals"].shape[0]
      total_scores = layers_inst["scores"].shape[0]
  
      # Check we don't get more than top_n proposals.
      self.assertGreaterEqual(
          self.config.proposals.post_nms_top_n, total_proposals
      )
  
      # Check we get a score for each proposal.
      self.assertEqual(total_proposals, total_scores)
  
      # Check that we get a regression for each anchor.
      self.assertEqual(
          layers_inst["rpn_bbox_pred"].shape, (total_anchors, 4)
      )
  
      # Check that we get a target for each regression for each anchor.
      self.assertEqual(
          layers_inst["rpn_bbox_target"].shape, (total_anchors, 4)
      )
  
      # Check that we get a target class for each anchor.
      self.assertEqual(
          layers_inst["rpn_cls_target"].shape, (total_anchors,)
      )
  
      # Check that targets are composed of [-1, 0, 1] only.
      rpn_cls_target = layers_inst["rpn_cls_target"]
      self.assertEqual(
          tuple(np.sort(np.unique(rpn_cls_target))), (-1, 0.0, 1.0)
      )
  
      batch_cls_target = rpn_cls_target[
          (rpn_cls_target == 0.0) | (rpn_cls_target == 1.0)
      ]
  
      # Check that the non negative target class are exactly the size
      # as the minibatch
      self.assertEqual(
          batch_cls_target.shape, (self.config.target.minibatch_size,)
      )
  
      # Check that we get upto foreground_fraction of positive anchors.
      self.assertLessEqual(
          batch_cls_target[batch_cls_target == 1.0].shape[0]
          / batch_cls_target.shape[0],
          self.config.target.foreground_fraction,
      )
  
file_path: luminoth/luminoth/models/fasterrcnn/rpn_test.py
imports: import numpy
  import tensorflow
  from easydict import EasyDict
  from luminoth.models.fasterrcnn.rpn import RPN
  from luminoth.utils.anchors import generate_anchors_reference
  from luminoth.utils.test import generate_gt_boxes, generate_anchors
label_desc: Use image node_id 2 for calling the RPNTest obj's underlying member method code with example usage: obj.testBasic() without return types