Skip to content

Commit

Permalink
Completed coverage. Fixes #1
Browse files Browse the repository at this point in the history
  • Loading branch information
m_helleis authored and m_helleis committed Jun 9, 2021
1 parent 2df27ed commit 0d54333
Showing 1 changed file with 66 additions and 6 deletions.
72 changes: 66 additions & 6 deletions tests/test_seg_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,49 @@
from sklearn.metrics import accuracy_score, f1_score, recall_score, precision_score, jaccard_score, cohen_kappa_score


def test_segmentation_metrics():
shape = (256, 256, 3)
# case all pixels belong to the positive class and are detected
y_true = np.random.randint(0, 2, shape)
y_pred = np.random.randint(0, 2, shape)
valid_mask = np.random.randint(0, 2, shape)
tpfptnfn = segm.tpfptnfn(y_true, y_pred, valid_mask)
decimals = 6
metrics = segm.segmentation_metrics(tpfptnfn, decimals=decimals)
# acc
assert (
round(segm._accuracy(tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["tn"], tpfptnfn["fn"]), decimals)
== metrics["acc"]
)
# recall
assert round(segm._recall(tpfptnfn["tp"], tpfptnfn["fn"]), decimals) == metrics["recall"]
# precision
assert round(segm._precision(tpfptnfn["tp"], tpfptnfn["fp"]), decimals) == metrics["precision"]
# F1
assert (
round(
segm._f1_score(
segm._recall(tpfptnfn["tp"], tpfptnfn["fn"]), segm._precision(tpfptnfn["tp"], tpfptnfn["fp"])
),
decimals,
)
== metrics["F1"]
)
# IoU
assert (
round(segm._intersection_over_union(tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["fn"], tpfptnfn["tn"]), decimals)
== metrics["iou"]
)
# kappa
assert (
round(
segm._kappa(tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["tn"], tpfptnfn["fn"], tpfptnfn["n_valid_pixel"]),
decimals,
)
== metrics["kappa"]
)


def test_tpfptnfn():
shape = (256, 256, 3)
# case all pixels belong to the positive class and are detected
Expand Down Expand Up @@ -49,6 +92,14 @@ def test_tpfptnfn():
== np.sum([tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["tn"], tpfptnfn["fn"]])
== tpfptnfn["n_valid_pixel"]
)
# test automatic generation off all-is-valid mask, if no valid-mask is provided
tpfptnfn = segm.tpfptnfn(y_true, y_pred, None)
assert (
np.sum([tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["tn"], tpfptnfn["fn"]])
== tpfptnfn["n_valid_pixel"]
== y_true.size
== y_pred.size
)


def test_accuracy():
Expand Down Expand Up @@ -108,9 +159,7 @@ def test_f1_score():
tpfptnfn = segm.tpfptnfn(y_true, y_pred, valid_mask)
rec = segm._recall(tpfptnfn["tp"], tpfptnfn["fn"])
prec = segm._precision(tpfptnfn["tp"], tpfptnfn["fp"])
assert np.round(segm._f1_score(rec, prec), decimals=6) == np.round(
f1_score(y_true_sk.flatten(), y_pred_sk.flatten()), decimals=6
)
assert round(segm._f1_score(rec, prec), 6) == round(f1_score(y_true_sk.flatten(), y_pred_sk.flatten()), 6)


def test_intersection_over_union():
Expand All @@ -127,6 +176,17 @@ def test_intersection_over_union():
assert segm._intersection_over_union(
tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["fn"], tpfptnfn["tn"]
) == jaccard_score(y_true_sk.flatten(), y_pred_sk.flatten())
# test the special case were we have only true negatives and no wrong predictions
y_true = np.zeros(shape)
y_pred = np.zeros(shape)
y_true_sk = y_true[valid_mask == 1]
y_pred_sk = y_pred[valid_mask == 1]
tpfptnfn = segm.tpfptnfn(y_true, y_pred, valid_mask)
assert (
segm._intersection_over_union(tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["fn"], tpfptnfn["tn"])
== 1.0
== jaccard_score(y_true_sk.flatten(), y_pred_sk.flatten(), zero_division=1.0)
)


def test_kappa():
Expand All @@ -141,9 +201,9 @@ def test_kappa():
y_pred_sk = y_pred[valid_mask == 1]
tpfptnfn = segm.tpfptnfn(y_true, y_pred, valid_mask)
assert (
np.round(
round(
segm._kappa(tpfptnfn["tp"], tpfptnfn["fp"], tpfptnfn["tn"], tpfptnfn["fn"], tpfptnfn["n_valid_pixel"]),
decimals=6,
6,
)
== np.round(cohen_kappa_score(y_true_sk.flatten(), y_pred_sk.flatten()), decimals=6)
== round(cohen_kappa_score(y_true_sk.flatten(), y_pred_sk.flatten()), 6)
)

0 comments on commit 0d54333

Please sign in to comment.