| | import numpy as np |
| | import torch |
| | from sklearn.metrics import (average_precision_score, f1_score, |
| | precision_recall_curve, roc_curve) |
| |
|
| | SMOOTH = 1e-6 |
| | __all__ = [ |
| | "get_f1_scores", |
| | "get_ap_scores", |
| | "batch_pix_accuracy", |
| | "batch_intersection_union", |
| | "get_iou", |
| | "get_pr", |
| | "get_roc", |
| | "get_ap_multiclass", |
| | ] |
| |
|
| |
|
| | def get_iou(outputs: torch.Tensor, labels: torch.Tensor): |
| | |
| | |
| | |
| | outputs = outputs.squeeze(1) |
| | labels = labels.squeeze(1) |
| |
|
| | intersection = ( |
| | (outputs & labels).float().sum((1, 2)) |
| | ) |
| | union = (outputs | labels).float().sum((1, 2)) |
| |
|
| | iou = (intersection + SMOOTH) / ( |
| | union + SMOOTH |
| | ) |
| |
|
| | return iou.cpu().numpy() |
| |
|
| |
|
| | def get_f1_scores(predict, target, ignore_index=-1): |
| | |
| | batch_size = predict.shape[0] |
| | predict = predict.data.cpu().numpy().reshape(-1) |
| | target = target.data.cpu().numpy().reshape(-1) |
| | pb = predict[target != ignore_index].reshape(batch_size, -1) |
| | tb = target[target != ignore_index].reshape(batch_size, -1) |
| |
|
| | total = [] |
| | for p, t in zip(pb, tb): |
| | total.append(np.nan_to_num(f1_score(t, p))) |
| |
|
| | return total |
| |
|
| |
|
| | def get_roc(predict, target, ignore_index=-1): |
| | target_expand = target.unsqueeze(1).expand_as(predict) |
| | target_expand_numpy = target_expand.data.cpu().numpy().reshape(-1) |
| | |
| | x = torch.zeros_like(target_expand) |
| | t = target.unsqueeze(1).clamp(min=0) |
| | target_1hot = x.scatter_(1, t, 1) |
| | batch_size = predict.shape[0] |
| | predict = predict.data.cpu().numpy().reshape(-1) |
| | target = target_1hot.data.cpu().numpy().reshape(-1) |
| | pb = predict[target_expand_numpy != ignore_index].reshape(batch_size, -1) |
| | tb = target[target_expand_numpy != ignore_index].reshape(batch_size, -1) |
| |
|
| | total = [] |
| | for p, t in zip(pb, tb): |
| | total.append(roc_curve(t, p)) |
| |
|
| | return total |
| |
|
| |
|
| | def get_pr(predict, target, ignore_index=-1): |
| | target_expand = target.unsqueeze(1).expand_as(predict) |
| | target_expand_numpy = target_expand.data.cpu().numpy().reshape(-1) |
| | |
| | x = torch.zeros_like(target_expand) |
| | t = target.unsqueeze(1).clamp(min=0) |
| | target_1hot = x.scatter_(1, t, 1) |
| | batch_size = predict.shape[0] |
| | predict = predict.data.cpu().numpy().reshape(-1) |
| | target = target_1hot.data.cpu().numpy().reshape(-1) |
| | pb = predict[target_expand_numpy != ignore_index].reshape(batch_size, -1) |
| | tb = target[target_expand_numpy != ignore_index].reshape(batch_size, -1) |
| |
|
| | total = [] |
| | for p, t in zip(pb, tb): |
| | total.append(precision_recall_curve(t, p)) |
| |
|
| | return total |
| |
|
| |
|
| | def get_ap_scores(predict, target, ignore_index=-1): |
| | total = [] |
| | for pred, tgt in zip(predict, target): |
| | target_expand = tgt.unsqueeze(0).expand_as(pred) |
| | target_expand_numpy = target_expand.data.cpu().numpy().reshape(-1) |
| |
|
| | |
| | x = torch.zeros_like(target_expand) |
| | t = tgt.unsqueeze(0).clamp(min=0).long() |
| | target_1hot = x.scatter_(0, t, 1) |
| | predict_flat = pred.data.cpu().numpy().reshape(-1) |
| | target_flat = target_1hot.data.cpu().numpy().reshape(-1) |
| |
|
| | p = predict_flat[target_expand_numpy != ignore_index] |
| | t = target_flat[target_expand_numpy != ignore_index] |
| |
|
| | total.append(np.nan_to_num(average_precision_score(t, p))) |
| |
|
| | return total |
| |
|
| |
|
| | def get_ap_multiclass(predict, target): |
| | total = [] |
| | for pred, tgt in zip(predict, target): |
| | predict_flat = pred.data.cpu().numpy().reshape(-1) |
| | target_flat = tgt.data.cpu().numpy().reshape(-1) |
| |
|
| | total.append(np.nan_to_num(average_precision_score(target_flat, predict_flat))) |
| |
|
| | return total |
| |
|
| |
|
| | def batch_precision_recall(predict, target, thr=0.5): |
| | """Batch Precision Recall |
| | Args: |
| | predict: input 4D tensor |
| | target: label 4D tensor |
| | """ |
| | |
| |
|
| | predict = predict > thr |
| | predict = predict.data.cpu().numpy() + 1 |
| | target = target.data.cpu().numpy() + 1 |
| |
|
| | tp = np.sum(((predict == 2) * (target == 2)) * (target > 0)) |
| | fp = np.sum(((predict == 2) * (target == 1)) * (target > 0)) |
| | fn = np.sum(((predict == 1) * (target == 2)) * (target > 0)) |
| |
|
| | precision = float(np.nan_to_num(tp / (tp + fp))) |
| | recall = float(np.nan_to_num(tp / (tp + fn))) |
| |
|
| | return precision, recall |
| |
|
| |
|
| | def batch_pix_accuracy(predict, target): |
| | """Batch Pixel Accuracy |
| | Args: |
| | predict: input 3D tensor |
| | target: label 3D tensor |
| | """ |
| |
|
| | |
| |
|
| | _, predict = torch.max(predict, 0) |
| | predict = predict.cpu().numpy() + 1 |
| | target = target.cpu().numpy() + 1 |
| | pixel_labeled = np.sum(target > 0) |
| | pixel_correct = np.sum((predict == target) * (target > 0)) |
| | assert pixel_correct <= pixel_labeled, "Correct area should be smaller than Labeled" |
| | return pixel_correct, pixel_labeled |
| |
|
| |
|
| | def batch_intersection_union(predict, target, nclass): |
| | """Batch Intersection of Union |
| | Args: |
| | predict: input 3D tensor |
| | target: label 3D tensor |
| | nclass: number of categories (int) |
| | """ |
| | _, predict = torch.max(predict, 0) |
| | mini = 1 |
| | maxi = nclass |
| | nbins = nclass |
| | predict = predict.cpu().numpy() + 1 |
| | target = target.cpu().numpy() + 1 |
| |
|
| | predict = predict * (target > 0).astype(predict.dtype) |
| | intersection = predict * (predict == target) |
| | |
| | area_inter, _ = np.histogram(intersection, bins=nbins, range=(mini, maxi)) |
| | area_pred, _ = np.histogram(predict, bins=nbins, range=(mini, maxi)) |
| | area_lab, _ = np.histogram(target, bins=nbins, range=(mini, maxi)) |
| | area_union = area_pred + area_lab - area_inter |
| | assert ( |
| | area_inter <= area_union |
| | ).all(), "Intersection area should be smaller than Union area" |
| | return area_inter, area_union |
| |
|
| |
|
| | |
| | def pixel_accuracy(im_pred, im_lab): |
| | im_pred = np.asarray(im_pred) |
| | im_lab = np.asarray(im_lab) |
| |
|
| | |
| | |
| | pixel_labeled = np.sum(im_lab > 0) |
| | pixel_correct = np.sum((im_pred == im_lab) * (im_lab > 0)) |
| | |
| | return pixel_correct, pixel_labeled |
| |
|
| |
|
| | def intersection_and_union(im_pred, im_lab, num_class): |
| | im_pred = np.asarray(im_pred) |
| | im_lab = np.asarray(im_lab) |
| | |
| | im_pred = im_pred * (im_lab > 0) |
| | |
| | intersection = im_pred * (im_pred == im_lab) |
| | area_inter, _ = np.histogram( |
| | intersection, bins=num_class - 1, range=(1, num_class - 1) |
| | ) |
| | |
| | area_pred, _ = np.histogram(im_pred, bins=num_class - 1, range=(1, num_class - 1)) |
| | area_lab, _ = np.histogram(im_lab, bins=num_class - 1, range=(1, num_class - 1)) |
| | area_union = area_pred + area_lab - area_inter |
| | return area_inter, area_union |
| |
|