def test_with_descending_sorting(self):
    sorted_boxlist = np_box_list_ops.sort_by_field(self.boxlist, 'scores')

    expected_boxes = np.array([[14.0, 14.0, 15.0, 15.0], [3.0, 4.0, 6.0, 8.0],
                               [0.0, 0.0, 20.0, 20.0]],
                              dtype=float)
    self.assertAllClose(expected_boxes, sorted_boxlist.get())

    expected_scores = np.array([0.9, 0.5, 0.4], dtype=float)
    self.assertAllClose(expected_scores, sorted_boxlist.get_field('scores'))
Exemple #2
0
  def test_with_descending_sorting(self):
    sorted_boxlist = np_box_list_ops.sort_by_field(self.boxlist, 'scores')

    expected_boxes = np.array([[14.0, 14.0, 15.0, 15.0], [3.0, 4.0, 6.0, 8.0],
                               [0.0, 0.0, 20.0, 20.0]],
                              dtype=float)
    self.assertAllClose(expected_boxes, sorted_boxlist.get())

    expected_scores = np.array([0.9, 0.5, 0.4], dtype=float)
    self.assertAllClose(expected_scores, sorted_boxlist.get_field('scores'))
Exemple #3
0
def sort_by_field(box_mask_list, field,
                  order=np_box_list_ops.SortOrder.DESCEND):
  """Sort boxes and associated fields according to a scalar field.

  A common use case is reordering the boxes according to descending scores.

  Args:
    box_mask_list: BoxMaskList holding N boxes.
    field: A BoxMaskList field for sorting and reordering the BoxMaskList.
    order: (Optional) 'descend' or 'ascend'. Default is descend.

  Returns:
    sorted_box_mask_list: A sorted BoxMaskList with the field in the specified
      order.
  """
  return box_list_to_box_mask_list(
      np_box_list_ops.sort_by_field(
          boxlist=box_mask_list, field=field, order=order))
    def _get_overlaps_and_scores_relation_tuples(self, detected_box_tuples,
                                                 detected_scores,
                                                 groundtruth_box_tuples):
        """Computes overlaps and scores between detected and groundtruth tuples.

    Both detections and groundtruth boxes have the same class tuples.

    Args:
      detected_box_tuples: A numpy array of structures with shape [N,],
          representing N tuples, each tuple containing the same number of named
          bounding boxes.
          Each box is of the format [y_min, x_min, y_max, x_max]
      detected_scores: A float numpy array of shape [N,], representing
          the confidence scores of the detected N object instances.
      groundtruth_box_tuples: A float numpy array of structures with the shape
          [M,], representing M tuples, each tuple containing the same number
          of named bounding boxes.
          Each box is of the format [y_min, x_min, y_max, x_max]

    Returns:
      result_iou: A float numpy array of size
        [num_detected_tuples, num_gt_box_tuples].
      scores: The score of the detected boxlist.
    """

        result_iou = np.ones(
            (detected_box_tuples.shape[0], groundtruth_box_tuples.shape[0]),
            dtype=float)
        for field in detected_box_tuples.dtype.fields:
            detected_boxlist_field = np_box_list.BoxList(
                detected_box_tuples[field])
            detected_boxlist_field.add_field('scores', detected_scores)
            detected_boxlist_field = np_box_list_ops.sort_by_field(
                detected_boxlist_field, 'scores')
            gt_boxlist_field = np_box_list.BoxList(
                groundtruth_box_tuples[field])
            iou_field = np_box_list_ops.iou(detected_boxlist_field,
                                            gt_boxlist_field)
            result_iou = np.minimum(iou_field, result_iou)
        scores = detected_boxlist_field.get_field('scores')
        return result_iou, scores
def multi_class_non_max_suppression(boxlist, score_thresh, iou_thresh,
                                    max_output_size):
    if not 0 <= iou_thresh <= 1.0:
        raise ValueError('thresh must be between 0 and 1')
    scores = boxlist.get_field('scores')
    classes = boxlist.get_field('classes')
    num_boxes = boxlist.num_boxes()

    selected_boxes_list = []
    for cls in np.unique(classes):
        inds = np.where(cls == classes)[0]
        subboxlist = gather(boxlist, inds)
        boxlist_filt = filter_scores_greater_than(subboxlist, score_thresh)
        nms_result = non_max_suppression(boxlist_filt,
                                         max_output_size=max_output_size,
                                         iou_threshold=iou_thresh,
                                         score_threshold=score_thresh)
        selected_boxes_list.append(nms_result)
    selected_boxes = concatenate(selected_boxes_list)
    sorted_boxes = sort_by_field(selected_boxes, 'scores')
    return sorted_boxes
