forked from DonaldRR/SimpleNet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmetrics.py
122 lines (99 loc) · 4.24 KB
/
metrics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""Anomaly metrics."""
import cv2
import numpy as np
from sklearn import metrics
def compute_imagewise_retrieval_metrics(
anomaly_prediction_weights, anomaly_ground_truth_labels
):
"""
Computes retrieval statistics (AUROC, FPR, TPR).
Args:
anomaly_prediction_weights: [np.array or list] [N] Assignment weights
per image. Higher indicates higher
probability of being an anomaly.
anomaly_ground_truth_labels: [np.array or list] [N] Binary labels - 1
if image is an anomaly, 0 if not.
"""
fpr, tpr, thresholds = metrics.roc_curve(
anomaly_ground_truth_labels, anomaly_prediction_weights
)
auroc = metrics.roc_auc_score(
anomaly_ground_truth_labels, anomaly_prediction_weights
)
precision, recall, _ = metrics.precision_recall_curve(
anomaly_ground_truth_labels, anomaly_prediction_weights
)
auc_pr = metrics.auc(recall, precision)
return {"auroc": auroc, "fpr": fpr, "tpr": tpr, "threshold": thresholds}
def compute_pixelwise_retrieval_metrics(anomaly_segmentations, ground_truth_masks):
"""
Computes pixel-wise statistics (AUROC, FPR, TPR) for anomaly segmentations
and ground truth segmentation masks.
Args:
anomaly_segmentations: [list of np.arrays or np.array] [NxHxW] Contains
generated segmentation masks.
ground_truth_masks: [list of np.arrays or np.array] [NxHxW] Contains
predefined ground truth segmentation masks
"""
if isinstance(anomaly_segmentations, list):
anomaly_segmentations = np.stack(anomaly_segmentations)
if isinstance(ground_truth_masks, list):
ground_truth_masks = np.stack(ground_truth_masks)
flat_anomaly_segmentations = anomaly_segmentations.ravel()
flat_ground_truth_masks = ground_truth_masks.ravel()
fpr, tpr, thresholds = metrics.roc_curve(
flat_ground_truth_masks.astype(int), flat_anomaly_segmentations
)
auroc = metrics.roc_auc_score(
flat_ground_truth_masks.astype(int), flat_anomaly_segmentations
)
precision, recall, thresholds = metrics.precision_recall_curve(
flat_ground_truth_masks.astype(int), flat_anomaly_segmentations
)
F1_scores = np.divide(
2 * precision * recall,
precision + recall,
out=np.zeros_like(precision),
where=(precision + recall) != 0,
)
optimal_threshold = thresholds[np.argmax(F1_scores)]
predictions = (flat_anomaly_segmentations >= optimal_threshold).astype(int)
fpr_optim = np.mean(predictions > flat_ground_truth_masks)
fnr_optim = np.mean(predictions < flat_ground_truth_masks)
return {
"auroc": auroc,
"fpr": fpr,
"tpr": tpr,
"optimal_threshold": optimal_threshold,
"optimal_fpr": fpr_optim,
"optimal_fnr": fnr_optim,
}
import pandas as pd
from skimage import measure
def compute_pro(masks, amaps, num_th=200):
df = pd.DataFrame([], columns=["pro", "fpr", "threshold"])
binary_amaps = np.zeros_like(amaps, dtype=np.bool)
min_th = amaps.min()
max_th = amaps.max()
delta = (max_th - min_th) / num_th
k = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
for th in np.arange(min_th, max_th, delta):
binary_amaps[amaps <= th] = 0
binary_amaps[amaps > th] = 1
pros = []
for binary_amap, mask in zip(binary_amaps, masks):
binary_amap = cv2.dilate(binary_amap.astype(np.uint8), k)
for region in measure.regionprops(measure.label(mask)):
axes0_ids = region.coords[:, 0]
axes1_ids = region.coords[:, 1]
tp_pixels = binary_amap[axes0_ids, axes1_ids].sum()
pros.append(tp_pixels / region.area)
inverse_masks = 1 - masks
fp_pixels = np.logical_and(inverse_masks, binary_amaps).sum()
fpr = fp_pixels / inverse_masks.sum()
df = df.append({"pro": np.mean(pros), "fpr": fpr, "threshold": th}, ignore_index=True)
# Normalize FPR from 0 ~ 1 to 0 ~ 0.3
df = df[df["fpr"] < 0.3]
df["fpr"] = df["fpr"] / df["fpr"].max()
pro_auc = metrics.auc(df["fpr"], df["pro"])
return pro_auc