def _compute_is_aclass_correctly_detected_in_image(self, detected_boxes, detected_scores, groundtruth_boxes): """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 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) 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
def evaluate_instance_motions(gt_boxes, gt_motions, detected_boxes, detected_motions, matching_iou_threshold=.5): gt_boxlist = np_box_list.BoxList(gt_boxes) detected_boxlist = np_box_list.BoxList(detected_boxes) iou = np_box_list_ops.iou(detected_boxlist, gt_boxlist) max_overlap_gt_ids = np.argmax(iou, axis=1) pred_list = [] target_list = [] for i in range(detected_boxlist.num_boxes()): gt_id = max_overlap_gt_ids[i] if iou[i, gt_id] >= matching_iou_threshold: pred_list.append(detected_motions[i, :]) target_list.append(gt_motions[gt_id, :]) if len(pred_list) == 0: return { 'mAngle': 0, 'mTrans': 0, 'mPivot': 0, # 'mRelAngle': 0, # 'mRelTrans': 0, 'mAveAngle': 0, 'mAveTrans': 0 } pred = np.stack(pred_list, axis=0) target = np.stack(target_list, axis=0) return _motion_errors(pred, target)
def _get_overlaps_and_scores_relation_tuples(self, detected_box_tuples, 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] 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]. """ 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]) 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) return result_iou
def _compute_is_aclass_correctly_detected_in_image( self, detected_boxes, detected_scores, groundtruth_boxes): """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 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) 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
def _get_overlaps_and_scores_relation_tuples(self, detected_box_tuples, 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] 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]. """ 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]) 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) return result_iou
def _compute_tp_fp_for_single_class(self, detected_boxes, detected_scores, groundtruth_boxes, groundtruth_is_difficult_list): """Labels boxes detected with the same class from the same image as tp/fp. 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 groundtruth_is_difficult_list: A boolean numpy array of length M denoting whether a ground truth box is a difficult instance or not Returns: scores: A numpy array representing the detection scores tp_fp_labels: a boolean numpy array indicating whether a detection is a true positive. """ if detected_boxes.size == 0: return np.array([], dtype=float), np.array([], dtype=bool) detected_boxlist = np_box_list.BoxList(detected_boxes) detected_boxlist.add_field('scores', detected_scores) detected_boxlist = np_box_list_ops.non_max_suppression( detected_boxlist, self.nms_max_output_boxes, self.nms_iou_threshold) scores = detected_boxlist.get_field('scores') if groundtruth_boxes.size == 0: return scores, np.zeros(detected_boxlist.num_boxes(), dtype=bool) gt_boxlist = np_box_list.BoxList(groundtruth_boxes) iou = np_box_list_ops.iou(detected_boxlist, gt_boxlist) max_overlap_gt_ids = np.argmax(iou, axis=1) is_gt_box_detected = np.zeros(gt_boxlist.num_boxes(), dtype=bool) tp_fp_labels = np.zeros(detected_boxlist.num_boxes(), dtype=bool) is_matched_to_difficult_box = np.zeros(detected_boxlist.num_boxes(), dtype=bool) for i in range(detected_boxlist.num_boxes()): gt_id = max_overlap_gt_ids[i] if iou[i, gt_id] >= self.matching_iou_threshold: if not groundtruth_is_difficult_list[gt_id]: if not is_gt_box_detected[gt_id]: tp_fp_labels[i] = True is_gt_box_detected[gt_id] = True else: is_matched_to_difficult_box[i] = True return scores[~is_matched_to_difficult_box], tp_fp_labels[ ~is_matched_to_difficult_box]
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
def _compute_tp_fp_for_single_class(self, detected_boxes, detected_scores, groundtruth_boxes, groundtruth_is_difficult_list): """Labels boxes detected with the same class from the same image as tp/fp. 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 groundtruth_is_difficult_list: A boolean numpy array of length M denoting whether a ground truth box is a difficult instance or not Returns: scores: A numpy array representing the detection scores tp_fp_labels: a boolean numpy array indicating whether a detection is a true positive. """ if detected_boxes.size == 0: return np.array([], dtype=float), np.array([], dtype=bool) detected_boxlist = np_box_list.BoxList(detected_boxes) detected_boxlist.add_field('scores', detected_scores) detected_boxlist = np_box_list_ops.non_max_suppression( detected_boxlist, self.nms_max_output_boxes, self.nms_iou_threshold) scores = detected_boxlist.get_field('scores') if groundtruth_boxes.size == 0: return scores, np.zeros(detected_boxlist.num_boxes(), dtype=bool) gt_boxlist = np_box_list.BoxList(groundtruth_boxes) iou = np_box_list_ops.iou(detected_boxlist, gt_boxlist) max_overlap_gt_ids = np.argmax(iou, axis=1) is_gt_box_detected = np.zeros(gt_boxlist.num_boxes(), dtype=bool) tp_fp_labels = np.zeros(detected_boxlist.num_boxes(), dtype=bool) is_matched_to_difficult_box = np.zeros( detected_boxlist.num_boxes(), dtype=bool) for i in range(detected_boxlist.num_boxes()): gt_id = max_overlap_gt_ids[i] if iou[i, gt_id] >= self.matching_iou_threshold: if not groundtruth_is_difficult_list[gt_id]: if not is_gt_box_detected[gt_id]: tp_fp_labels[i] = True is_gt_box_detected[gt_id] = True else: is_matched_to_difficult_box[i] = True return scores[~is_matched_to_difficult_box], tp_fp_labels[ ~is_matched_to_difficult_box]
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
def _get_overlaps_and_scores_box_mode(self, detected_boxes, detected_scores, groundtruth_boxes, groundtruth_is_group_of_list): """Computes overlaps and scores between detected and groudntruth boxes. 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 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_list.BoxList(detected_boxes) #print(detected_boxes) #print('no of detected boxes22', len(detected_boxes)) #print('detected_boxlist size', detected_boxlist.num_boxes()) #print('detected_boxlist.data',detected_boxlist.data['boxes']) detected_boxlist.add_field('scores', detected_scores) detected_boxlist = np_box_list_ops.non_max_suppression( detected_boxlist, self.nms_max_output_boxes, 0.5) #print('detected_boxlist size after nms', detected_boxlist.num_boxes()) gt_non_group_of_boxlist = np_box_list.BoxList( groundtruth_boxes[~groundtruth_is_group_of_list]) gt_group_of_boxlist = np_box_list.BoxList( groundtruth_boxes[groundtruth_is_group_of_list]) iou = np_box_list_ops.iou(detected_boxlist, gt_non_group_of_boxlist) ioa = np.transpose( np_box_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
def _get_overlaps_and_scores_box_mode( self, detected_boxes, detected_scores, groundtruth_boxes, groundtruth_is_group_of_list): """Computes overlaps and scores between detected and groudntruth boxes. 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 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_list.BoxList(detected_boxes) detected_boxlist.add_field('scores', detected_scores) detected_boxlist = np_box_list_ops.non_max_suppression( detected_boxlist, self.nms_max_output_boxes, self.nms_iou_threshold) gt_non_group_of_boxlist = np_box_list.BoxList( groundtruth_boxes[~groundtruth_is_group_of_list]) gt_group_of_boxlist = np_box_list.BoxList( groundtruth_boxes[groundtruth_is_group_of_list]) iou = np_box_list_ops.iou(detected_boxlist, gt_non_group_of_boxlist) ioa = np.transpose( np_box_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
def test_iou(self): iou = np_box_list_ops.iou(self.boxlist1, self.boxlist2) expected_iou = np.array([[2.0 / 16.0, 0.0, 6.0 / 400.0], [1.0 / 16.0, 0.0, 5.0 / 400.0]], dtype=float) self.assertAllClose(iou, expected_iou)
def _compute_tp_fp_for_single_class(self, detected_boxes, detected_scores, groundtruth_boxes, groundtruth_is_difficult_list, groundtruth_is_group_of_list): """Labels boxes detected with the same class from the same image as tp/fp. 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 groundtruth_is_difficult_list: A boolean numpy array of length M denoting whether a ground truth box is a difficult instance or not. If a groundtruth box is difficult, every detection matching this box is ignored. 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: Two arrays of the same size, containing all boxes that were evaluated as being true positives or false positives; if a box matched to a difficult box or to a group-of box, it is ignored. scores: A numpy array representing the detection scores. tp_fp_labels: a boolean numpy array indicating whether a detection is a true positive. """ if detected_boxes.size == 0: return np.array([], dtype=float), np.array([], dtype=bool) detected_boxlist = np_box_list.BoxList(detected_boxes) detected_boxlist.add_field('scores', detected_scores) detected_boxlist = np_box_list_ops.non_max_suppression( detected_boxlist, self.nms_max_output_boxes, self.nms_iou_threshold) scores = detected_boxlist.get_field('scores') if groundtruth_boxes.size == 0: return scores, np.zeros(detected_boxlist.num_boxes(), dtype=bool) tp_fp_labels = np.zeros(detected_boxlist.num_boxes(), dtype=bool) is_matched_to_difficult_box = np.zeros(detected_boxlist.num_boxes(), dtype=bool) is_matched_to_group_of_box = np.zeros(detected_boxlist.num_boxes(), dtype=bool) # The evaluation is done in two stages: # 1. All detections are matched to non group-of boxes; true positives are # determined and detections matched to difficult boxes are ignored. # 2. Detections that are determined as false positives are matched against # group-of boxes and ignored if matched. # Tp-fp evaluation for non-group of boxes (if any). gt_non_group_of_boxlist = np_box_list.BoxList( groundtruth_boxes[~groundtruth_is_group_of_list, :]) if gt_non_group_of_boxlist.num_boxes() > 0: groundtruth_nongroup_of_is_difficult_list = groundtruth_is_difficult_list[ ~groundtruth_is_group_of_list] iou = np_box_list_ops.iou(detected_boxlist, gt_non_group_of_boxlist) max_overlap_gt_ids = np.argmax(iou, axis=1) is_gt_box_detected = np.zeros(gt_non_group_of_boxlist.num_boxes(), dtype=bool) for i in range(detected_boxlist.num_boxes()): gt_id = max_overlap_gt_ids[i] if iou[i, gt_id] >= self.matching_iou_threshold: if not groundtruth_nongroup_of_is_difficult_list[gt_id]: if not is_gt_box_detected[gt_id]: tp_fp_labels[i] = True is_gt_box_detected[gt_id] = True else: is_matched_to_difficult_box[i] = True # Tp-fp evaluation for group of boxes. gt_group_of_boxlist = np_box_list.BoxList( groundtruth_boxes[groundtruth_is_group_of_list, :]) if gt_group_of_boxlist.num_boxes() > 0: ioa = np_box_list_ops.ioa(gt_group_of_boxlist, detected_boxlist) max_overlap_group_of_gt = np.max(ioa, axis=0) for i in range(detected_boxlist.num_boxes()): if (not tp_fp_labels[i] and not is_matched_to_difficult_box[i] and max_overlap_group_of_gt[i] >= self.matching_iou_threshold): is_matched_to_group_of_box[i] = True return scores[~is_matched_to_difficult_box & ~is_matched_to_group_of_box], tp_fp_labels[ ~is_matched_to_difficult_box & ~is_matched_to_group_of_box]
def test_iou(self): iou = np_box_list_ops.iou(self.boxlist1, self.boxlist2) expected_iou = np.array([[2.0 / 16.0, 0.0, 6.0 / 400.0], [1.0 / 16.0, 0.0, 5.0 / 400.0]], dtype=float) self.assertAllClose(iou, expected_iou)