def test_valid_boundary(): x = [0, 0, 1, 0, 1, 1, 0, 1] assert not utils.valid_boundary(x, True) assert not utils.valid_boundary([0]) assert utils.valid_boundary(x, False) x = [0, 0, 1, 0, 1, 1, 0, 1, 1] assert utils.valid_boundary(x, True)
def boundary_iou(src, target): """Calculate the IOU between two boundaries. Args: src (list): Source boundary. target (list): Target boundary. Returns: iou (float): The iou between two boundaries. """ assert utils.valid_boundary(src, False) assert utils.valid_boundary(target, False) src_poly = points2polygon(src) target_poly = points2polygon(target) return poly_iou(src_poly, target_poly)
def boundary_iou(src, target, zero_division=0): """Calculate the IOU between two boundaries. Args: src (list): Source boundary. target (list): Target boundary. zero_division (int|float): The return value when invalid boundary exists. Returns: iou (float): The iou between two boundaries. """ assert utils.valid_boundary(src, False) assert utils.valid_boundary(target, False) src_poly = points2polygon(src) target_poly = points2polygon(target) return poly_iou(src_poly, target_poly, zero_division=zero_division)
def imshow_pred_boundary(img, boundaries_with_scores, labels, score_thr=0, boundary_color='blue', text_color='blue', thickness=1, font_scale=0.5, show=True, win_name='', wait_time=0, out_file=None, show_score=False): """Draw boundaries and class labels (with scores) on an image. Args: img (str or ndarray): The image to be displayed. boundaries_with_scores (list[list[float]]): Boundaries with scores. labels (list[int]): Labels of boundaries. score_thr (float): Minimum score of boundaries to be shown. boundary_color (str or tuple or :obj:`Color`): Color of boundaries. text_color (str or tuple or :obj:`Color`): Color of texts. thickness (int): Thickness of lines. font_scale (float): Font scales of texts. show (bool): Whether to show the image. win_name (str): The window name. wait_time (int): Value of waitKey param. out_file (str or None): The filename of the output. show_score (bool): Whether to show text instance score. """ assert isinstance(img, (str, np.ndarray)) assert utils.is_2dlist(boundaries_with_scores) assert utils.is_type_list(labels, int) assert utils.equal_len(boundaries_with_scores, labels) if len(boundaries_with_scores) == 0: warnings.warn('0 text found in ' + out_file) return utils.valid_boundary(boundaries_with_scores[0]) img = mmcv.imread(img) scores = np.array([b[-1] for b in boundaries_with_scores]) inds = scores > score_thr boundaries = [boundaries_with_scores[i][:-1] for i in np.where(inds)[0]] scores = [scores[i] for i in np.where(inds)[0]] labels = [labels[i] for i in np.where(inds)[0]] boundary_color = mmcv.color_val(boundary_color) text_color = mmcv.color_val(text_color) font_scale = 0.5 for boundary, score, label in zip(boundaries, scores, labels): boundary_int = np.array(boundary).astype(np.int32) cv2.polylines(img, [boundary_int.reshape(-1, 1, 2)], True, color=boundary_color, thickness=thickness) if show_score: label_text = f'{score:.02f}' cv2.putText(img, label_text, (boundary_int[0], boundary_int[1] - 2), cv2.FONT_HERSHEY_COMPLEX, font_scale, text_color) if show: mmcv.imshow(img, win_name, wait_time) if out_file is not None: mmcv.imwrite(img, out_file) return img
def eval_hmean(results, img_infos, ann_infos, metrics={'hmean-iou'}, score_thr=0.3, rank_list=None, logger=None, **kwargs): """Evaluation in hmean metric. Args: results (list[dict]): Each dict corresponds to one image, containing the following keys: boundary_result img_infos (list[dict]): Each dict corresponds to one image, containing the following keys: filename, height, width ann_infos (list[dict]): Each dict corresponds to one image, containing the following keys: masks, masks_ignore score_thr (float): Score threshold of prediction map. metrics (set{str}): Hmean metric set, should be one or all of {'hmean-iou', 'hmean-ic13'} Returns: dict[str: float] """ assert utils.is_type_list(results, dict) assert utils.is_type_list(img_infos, dict) assert utils.is_type_list(ann_infos, dict) assert len(results) == len(img_infos) == len(ann_infos) assert isinstance(metrics, set) gts, gts_ignore = get_gt_masks(ann_infos) preds = [] pred_scores = [] for result in results: _, texts, scores = extract_boundary(result) if len(texts) > 0: assert utils.valid_boundary(texts[0], False) valid_texts, valid_text_scores = filter_2dlist_result( texts, scores, score_thr) preds.append(valid_texts) pred_scores.append(valid_text_scores) eval_results = {} for metric in metrics: msg = f'Evaluating {metric}...' if logger is None: msg = '\n' + msg print_log(msg, logger=logger) best_result = dict(hmean=-1) for iter in range(3, 10): thr = iter * 0.1 if thr < score_thr: continue top_preds = select_top_boundary(preds, pred_scores, thr) if metric == 'hmean-iou': result, img_result = hmean_iou.eval_hmean_iou( top_preds, gts, gts_ignore) elif metric == 'hmean-ic13': result, img_result = hmean_ic13.eval_hmean_ic13( top_preds, gts, gts_ignore) else: raise NotImplementedError if rank_list is not None: output_ranklist(img_result, img_infos, rank_list) print_log('thr {0:.2f}, recall: {1[recall]:.3f}, ' 'precision: {1[precision]:.3f}, ' 'hmean: {1[hmean]:.3f}'.format(thr, result), logger=logger) if result['hmean'] > best_result['hmean']: best_result = result eval_results[metric + ':recall'] = best_result['recall'] eval_results[metric + ':precision'] = best_result['precision'] eval_results[metric + ':hmean'] = best_result['hmean'] return eval_results
def eval_hmean(results, img_infos, ann_infos, metrics={'hmean-iou'}, score_thr=None, min_score_thr=0.3, max_score_thr=0.9, step=0.1, rank_list=None, logger=None, **kwargs): """Evaluation in hmean metric. It conducts grid search over a range of boundary score thresholds and reports the best result. Args: results (list[dict]): Each dict corresponds to one image, containing the following keys: boundary_result img_infos (list[dict]): Each dict corresponds to one image, containing the following keys: filename, height, width ann_infos (list[dict]): Each dict corresponds to one image, containing the following keys: masks, masks_ignore score_thr (float): Deprecated. Please use min_score_thr instead. min_score_thr (float): Minimum score threshold of prediction map. max_score_thr (float): Maximum score threshold of prediction map. step (float): The spacing between score thresholds. metrics (set{str}): Hmean metric set, should be one or all of {'hmean-iou', 'hmean-ic13'} Returns: dict[str: float] """ assert utils.is_type_list(results, dict) assert utils.is_type_list(img_infos, dict) assert utils.is_type_list(ann_infos, dict) if score_thr: warnings.warn('score_thr is deprecated. Please use min_score_thr ' 'instead.') min_score_thr = score_thr assert 0 <= min_score_thr <= max_score_thr <= 1 assert 0 <= step <= 1 assert len(results) == len(img_infos) == len(ann_infos) assert isinstance(metrics, set) min_score_thr = float(min_score_thr) max_score_thr = float(max_score_thr) step = float(step) gts, gts_ignore = get_gt_masks(ann_infos) preds = [] pred_scores = [] for result in results: _, texts, scores = extract_boundary(result) if len(texts) > 0: assert utils.valid_boundary(texts[0], False) valid_texts, valid_text_scores = filter_2dlist_result( texts, scores, min_score_thr) preds.append(valid_texts) pred_scores.append(valid_text_scores) eval_results = {} for metric in metrics: msg = f'Evaluating {metric}...' if logger is None: msg = '\n' + msg print_log(msg, logger=logger) best_result = dict(hmean=-1) for thr in np.arange(min_score_thr, min(max_score_thr + step, 1.0), step): top_preds = select_top_boundary(preds, pred_scores, thr) if metric == 'hmean-iou': result, img_result = hmean_iou.eval_hmean_iou( top_preds, gts, gts_ignore) elif metric == 'hmean-ic13': result, img_result = hmean_ic13.eval_hmean_ic13( top_preds, gts, gts_ignore) else: raise NotImplementedError if rank_list is not None: output_ranklist(img_result, img_infos, rank_list) print_log( 'thr {0:.2f}, recall: {1[recall]:.3f}, ' 'precision: {1[precision]:.3f}, ' 'hmean: {1[hmean]:.3f}'.format(thr, result), logger=logger) if result['hmean'] > best_result['hmean']: best_result = result eval_results[metric + ':recall'] = best_result['recall'] eval_results[metric + ':precision'] = best_result['precision'] eval_results[metric + ':hmean'] = best_result['hmean'] return eval_results