[96354c]: / src / metrics / evaluation_metrics.py

Download this file

82 lines (59 with data), 2.3 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
78
79
from typing import Tuple
from medpy import metric
import numpy as np
def get_confusion_matrix(prediction: np.ndarray, reference: np.ndarray, roi_mask: np.ndarray) -> Tuple[int, int, int, int]:
"""
Computes tp/fp/tn/fn from teh provided segmentations
"""
assert prediction.shape == reference.shape, "'prediction' and 'reference' must have the same shape"
tp = int((roi_mask*(prediction != 0) * (reference != 0)).sum()) # overlap
fp = int((roi_mask*(prediction != 0) * (reference == 0)).sum())
tn = int((roi_mask*(prediction == 0) * (reference == 0)).sum()) # no segmentation
fn = int((roi_mask*(prediction == 0) * (reference != 0)).sum())
return tp, fp, tn, fn
def dice(tp: int, fp:int, fn:int) -> float:
"""
Dice coefficient computed using the definition of true positive (TP), false positive (FP), and false negative (FN)
2TP / (2TP + FP + FN)
"""
denominator = 2*tp + fp + fn
if denominator <= 0:
return 0
return (2 * tp / denominator)
# Hausdorff
def hausdorff(prediction: np.ndarray, reference: np.ndarray) -> float:
try:
return metric.hd95(prediction, reference)
except Exception as e:
print("Error: ", e)
print(f"Prediction does not contain the same label as gt. "
f"Pred labels {np.unique(prediction)} GT labels {np.unique(reference)}")
return 373
# Sensitivity: recall
def recall(tp, fn) -> float:
"""TP / (TP + FN)"""
actual_positives = tp + fn
if actual_positives <= 0:
return 0
return tp / actual_positives
# Specificity: precision
def precision(tp, fp) -> float:
"""TP/ (TP + FP)"""
predicted_positives = tp + fp
if predicted_positives <= 0:
return 0
return tp / predicted_positives
def fscore(tp, fp, tn, fn, beta:int=1) -> float:
"""(1 + b^2) * TP / ((1 + b^2) * TP + b^2 * FN + FP)"""
assert beta > 0
precision_ = precision(tn, fp)
recall_ = recall(tp, fn)
if ((beta * beta * precision_) + recall_) <= 0:
return 0
fscore = (1 + beta * beta) * precision_ * recall_ / ((beta * beta * precision_) + recall_)
return fscore
def accuracy(tp, fp, tn, fn) -> float:
"""(TP + TN) / (TP + FP + FN + TN)"""
if (tp + fp + tn + fn) <= 0:
return 0
return (tp + tn) / (tp + fp + tn + fn)