forked from hmyao22/DADF
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
77 lines (61 loc) · 2.63 KB
/
Copy pathutils.py
File metadata and controls
77 lines (61 loc) · 2.63 KB
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
from numpy import ndarray
import pandas as pd
import numpy as np
from skimage import measure
from statistics import mean
from sklearn.metrics import auc
from warnings import simplefilter
simplefilter(action="ignore", category=FutureWarning)
class AverageMeter:
"""Computes and stores the average and current value"""
def __init__(self):
self.reset()
def reset(self):
self.val = 0
self.avg = 0
self.sum = 0
self.count = 0
def update(self, val, n=1):
self.val = val
self.sum += val * n
self.count += n
self.avg = self.sum / self.count
def compute_pro(masks, amaps, num_th: int = 200) -> None:
"""Compute the area under the curve of per-region overlaping (PRO) and 0 to 0.3 FPR
Args:
category (str): Category of product
masks (ndarray): All binary masks in test. masks.shape -> (num_test_data, h, w)
amaps (ndarray): All anomaly maps in test. amaps.shape -> (num_test_data, h, w)
num_th (int, optional): Number of thresholds
"""
assert isinstance(amaps, ndarray), "type(amaps) must be ndarray"
assert isinstance(masks, ndarray), "type(masks) must be ndarray"
assert amaps.ndim == 3, "amaps.ndim must be 3 (num_test_data, h, w)"
assert masks.ndim == 3, "masks.ndim must be 3 (num_test_data, h, w)"
assert amaps.shape == masks.shape, "amaps.shape and masks.shape must be same"
assert set(masks.flatten()) == {0, 1}, "set(masks.flatten()) must be {0, 1}"
assert isinstance(num_th, int), "type(num_th) must be int"
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
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):
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": 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 = auc(df["fpr"], df["pro"])
return pro_auc