def multi_class_non_max_suppression_with_extra_fields(
        boxlist: BoxList, score_thresh: float, iou_thresh: float,
        max_output_size: int) -> BoxList:
    """
    Is the same method as
    `object_detection.utils.np_box_list_ops.multi_class_non_max_suppression`
    but also preserves all the extra fields of the boxlist after nms
    """
    # Modification: omit all the assertions
    # End of modification
    scores = boxlist.get_field('scores')
    num_scores = scores.shape[0]
    num_classes = scores.shape[1]
    selected_boxes_list = []
    for class_idx in range(num_classes):
        boxlist_and_class_scores = np_box_list.BoxList(boxlist.get())
        class_scores = np.reshape(scores[0:num_scores, class_idx], [-1])
        boxlist_and_class_scores.add_field('scores', class_scores)
        # Modification: add extra fields to boxlist_and_class_scores
        for each_extra_field in boxlist.get_extra_fields():
            if (not boxlist_and_class_scores.has_field(each_extra_field)
                    and each_extra_field != "classes"):
                boxlist_and_class_scores.add_field(
                    each_extra_field, boxlist.get_field(each_extra_field))
        # End of modification
        boxlist_filt = np_box_list_ops.filter_scores_greater_than(
            boxlist_and_class_scores, score_thresh)
        nms_result = np_box_list_ops.non_max_suppression(
            boxlist_filt,
            max_output_size=max_output_size,
            iou_threshold=iou_thresh,
            score_threshold=score_thresh)
        nms_result.add_field(
            'classes',
            np.zeros_like(nms_result.get_field('scores')) + class_idx)
        selected_boxes_list.append(nms_result)
    selected_boxes = np_box_list_ops.concatenate(selected_boxes_list)
    sorted_boxes = np_box_list_ops.sort_by_field(selected_boxes, 'scores')
    return sorted_boxes
  def _get_overlaps_and_scores_relation_tuples(
      self, detected_box_tuples, detected_scores, groundtruth_box_tuples):
    """Computes overlaps and scores between detected and groundtruth tuples.

    Both detections and groundtruth boxes have the same class tuples.

    Args:
      detected_box_tuples: A numpy array of structures with shape [N,],
          representing N tuples, each tuple containing the same number of named
          bounding boxes.
          Each box is of the format [y_min, x_min, y_max, x_max]
      detected_scores: A float numpy array of shape [N,], representing
          the confidence scores of the detected N object instances.
      groundtruth_box_tuples: A float numpy array of structures with the shape
          [M,], representing M tuples, each tuple containing the same number
          of named bounding boxes.
          Each box is of the format [y_min, x_min, y_max, x_max]

    Returns:
      result_iou: A float numpy array of size
        [num_detected_tuples, num_gt_box_tuples].
      scores: The score of the detected boxlist.
    """

    result_iou = np.ones(
        (detected_box_tuples.shape[0], groundtruth_box_tuples.shape[0]),
        dtype=float)
    for field in detected_box_tuples.dtype.fields:
      detected_boxlist_field = np_box_list.BoxList(detected_box_tuples[field])
      detected_boxlist_field.add_field('scores', detected_scores)
      detected_boxlist_field = np_box_list_ops.sort_by_field(
          detected_boxlist_field, 'scores')
      gt_boxlist_field = np_box_list.BoxList(groundtruth_box_tuples[field])
      iou_field = np_box_list_ops.iou(detected_boxlist_field, gt_boxlist_field)
      result_iou = np.minimum(iou_field, result_iou)
    scores = detected_boxlist_field.get_field('scores')
    return result_iou, scores
Exemple #8
0
 def test_with_invalid_sorting_order(self):
   with self.assertRaises(ValueError):
     np_box_list_ops.sort_by_field(self.boxlist, 'scores', 'Descending')
