コード例 #1
0
def concatenate(box_mask_lists, fields=None):
  """Concatenate list of box_mask_lists.

  This op concatenates a list of input box_mask_lists into a larger
  box_mask_list.  It also
  handles concatenation of box_mask_list fields as long as the field tensor
  shapes are equal except for the first dimension.

  Args:
    box_mask_lists: list of np_box_mask_list.BoxMaskList objects
    fields: optional list of fields to also concatenate.  By default, all
      fields from the first BoxMaskList in the list are included in the
      concatenation.

  Returns:
    a box_mask_list with number of boxes equal to
      sum([box_mask_list.num_boxes() for box_mask_list in box_mask_list])
  Raises:
    ValueError: if box_mask_lists is invalid (i.e., is not a list, is empty, or
      contains non box_mask_list objects), or if requested fields are not
      contained in all box_mask_lists
  """
  if fields is not None:
    if 'masks' not in fields:
      fields.append('masks')
  return box_list_to_box_mask_list(
      np_box_list_ops.concatenate(boxlists=box_mask_lists, fields=fields))
コード例 #2
0
    def concatenate(labels1, labels2):
        """Return concatenation of labels.

        Args:
            labels1: ObjectDetectionLabels
            labels2: ObjectDetectionLabels
        """
        from object_detection.utils.np_box_list_ops import concatenate

        new_boxlist = concatenate([labels1.to_boxlist(), labels2.to_boxlist()])
        return ObjectDetectionLabels.from_boxlist(new_boxlist)
コード例 #3
0
 def test_concatenate(self):
     boxlist1 = np_box_list.BoxList(
         np.array([[0.25, 0.25, 0.75, 0.75], [0.0, 0.0, 0.5, 0.75]],
                  dtype=np.float32))
     boxlist2 = np_box_list.BoxList(
         np.array([[0.5, 0.25, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]],
                  dtype=np.float32))
     boxlists = [boxlist1, boxlist2]
     boxlist_concatenated = np_box_list_ops.concatenate(boxlists)
     boxlist_concatenated_expected = np_box_list.BoxList(
         np.array([[0.25, 0.25, 0.75, 0.75], [0.0, 0.0, 0.5, 0.75],
                   [0.5, 0.25, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]],
                  dtype=np.float32))
     self.assertAllClose(boxlist_concatenated_expected.get(),
                         boxlist_concatenated.get())
コード例 #4
0
 def test_concatenate(self):
   boxlist1 = np_box_list.BoxList(
       np.array(
           [[0.25, 0.25, 0.75, 0.75], [0.0, 0.0, 0.5, 0.75]], dtype=
           np.float32))
   boxlist2 = np_box_list.BoxList(
       np.array(
           [[0.5, 0.25, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]], dtype=np.float32))
   boxlists = [boxlist1, boxlist2]
   boxlist_concatenated = np_box_list_ops.concatenate(boxlists)
   boxlist_concatenated_expected = np_box_list.BoxList(
       np.array(
           [[0.25, 0.25, 0.75, 0.75], [0.0, 0.0, 0.5, 0.75],
            [0.5, 0.25, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]],
           dtype=np.float32))
   self.assertAllClose(boxlist_concatenated_expected.get(),
                       boxlist_concatenated.get())
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 _merge_results(res0, res1=None, nms=False, max_proposal=50):
    res0 = dict(res0)

    had_scores = 'scores' in res0

    if not had_scores:
        res0['scores'] = np.zeros_like(res0['boxes'][..., 0])

    boxlist = _to_boxlist(res0)

    # Do the same thing to res1
    if res1 is not None:
        res1 = dict(res1)
        if not had_scores:
            res1['scores'] = np.zeros_like(res1['boxes'][..., 0])
        boxlist1 = _to_boxlist(res1)
        boxlist = concatenate([boxlist, boxlist1])

    if nms:
        boxlist = multi_class_non_max_suppression(boxlist,
                                                  score_thresh=-float('inf'),
                                                  iou_thresh=0.99,
                                                  max_output_size=max_proposal)

    res = boxlist.data

    if 'class_agnostic' in res0:
        res['class_agnostic'] = res0['class_agnostic']

    if 'groundtruth' in res0:
        if res1 is not None:
            assert (np.all([
                np.all(res0['groundtruth'][key] == res1['groundtruth'][key])
                for key in res0['groundtruth'].keys()
            ]))
        res['groundtruth'] = res0['groundtruth']

    if not had_scores:
        res.pop('scores')
    return res
コード例 #7
0
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
コード例 #8
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)