Statistical note
Segmentation metrics: IoU, Dice, and boundary error
Overlap, class imbalance, object-level failure, and how to evaluate biological segmentation beyond one score.
For predicted pixels and reference pixels ,
For a binary mask, Dice equals the pixel-level F1 score, and .
import numpy as np
from sklearn.metrics import jaccard_score, f1_score
truth = np.array([[0, 1, 1], [0, 1, 0], [0, 0, 0]]).ravel()
pred = np.array([[0, 1, 1], [0, 1, 1], [0, 0, 0]]).ravel()
print("IoU", jaccard_score(truth, pred))
print("Dice", f1_score(truth, pred))
Case study: cell segmentation
Pixel overlap can look excellent even when adjacent cells are merged, because most foreground pixels remain correct. Add object-level matching, split/merge counts, boundary distance, per-image distributions, and downstream measurement error. Define how empty masks and small objects are handled.
Macro averaging gives each class equal weight; micro averaging pools pixels and can be dominated by background. scikit-learn supplies overlap primitives, while object and boundary metrics often require domain-specific code.
Functions: sklearn.metrics.jaccard_score, f1_score, confusion_matrix, and multilabel_confusion_matrix.



