Beispiel #1
0
    def _compute_is_class_correctly_detected_in_image(self,
                                                      detected_boxes,
                                                      detected_scores,
                                                      groundtruth_boxes,
                                                      detected_masks=None,
                                                      groundtruth_masks=None):
        """Compute CorLoc score for a single class.

    Args:
      detected_boxes: A numpy array of shape [N, 4] representing detected box
          coordinates
      detected_scores: A 1-d numpy array of length N representing classification
          score
      groundtruth_boxes: A numpy array of shape [M, 4] representing ground truth
          box coordinates
      detected_masks: (optional) A np.uint8 numpy array of shape
        [N, height, width]. If not None, the scores will be computed based
        on masks.
      groundtruth_masks: (optional) A np.uint8 numpy array of shape
        [M, height, width].

    Returns:
      is_class_correctly_detected_in_image: An integer 1 or 0 denoting whether a
          class is correctly detected in the image or not
    """
        if detected_boxes.size > 0:
            if groundtruth_boxes.size > 0:
                max_score_id = np.argmax(detected_scores)
                mask_mode = False
                if detected_masks is not None and groundtruth_masks is not None:
                    mask_mode = True
                if mask_mode:
                    detected_boxlist = np_box_mask_list.BoxMaskList(
                        box_data=np.expand_dims(detected_boxes[max_score_id],
                                                axis=0),
                        mask_data=np.expand_dims(detected_masks[max_score_id],
                                                 axis=0))
                    gt_boxlist = np_box_mask_list.BoxMaskList(
                        box_data=groundtruth_boxes,
                        mask_data=groundtruth_masks)
                    iou = np_box_mask_list_ops.iou(detected_boxlist,
                                                   gt_boxlist)
                else:
                    detected_boxlist = np_box_list.BoxList(
                        np.expand_dims(detected_boxes[max_score_id, :],
                                       axis=0))
                    gt_boxlist = np_box_list.BoxList(groundtruth_boxes)
                    iou = np_box_list_ops.iou(detected_boxlist, gt_boxlist)
                if np.max(iou) >= self.matching_iou_threshold:
                    return 1
        return 0
Beispiel #2
0
    def _get_overlaps_and_scores_mask_mode(self, detected_boxes,
                                           detected_scores, detected_masks,
                                           groundtruth_boxes,
                                           groundtruth_masks,
                                           groundtruth_is_group_of_list):
        """Computes overlaps and scores between detected and groudntruth masks.

    Args:
      detected_boxes: A numpy array of shape [N, 4] representing detected box
          coordinates
      detected_scores: A 1-d numpy array of length N representing classification
          score
      detected_masks: A uint8 numpy array of shape [N, height, width]. If not
          None, the scores will be computed based on masks.
      groundtruth_boxes: A numpy array of shape [M, 4] representing ground truth
          box coordinates
      groundtruth_masks: A uint8 numpy array of shape [M, height, width].
      groundtruth_is_group_of_list: A boolean numpy array of length M denoting
          whether a ground truth box has group-of tag. If a groundtruth box
          is group-of box, every detection matching this box is ignored.

    Returns:
      iou: A float numpy array of size [num_detected_boxes, num_gt_boxes]. If
          gt_non_group_of_boxlist.num_boxes() == 0 it will be None.
      ioa: A float numpy array of size [num_detected_boxes, num_gt_boxes]. If
          gt_group_of_boxlist.num_boxes() == 0 it will be None.
      scores: The score of the detected boxlist.
      num_boxes: Number of non-maximum suppressed detected boxes.
    """
        detected_boxlist = np_box_mask_list.BoxMaskList(
            box_data=detected_boxes, mask_data=detected_masks)
        detected_boxlist.add_field('scores', detected_scores)
        detected_boxlist = np_box_mask_list_ops.non_max_suppression(
            detected_boxlist, self.nms_max_output_boxes,
            self.nms_iou_threshold)
        gt_non_group_of_boxlist = np_box_mask_list.BoxMaskList(
            box_data=groundtruth_boxes[~groundtruth_is_group_of_list],
            mask_data=groundtruth_masks[~groundtruth_is_group_of_list])
        gt_group_of_boxlist = np_box_mask_list.BoxMaskList(
            box_data=groundtruth_boxes[groundtruth_is_group_of_list],
            mask_data=groundtruth_masks[groundtruth_is_group_of_list])
        iou = np_box_mask_list_ops.iou(detected_boxlist,
                                       gt_non_group_of_boxlist)
        ioa = np.transpose(
            np_box_mask_list_ops.ioa(gt_group_of_boxlist, detected_boxlist))
        scores = detected_boxlist.get_field('scores')
        num_boxes = detected_boxlist.num_boxes()
        return iou, ioa, scores, num_boxes
Beispiel #3
0
def box_list_to_box_mask_list(boxlist):
  """Converts a BoxList containing 'masks' into a BoxMaskList.

  Args:
    boxlist: An np_box_list.BoxList object.

  Returns:
    An np_box_mask_list.BoxMaskList object.

  Raises:
    ValueError: If boxlist does not contain `masks` as a field.
  """
  if not boxlist.has_field('masks'):
    raise ValueError('boxlist does not contain mask field.')
  box_mask_list = np_box_mask_list.BoxMaskList(
      box_data=boxlist.get(),
      mask_data=boxlist.get_field('masks'))
  extra_fields = boxlist.get_extra_fields()
  for key in extra_fields:
    if key != 'masks':
      box_mask_list.data[key] = boxlist.get_field(key)
  return box_mask_list
Beispiel #4
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)