CLYang617/RemoteSensingChangeDetection-RSCD.HA2F
0
1import numpy as np2 3 4################### metrics ###################5class AverageMeter(object):6 """Computes and stores the average and current value"""7 8 def __init__(self):9 self.initialized = False10 self.val = None11 self.avg = None12 self.sum = None13 self.count = None14 15 def initialize(self, val, weight):16 self.val = val17 self.avg = val18 self.sum = val * weight19 self.count = weight20 self.initialized = True21 22 def update(self, val, weight=1):23 if not self.initialized:24 self.initialize(val, weight)25 else:26 self.add(val, weight)27 28 def add(self, val, weight):29 self.val = val30 self.sum += val * weight31 self.count += weight32 self.avg = self.sum / self.count33 34 def value(self):35 return self.val36 37 def average(self):38 return self.avg39 40 def get_scores(self):41 scores_dict = cm2score(self.sum)42 return scores_dict43 44 def clear(self):45 self.initialized = False46 47 48################### cm metrics ###################49class ConfuseMatrixMeter(AverageMeter):50 """Computes and stores the average and current value"""51 52 def __init__(self, n_class):53 super(ConfuseMatrixMeter, self).__init__()54 self.n_class = n_class55 56 def update_cm(self, pr, gt, weight=1):57 """获得当前混淆矩阵,并计算当前F1得分,并更新混淆矩阵"""58 val = get_confuse_matrix(num_classes=self.n_class, label_gts=gt, label_preds=pr)59 self.update(val, weight)60 current_score = cm2F1(val)61 return current_score62 63 def get_scores(self):64 scores_dict = cm2score(self.sum)65 return scores_dict66 67 68def harmonic_mean(xs):69 harmonic_mean = len(xs) / sum((x + 1e-6) ** -1 for x in xs)70 return harmonic_mean71 72 73def cm2F1(confusion_matrix):74 hist = confusion_matrix75 tp = hist[1, 1]76 fn = hist[1, 0]77 fp = hist[0, 1]78 tn = hist[0, 0]79 # recall80 recall = tp / (tp + fn + np.finfo(np.float32).eps)81 # precision82 precision = tp / (tp + fp + np.finfo(np.float32).eps)83 # F1 score84 f1 = 2 * recall * precision / (recall + precision + np.finfo(np.float32).eps)85 return f186 87 88def cm2score(confusion_matrix):89 hist = confusion_matrix90 tp = hist[1, 1]91 fn = hist[1, 0]92 fp = hist[0, 1]93 tn = hist[0, 0]94 # acc95 oa = (tp + tn) / (tp + fn + fp + tn + np.finfo(np.float32).eps)96 # recall97 recall = tp / (tp + fn + np.finfo(np.float32).eps)98 # precision99 precision = tp / (tp + fp + np.finfo(np.float32).eps)100 # F1 score101 f1 = 2 * recall * precision / (recall + precision + np.finfo(np.float32).eps)102 # IoU103 iou = tp / (tp + fp + fn + np.finfo(np.float32).eps)104 # pre105 pre = ((tp + fn) * (tp + fp) + (tn + fp) * (tn + fn)) / (tp + fp + tn + fn) ** 2106 # kappa107 kappa = (oa - pre) / (1 - pre)108 score_dict = {'Kappa': kappa, 'IoU': iou, 'F1': f1, 'OA': oa, 'recall': recall, 'precision': precision, 'Pre': pre}109 return score_dict110 111 112def get_confuse_matrix(num_classes, label_gts, label_preds):113 """计算一组预测的混淆矩阵"""114 115 def __fast_hist(label_gt, label_pred):116 """117 Collect values for Confusion Matrix118 For reference, please see: https://en.wikipedia.org/wiki/Confusion_matrix119 :param label_gt: <np.array> ground-truth120 :param label_pred: <np.array> prediction121 :return: <np.ndarray> values for confusion matrix122 """123 mask = (label_gt >= 0) & (label_gt < num_classes)124 hist = np.bincount(num_classes * label_gt[mask].astype(int) + label_pred[mask],125 minlength=num_classes ** 2).reshape(num_classes, num_classes)126 return hist127 128 confusion_matrix = np.zeros((num_classes, num_classes))129 for lt, lp in zip(label_gts, label_preds):130 confusion_matrix += __fast_hist(lt.flatten(), lp.flatten())131 return confusion_matrix132 