Exemple #9
0
 def test_with_invalid_field(self):
   with self.assertRaises(ValueError):
     np_box_list_ops.sort_by_field(self.boxlist, 'objectness')
   with self.assertRaises(ValueError):
     np_box_list_ops.sort_by_field(self.boxlist, 'labels')
Exemple #10
0
def multi_class_non_max_suppression(box_mask_list, score_thresh, iou_thresh,
                                    max_output_size):
  """Multi-class version of non maximum suppression.

  This op greedily selects a subset of detection bounding boxes, pruning
  away boxes that have high IOU (intersection over union) overlap (> thresh)
  with already selected boxes.  It operates independently for each class for
  which scores are provided (via the scores field of the input box_list),
  pruning boxes with score less than a provided threshold prior to
  applying NMS.

  Args:
    box_mask_list: np_box_mask_list.BoxMaskList holding N boxes.  Must contain a
      'scores' field representing detection scores.  This scores field is a
      tensor that can be 1 dimensional (in the case of a single class) or
      2-dimensional, in which case we assume that it takes the
      shape [num_boxes, num_classes]. We further assume that this rank is known
      statically and that scores.shape[1] is also known (i.e., the number of
      classes is fixed and known at graph construction time).
    score_thresh: scalar threshold for score (low scoring boxes are removed).
    iou_thresh: scalar threshold for IOU (boxes that that high IOU overlap
      with previously selected boxes are removed).
    max_output_size: maximum number of retained boxes per class.

  Returns:
    a box_mask_list holding M boxes with a rank-1 scores field representing
      corresponding scores for each box with scores sorted in decreasing order
      and a rank-1 classes field representing a class label for each box.
  Raises:
    ValueError: if iou_thresh is not in [0, 1] or if input box_mask_list does
      not have a valid scores field.
  """
  if not 0 <= iou_thresh <= 1.0:
    raise ValueError('thresh must be between 0 and 1')
  if not isinstance(box_mask_list, np_box_mask_list.BoxMaskList):
    raise ValueError('box_mask_list must be a box_mask_list')
  if not box_mask_list.has_field('scores'):
    raise ValueError('input box_mask_list must have \'scores\' field')
  scores = box_mask_list.get_field('scores')
  if len(scores.shape) == 1:
    scores = np.reshape(scores, [-1, 1])
  elif len(scores.shape) == 2:
    if scores.shape[1] is None:
      raise ValueError('scores field must have statically defined second '
                       'dimension')
  else:
    raise ValueError('scores field must be of rank 1 or 2')

  num_boxes = box_mask_list.num_boxes()
  num_scores = scores.shape[0]
  num_classes = scores.shape[1]

  if num_boxes != num_scores:
    raise ValueError('Incorrect scores field length: actual vs expected.')

  selected_boxes_list = []
  for class_idx in range(num_classes):
    box_mask_list_and_class_scores = np_box_mask_list.BoxMaskList(
        box_data=box_mask_list.get(),
        mask_data=box_mask_list.get_masks())
    class_scores = np.reshape(scores[0:num_scores, class_idx], [-1])
    box_mask_list_and_class_scores.add_field('scores', class_scores)
    box_mask_list_filt = filter_scores_greater_than(
        box_mask_list_and_class_scores, score_thresh)
    nms_result = non_max_suppression(
        box_mask_list_filt,
        max_output_size=max_output_size,
        iou_threshold=iou_thresh,
        score_threshold=score_thresh)
    nms_result.add_field(
        'classes',
        np.zeros_like(nms_result.get_field('scores')) + class_idx)
    selected_boxes_list.append(nms_result)
  selected_boxes = np_box_list_ops.concatenate(selected_boxes_list)
  sorted_boxes = np_box_list_ops.sort_by_field(selected_boxes, 'scores')
  return box_list_to_box_mask_list(boxlist=sorted_boxes)
 def test_with_invalid_sorting_order(self):
   with self.assertRaises(ValueError):
     np_box_list_ops.sort_by_field(self.boxlist, 'scores', 'Descending')
 def test_with_invalid_field(self):
   with self.assertRaises(ValueError):
     np_box_list_ops.sort_by_field(self.boxlist, 'objectness')
   with self.assertRaises(ValueError):
     np_box_list_ops.sort_by_field(self.boxlist, 'labels')