import numpy as np
from HMB.ImagesHelper import MinMaxNormalization
[docs]
def ComputeIoU(preds, targets, smooth=1.0, iouType="binary", weight=None):
r'''
Compute the Intersection over Union (IoU) metric.
.. math::
IoU = \frac{|Prediction \cap Ground\ Truth| + smooth}{|Prediction \cup Ground\ Truth| + smooth}
where:
- :math:`|Prediction \cap Ground\ Truth|` is the intersection of the predicted and ground truth tensors.
- :math:`|Prediction \cup Ground\ Truth|` is the union of the predicted and ground truth tensors.
- :math:`smooth` is a small constant to avoid division by zero.
.. note::
The `iouType` parameter determines how the IoU is computed:
- `binary`: Threshold predictions at 0.5 to obtain binary masks.
- `soft`: Use raw predictions for soft IoU.
- `weighted`: Use class weights for weighted IoU (requires `weight` parameter).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
smooth (float, optional): Smoothing factor to avoid division by zero.
iouType (str, optional): Type of IoU to compute ("binary", "soft", or "weighted").
weight (numpy.ndarray, optional): Class weights for weighted IoU. Required if `iouType` is "weighted".
Returns:
float: IoU value.
Raises:
ValueError: If `iouType` is not one of "binary", "soft", or "weighted".
ValueError: If `weight` is not provided when `iouType` is "weighted".
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
iou = ism.ComputeIoU(preds, targets, iouType="binary")
print(f"IoU: {iou}")
iouSoft = ism.ComputeIoU(preds, targets, iouType="soft")
print(f"Soft IoU: {iouSoft}")
weight = np.array([0.7, 0.3]) # Example weights for two classes.
iouWeighted = ism.ComputeIoU(preds, targets, iouType="weighted", weight=weight)
print(f"Weighted IoU: {iouWeighted}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
if (iouType == "binary"):
# Threshold predictions at 0.5 to obtain binary mask.
preds = np.float32(preds > 0.5)
# Calculate intersection and union between prediction and target.
intersection = (preds * targets).sum()
union = preds.sum() + targets.sum() - intersection
elif (iouType == "soft"):
# Use raw predictions for soft IoU.
intersection = (preds * targets).sum()
union = preds.sum() + targets.sum() - intersection
elif (iouType == "weighted"):
if (weight is None):
raise ValueError("Weight must be provided for weighted IoU.")
# Broadcast weight over spatial dims and optionally channels
w = np.array(weight, dtype=np.float32)
while (w.ndim < preds.ndim):
w = w[:, None]
intersection = (w * preds * targets).sum()
union = ((w * preds).sum() + (w * targets).sum() - intersection)
else:
raise ValueError("Invalid iouType. Must be 'binary', 'soft', or 'weighted'.")
# Calculate the IoU using the formula.
iou = (intersection + smooth) / (union + smooth)
# Return the computed IoU value.
return iou
[docs]
def ComputeDice(preds, targets, smooth=1.0):
r'''
Compute the Dice coefficient.
.. math::
Dice = \frac{2 \times |Prediction \cap Ground\ Truth| + smooth}{|Prediction| + |Ground\ Truth| + smooth}
where:
- :math:`|Prediction \cap Ground\ Truth|` is the intersection of the predicted and ground truth tensors.
- :math:`|Prediction|` is the sum of the predicted tensor.
- :math:`|Ground\ Truth|` is the sum of the ground truth tensor.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
smooth (float, optional): Smoothing factor to avoid division by zero. Default is 1.0.
Returns:
float: Dice coefficient value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
dice = ism.ComputeDice(preds, targets)
print(f"Dice: {dice}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Threshold predictions at 0.5 to obtain binary mask.
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate intersection between prediction and target.
intersection = (preds * targets).sum()
# Calculate the Dice coefficient using the formula.
dice = (
(2.0 * intersection + smooth) /
(preds.sum() + targets.sum() + smooth)
)
# Return the computed Dice coefficient.
return dice
[docs]
def ComputePixelAccuracy(preds, targets):
r'''
Compute the pixel accuracy metric.
.. math::
Pixel\ Accuracy = \frac{Number\ of\ Correct\ Pixels}{Total\ Number\ of\ Pixels}
where:
- Number of Correct Pixels is the sum of pixels where predictions match targets.
- Total Number of Pixels is the product of the dimensions of the predicted tensor.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Pixel accuracy value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
acc = ism.ComputePixelAccuracy(preds, targets)
print(f"Pixel Accuracy: {acc}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
targets = np.float32(targets)
# Calculate the number of correct pixels.
correct = np.sum(preds == targets)
# Calculate the total number of pixels.
total = np.prod(preds.shape)
# Return the pixel accuracy value.
return correct / total
[docs]
def ComputePrecision(preds, targets):
r'''
Compute the precision metric.
.. math::
Precision = \frac{TP}{TP + FP}
where:
- :math:`TP` is the number of true positives (predicted positive and actually positive).
- :math:`FP` is the number of false positives (predicted positive but actually negative).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Precision value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
precision = ism.ComputePrecision(preds, targets)
print(f"Precision: {precision}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of true positives.
TP = (preds * targets).sum()
# Calculate the number of false positives.
FP = (preds * (1.0 - targets)).sum()
if ((TP + FP) == 0):
return 0.0
# Return the precision value.
return TP / (TP + FP)
[docs]
def ComputeRecall(preds, targets):
r'''
Compute the recall metric.
.. math::
Recall = \frac{TP}{TP + FN}
where:
- :math:`TP` is the number of true positives (predicted positive and actually positive).
- :math:`FN` is the number of false negatives (predicted negative but actually positive).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Recall value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
recall = ism.ComputeRecall(preds, targets)
print(f"Recall: {recall}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of true positives.
TP = (preds * targets).sum()
# Calculate the number of false negatives.
FN = ((1.0 - preds) * targets).sum()
if ((TP + FN) == 0):
return 0.0
# Return the recall value.
return TP / (TP + FN)
[docs]
def ComputeSpecificity(preds, targets):
r'''
Compute the specificity metric.
.. math::
Specificity = \frac{TN}{TN + FP}
where:
- :math:`TN` is the number of true negatives (predicted negative and actually negative).
- :math:`FP` is the number of false positives (predicted positive but actually negative).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Specificity value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
specificity = ism.ComputeSpecificity(preds, targets)
print(f"Specificity: {specificity}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of true negatives.
TN = ((1.0 - preds) * (1.0 - targets)).sum()
# Calculate the number of false positives.
FP = (preds * (1.0 - targets)).sum()
if ((TN + FP) == 0):
return 0.0
# Return the specificity value.
return TN / (TN + FP)
[docs]
def ComputeFPR(preds, targets):
r'''
Compute the false positive rate (FPR).
.. math::
FPR = \frac{FP}{FP + TN}
where:
- :math:`FP` is the number of false positives (predicted positive but actually negative).
- :math:`TN` is the number of true negatives (predicted negative and actually negative).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: FPR value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
fpr = ism.ComputeFPR(preds, targets)
print(f"FPR: {fpr}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of false positives.
FP = (preds * (1.0 - targets)).sum()
# Calculate the number of true negatives.
TN = ((1.0 - preds) * (1.0 - targets)).sum()
if ((FP + TN) == 0):
return 0.0
# Return the false positive rate value.
return FP / (FP + TN)
[docs]
def ComputeFNR(preds, targets):
r'''
Compute the false negative rate (FNR).
.. math::
FNR = \frac{FN}{FN + TP}
where:
- :math:`FN` is the number of false negatives (predicted negative but actually positive).
- :math:`TP` is the number of true positives (predicted positive and actually positive).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: FNR value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
fnr = ism.ComputeFNR(preds, targets)
print(f"FNR: {fnr}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of false negatives.
FN = ((1.0 - preds) * targets).sum()
# Calculate the number of true positives.
TP = (preds * targets).sum()
if ((TP + FN) == 0):
return 0.0
# Return the false negative rate value.
return FN / (FN + TP)
[docs]
def ComputeF1Score(preds, targets):
r'''
Compute the F1 score.
.. math::
F1 = \frac{2 \times Precision \times Recall}{Precision + Recall}
where:
- Precision is the ratio of true positives to the sum of true positives and false positives.
- Recall is the ratio of true positives to the sum of true positives and false negatives.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: F1 score value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
f1 = ism.ComputeF1Score(preds, targets)
print(f"F1 Score: {f1}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate precision and recall.
precision = ComputePrecision(preds, targets)
recall = ComputeRecall(preds, targets)
if ((precision + recall) == 0):
return 0.0
elif (np.isnan(precision) or np.isnan(recall)):
return 0.0
# Calculate the F1 Score using the formula.
f1 = (2.0 * precision * recall) / (precision + recall)
# Return the computed F1 Score.
return f1
[docs]
def ComputeMeanAveragePrecision(preds, targets):
r'''
Compute the mean average precision (mAP) for binary masks.
.. math::
mAP = \frac{1}{N} \times \sum_{i=1}^{N} Precision_i
where:
- :math:`Precision_i` is the precision for the i-th image in the batch.
- :math:`N` is the total number of images in the batch.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: mAP value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(2, 1, 256, 256)
targets = np.random.randint(0, 2, size=(2, 1, 256, 256))
mapScore = ism.ComputeMeanAveragePrecision(preds, targets)
print(f"mAP: {mapScore}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# For binary mask, mAP is just the precision averaged
# over all images (if batch).
if (preds.ndim > 2):
precisions = [
ComputePrecision(p, t)
for p, t in zip(preds, targets)
]
return np.mean(precisions)
else:
return ComputePrecision(preds, targets)
[docs]
def ComputeHausdorffDistance(preds, targets):
r'''
Compute the Hausdorff distance between predicted and ground truth masks.
.. math::
H(A, B) = \max\{\sup_{a \in A} \inf_{b \in B} d(a, b), \sup_{b \in B} \inf_{a \in A} d(a, b)\}
where:
- :math:`A` is the set of points in the predicted mask.
- :math:`B` is the set of points in the ground truth mask.
- :math:`d(a, b)` is the Euclidean distance between points `a` and `b`.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Hausdorff distance value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
hd = ism.ComputeHausdorffDistance(preds, targets)
print(f"Hausdorff Distance: {hd}")
'''
from scipy.spatial.distance import directed_hausdorff
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
targets = np.float32(targets > 0.5)
# Get the coordinates of the predicted and target points.
predPoints = np.argwhere(preds)
targetPoints = np.argwhere(targets)
# If either of the sets of points is empty, return infinity.
if (len(predPoints) == 0 or len(targetPoints) == 0):
return float("inf")
# Compute directed Hausdorff distances.
d1 = directed_hausdorff(predPoints, targetPoints)[0]
d2 = directed_hausdorff(targetPoints, predPoints)[0]
# Return the Hausdorff distance value.
return max(d1, d2)
[docs]
def ComputeBoundaryF1Score(preds, targets, dilationRatio=0.02, eps=1e-7):
r'''
Compute the Boundary F1 Score (BF Score).
.. math::
BF = \frac{2 \times Precision_{boundary} \times Recall_{boundary}}{Precision_{boundary} + Recall_{boundary}}
where:
- :math:`Precision_{boundary}` is the precision of the predicted boundary.
- :math:`Recall_{boundary}` is the recall of the predicted boundary.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
dilationRatio (float, optional): Ratio to determine the dilation size based on image dimensions. Default is 0.02.
eps (float, optional): Small constant to avoid division by zero. Default is 1e-7.
Returns:
float: Boundary F1 Score value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
bfScore = ism.ComputeBoundaryF1Score(preds, targets)
print(f"Boundary F1 Score: {bfScore}")
'''
from scipy.ndimage import binary_dilation, binary_erosion
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
preds = np.float32(preds > 0.5)
targets = np.float32(targets > 0.5)
# Get boundaries by subtracting eroded mask from mask.
def GetBoundary(mask, dilationRatio):
h, w = mask.shape[-2], mask.shape[-1]
dilation = int(np.round(dilationRatio * np.sqrt(h * w)))
eroded = binary_erosion(mask, iterations=dilation)
boundary = mask - eroded
return boundary
predBoundary = GetBoundary(preds.squeeze(), dilationRatio)
targetBoundary = GetBoundary(targets.squeeze(), dilationRatio)
# Dilate boundaries.
predDil = binary_dilation(predBoundary, iterations=1)
targetDil = binary_dilation(targetBoundary, iterations=1)
# Precision and recall for boundaries.
precision = (
(predBoundary * targetDil).sum() /
(predBoundary.sum() + eps)
)
recall = (
(targetBoundary * predDil).sum() /
(targetBoundary.sum() + eps)
)
bfScore = 2.0 * precision * recall / (precision + recall + eps)
return bfScore
[docs]
def ComputeMatthewsCorrelationCoefficient(preds, targets):
r'''
Compute the Matthews Correlation Coefficient (MCC).
.. math::
MCC = \frac{TP \times TN - FP \times FN}{\sqrt{(TP + FP) \times (TP + FN) \times (TN + FP) \times (TN + FN)}}
where
- :math:`TP` is the number of true positives (predicted positive and actually positive).
- :math:`TN` is the number of true negatives (predicted negative and actually negative).
- :math:`FP` is the number of false positives (predicted positive but actually negative).
- :math:`FN` is the number of false negatives (predicted negative but actually positive).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: MCC value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
mcc = ism.ComputeMatthewsCorrelationCoefficient(preds, targets)
print(f"Matthews Correlation Coefficient: {mcc}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of true positives.
TP = (preds * targets).sum()
# Calculate the number of true negatives.
TN = ((1.0 - preds) * (1.0 - targets)).sum()
# Calculate the number of false positives.
FP = (preds * (1.0 - targets)).sum()
# Calculate the number of false negatives.
FN = ((1.0 - preds) * targets).sum()
# Calculate the numerator and denominator for MCC.
num = (TP * TN) - (FP * FN)
den = np.sqrt(
(TP + FP) * (TP + FN) * (TN + FP) * (TN + FN)
)
if (den == 0):
return 0.0
# Return the Matthews Correlation Coefficient value.
return num / den
[docs]
def ComputeCohensKappa(preds, targets):
r'''
Compute Cohen's Kappa metric.
.. math::
\kappa = \frac{p_o - p_e}{1 - p_e}
where:
- :math:`p_o` is the observed agreement between predictions and targets.
- :math:`p_e` is the expected agreement by chance.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Cohen's Kappa value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
kappa = ism.ComputeCohensKappa(preds, targets)
print(f"Cohen's Kappa: {kappa}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of true positives.
TP = (preds * targets).sum()
# Calculate the number of true negatives.
TN = ((1.0 - preds) * (1.0 - targets)).sum()
# Calculate the number of false positives.
FP = (preds * (1.0 - targets)).sum()
# Calculate the number of false negatives.
FN = ((1.0 - preds) * targets).sum()
# Total number of pixels.
total = TP + TN + FP + FN
if (total == 0):
return 0.0
# Calculate observed accuracy.
Po = (TP + TN) / total
# Calculate expected accuracy.
Pe = (
((TP + FP) * (TP + FN) +
(FN + TN) * (FP + TN)) /
(total * total)
)
if ((1.0 - Pe) == 0):
return 0.0
# Return the Cohen's Kappa value.
return (Po - Pe) / (1.0 - Pe)
[docs]
def ComputeBalancedAccuracy(preds, targets):
r'''
Compute the balanced accuracy metric.
.. math::
Balanced\ Accuracy = \frac{Recall + Specificity}{2}
where:
- :math:`Recall` is the true positive rate.
- :math:`Specificity` is the true negative rate.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Balanced accuracy value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
balancedAcc = ism.ComputeBalancedAccuracy(preds, targets)
print(f"Balanced Accuracy: {balancedAcc}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate recall.
recall = ComputeRecall(preds, targets)
# Calculate specificity.
specificity = ComputeSpecificity(preds, targets)
# Return balanced accuracy value.
return (recall + specificity) / 2.0
[docs]
def ComputeMeanSurfaceDistance(preds, targets):
r'''
Compute the Mean Surface Distance (MSD) between predicted and ground truth masks.
.. math::
MSD = \frac{1}{|S_P|} \times \sum_{p \in S_P} \min_{q \in S_T} d(p, q)
where:
- :math:`S_P` is the set of points on the predicted mask boundary.
- :math:`S_T` is the set of points on the ground truth mask boundary
- :math:`d(p, q)` is the Euclidean distance between points `p` and `q`.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: MSD value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
msd = ism.ComputeMeanSurfaceDistance(preds, targets)
print(f"Mean Surface Distance: {msd}")
'''
from scipy.ndimage import distance_transform_edt
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
targets = np.float32(targets > 0.5)
# Get the coordinates of the predicted and target points.
predPoints = np.argwhere(preds)
targetPoints = np.argwhere(targets)
# If either of the sets of points is empty, return infinity.
if (len(predPoints) == 0 or len(targetPoints) == 0):
return float("inf")
# Compute distance transform for target points.
dtTarget = distance_transform_edt(1 - targets)
# For each predicted point, find the distance to the nearest target point.
distances = [dtTarget[tuple(coord)] for coord in predPoints]
# Return the mean surface distance value.
return np.mean(distances)
[docs]
def ComputeAverageSymmetricSurfaceDistance(preds, targets):
r'''
Compute the Average Symmetric Surface Distance (ASSD) between predicted and ground truth masks.
.. math::
ASSD = \frac{MSD(P, T) + MSD(T, P)}{2}
where:
- :math:`MSD(P, T)` is the Mean Surface Distance from prediction to target.
- :math:`MSD(T, P)` is the Mean Surface Distance from target to prediction.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: ASSD value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
assd = ism.ComputeAverageSymmetricSurfaceDistance(preds, targets)
print(f"Average Symmetric Surface Distance: {assd}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate MSD from prediction to target.
msd1 = ComputeMeanSurfaceDistance(preds, targets)
# Calculate MSD from target to prediction.
msd2 = ComputeMeanSurfaceDistance(targets, preds)
# Return ASSD value.
return (msd1 + msd2) / 2.0
[docs]
def ComputeVolumetricOverlapError(preds, targets, smooth=1.0):
r'''
Compute the Volumetric Overlap Error (VOE).
.. math::
VOE = 1 - IoU
where:
- :math:`IoU` is the Intersection over Union value.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
smooth (float, optional): Smoothing factor to avoid division by zero. Default is 1.0.
Returns:
float: VOE value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
voe = ism.ComputeVolumetricOverlapError(preds, targets)
print(f"Volumetric Overlap Error: {voe}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate IoU value.
iou = ComputeIoU(preds, targets, smooth=smooth, iouType="binary")
# Return VOE value.
return 1.0 - iou
[docs]
def ComputeGlobalConsistencyError(preds, targets):
r'''
Compute the Global Consistency Error (GCE).
.. math::
GCE = \frac{1}{N} \times \sum_{i=1}^{N} \min(E(S_1, S_2, p_i), E(S_2, S_1, p_i))
where:
- :math:`E(S_1, S_2, p_i)` is the error for pixel `p_i` in the predicted
mask compared to the ground truth mask.
- :math:`N` is the total number of pixels in the mask.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: GCE value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
gce = ism.ComputeGlobalConsistencyError(preds, targets)
print(f"Global Consistency Error: {gce}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
targets = np.float32(targets > 0.5)
# Flatten arrays.
predsFlat = preds.flatten()
targetsFlat = targets.flatten()
# Calculate error for each pixel.
error1 = np.sum(predsFlat != targetsFlat) / len(predsFlat)
error2 = np.sum(targetsFlat != predsFlat) / len(targetsFlat)
# Return GCE value.
return min(error1, error2)
[docs]
def ComputeTversky(preds, targets, alpha=0.5):
r'''
Compute the Tversky index metric.
.. math::
Tversky = \frac{TP}{TP + \alpha \times FP + (1-\alpha) \times FN}
where:
- :math:`TP` is the number of true positives (predicted positive and actually positive).
- :math:`FP` is the number of false positives (predicted positive but actually negative).
- :math:`FN` is the number of false negatives (predicted negative but actually positive).
- :math:`\alpha` is the weight for false positives (default 0.5).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
alpha (float, optional): Weight for false positives. Default is 0.5.
Returns:
float: Tversky index value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
tversky = ism.ComputeTversky(preds, targets, alpha=0.7)
print(f"Tversky Index: {tversky}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the number of true positives.
TP = (preds * targets).sum()
# Calculate the number of false positives.
FP = (preds * (1.0 - targets)).sum()
# Calculate the number of false negatives.
FN = ((1.0 - preds) * targets).sum()
beta = 1.0 - alpha
# Return the Tversky index value.
return TP / (TP + alpha * FP + beta * FN)
[docs]
def ComputeFocalTverskyLoss(preds, targets, alpha=0.5, gamma=np.round(4 / 3.0, 5)):
r'''
Compute the Focal Tversky index metric.
.. math::
FocalTversky = (1 - Tversky)^{1/\gamma}
where:
- :math:`Tversky` is the Tversky index (see ComputeTversky).
- :math:`\gamma` is the focusing parameter (default 4/3).
- :math:`\alpha` is the weight for false positives (default 0.5).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
alpha (float, optional): Weight for false positives. Default is 0.5.
gamma (float, optional): Focusing parameter. Default is 4/3.
Returns:
float: Focal Tversky index value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
focalTversky = ism.ComputeFocalTverskyLoss(preds, targets, alpha=0.7, gamma=1.33)
print(f"Focal Tversky Index: {focalTversky}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate the Tversky index.
tversky = ComputeTversky(preds, targets, alpha)
# Return the Focal Tversky value.
return np.power((1.0 - tversky), 1.0 / gamma)
[docs]
def ComputeFocalLoss(preds, targets, beta=0.5, gamma=2.0, eps=1e-7):
r'''
Compute the Focal Loss for binary segmentation.
.. math::
FL = -\beta \times (1 - p)^{\gamma} \times y \times \log(p) - (1 - \beta) \times p^{\gamma} \times (1 - y) \times \log(1 - p)
where:
- :math:`p` is the predicted probability.
- :math:`y` is the ground truth label.
- :math:`\beta` balances positive/negative examples.
- :math:`\gamma` focuses on hard examples.
- :math:`\epsilon` is a small constant to avoid log(0).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
beta (float, optional): Balancing factor for positive/negative examples. Default is 0.5.
gamma (float, optional): Focusing parameter. Default is 2.0.
eps (float, optional): Small constant to avoid log(0). Default is 1e-7.
Returns:
float: Focal loss value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
loss = ism.ComputeFocalLoss(preds, targets)
print(f"Focal Loss: {loss}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Clip predictions to avoid log(0) error.
preds = np.clip(preds, eps, 1.0 - eps)
# Calculate the focal loss.
loss = (
beta * np.power((1.0 - preds), gamma) *
targets * np.log(preds)
+ (1.0 - beta) * np.power(preds, gamma) *
(1.0 - targets) * np.log(1.0 - preds)
)
# Return the mean focal loss value.
return -np.mean(loss)
[docs]
def ComputeComboLoss(preds, targets, alpha=0.5, beta=0.5, smooth=1.0, eps=1e-7):
r'''
Compute the Combo Loss, combining weighted cross-entropy and Dice loss.
.. math::
ComboLoss = \beta \times CE + (1 - \beta) \times -\log(Dice)
where:
- :math:`CE` is the weighted cross-entropy.
- :math:`Dice` is the Dice coefficient.
- :math:`\alpha` weights positive/negative classes in CE.
- :math:`\beta` balances CE and Dice.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
alpha (float, optional): Weight for positive class in CE. Default is 0.5.
beta (float, optional): Balance between CE and Dice. Default is 0.5.
smooth (float, optional): Smoothing factor for Dice. Default is 1.0.
eps (float, optional): Small constant to avoid log(0). Default is 1e-7.
Returns:
float: Combo loss value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
loss = ism.ComputeComboLoss(preds, targets)
print(f"Combo Loss: {loss}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate the Dice coefficient.
dice = float(ComputeDice(preds, targets, smooth))
# Clip predictions to avoid log(0) error.
preds = np.clip(preds, eps, 1.0 - eps)
# Calculate the weighted cross-entropy.
tLnP = alpha * targets * np.log(preds)
pLnT = (1.0 - alpha) * (1.0 - targets) * np.log(1.0 - preds)
out = -tLnP + pLnT
weightedCE = np.mean(out)
# Calculate the Combo Loss.
loss = beta * weightedCE - (1.0 - beta) * np.log(dice)
return loss
[docs]
def ComputeTanimotoLoss(preds, targets):
r'''
Compute the Tanimoto Loss for binary segmentation.
.. math::
Tanimoto = 1 - \frac{\sum p t}{\sum p^2 + \sum t^2 - \sum p t}
where:
- :math:`p` is the predicted mask.
- :math:`t` is the ground truth mask.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Tanimoto loss value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
loss = ism.ComputeTanimotoLoss(preds, targets)
print(f"Tanimoto Loss: {loss}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Convert logits to binary predictions.
preds = np.float32(preds > 0.5)
# Calculate the numerator and denominator for Tanimoto loss.
num = (preds * targets).sum()
den = (
(preds ** 2).sum() +
(targets ** 2).sum() -
(preds * targets).sum()
)
# Return the Tanimoto loss value.
return 1.0 - num / den
[docs]
def ComputeMSELoss(preds, targets):
r'''
Compute the Mean Squared Error (MSE) loss.
.. math::
MSE = \frac{1}{N} \times \sum_{i=1}^N (p_i - t_i)^2
where:
- :math:`p_i` is the predicted value.
- :math:`t_i` is the ground truth value.
- :math:`N` is the number of elements.
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: MSE loss value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.rand(1, 1, 256, 256)
loss = ism.ComputeMSELoss(preds, targets)
print(f"MSE Loss: {loss}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate the Mean Squared Error (MSE) loss.
return np.mean((preds - targets) ** 2)
[docs]
def ComputeBCELoss(preds, targets, smooth=1e-7):
r'''
Compute the Binary Cross-Entropy (BCE) loss.
.. math::
BCE = -\frac{1}{N} \times \sum_{i=1}^N [t_i \times \log(p_i) + (1 - t_i) \times \log(1 - p_i)]
where:
- :math:`p_i` is the predicted probability.
- :math:`t_i` is the ground truth label.
- :math:`N` is the number of elements.
- :math:`smooth` is a small constant to avoid log(0).
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
smooth (float, optional): Small constant to avoid log(0). Default is 1e-7.
Returns:
float: BCE loss value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
loss = ism.ComputeBCELoss(preds, targets)
print(f"BCE Loss: {loss}")
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Clip predictions to avoid log(0) error.
preds = np.clip(preds, smooth, 1.0 - smooth)
# Calculate the Binary Cross-Entropy (BCE) loss.
bce = (
-np.mean(
targets * np.log(preds) +
(1.0 - targets) * np.log(1.0 - preds)
)
)
return bce
[docs]
def ComputeHMBLoss(preds, targets):
r'''
Compute the HMB Loss, a weighted combination of multiple loss functions for segmentation.
The HMB Loss (H-Loss), as suggested by Hossam (the author), introduces a weighted sum
of various loss functions: Dice, IoU, MSE, BCE, Tversky, and Tanimoto losses [1]_.
This idea is presented in a research article that can be accessed from:
https://doi.org/10.1109/ACCESS.2024.3483661
The HMB Loss combines:
- MSE Loss (distance-based)
- Dice Loss (region-based)
- IoU Loss (region-based)
- Tversky Loss (region-based)
- BCE Loss (distribution-based)
- Tanimoto Loss (distribution-based)
Parameters:
preds (numpy.ndarray): Predicted tensor (logits).
targets (numpy.ndarray): Ground truth tensor (binary mask).
Returns:
float: Weighted average loss value.
Examples
--------
.. code-block:: python
import numpy as np
import HMB.ImageSegmentationMetrics as ism
preds = np.random.rand(1, 1, 256, 256)
targets = np.random.randint(0, 2, size=(1, 1, 256, 256))
loss = ism.ComputeHMBLoss(preds, targets)
print(f"HMB Loss: {loss}")
References
----------
.. [1] Sharaby, I., Balaha, H. M., Alksas, A., Mahmoud, A., Abou El-Ghar, M., Khalil, A., ...
& El-Baz, A. (2024). Artificial intelligence-based kidney segmentation with modified
cycle-consistent generative adversarial network and appearance-based shape prior. IEEE Access.
https://doi.org/10.1109/ACCESS.2024.3483661
'''
# Normalize predictions and targets to [0, 1] range if they are not already.
preds = MinMaxNormalization(preds, mapToUint8=False) # Normalize predictions to [0, 1].
targets = MinMaxNormalization(targets, mapToUint8=False) # Normalize targets to [0, 1].
# Calculate individual loss components.
mseLoss = ComputeMSELoss(preds, targets) # Distance-based.
diceLoss = 1.0 - ComputeDice(preds, targets) # Region-based.
iouLoss = 1.0 - ComputeIoU(preds, targets) # Region-based.
tverskyLoss = 1.0 - ComputeTversky(preds, targets) # Region-based.
bceLoss = ComputeBCELoss(preds, targets) # Distribution-based.
tanimotoLoss = ComputeTanimotoLoss(preds, targets) # Distribution-based.
# Define weights for each loss component.
weights = np.array(
[
200, # Weight for MSE Loss.
50, # Weight for Dice Loss.
50, # Weight for IoU Loss.
50, # Weight for Tversky Loss.
25, # Weight for BCE Loss.
25, # Weight for Tanimoto Loss.
]
)
# Normalize the weights to sum to 1.
weights = weights / np.sum(weights)
# Calculate the weighted average loss.
avgLoss = (
weights[0] * mseLoss
+ weights[1] * diceLoss
+ weights[2] * iouLoss
+ weights[3] * tverskyLoss
+ weights[4] * bceLoss
+ weights[5] * tanimotoLoss
)
return avgLoss
# Main block to test the metric functions with simulated data.
if __name__ == "__main__":
# Simulate a model output tensor with random values (e.g., logits).
predictions = np.random.rand(1, 1, 256, 256).astype(np.float32) # Simulated model output tensor.
# Normalize the predictions to the range [0, 1].
predictions = (predictions - predictions.min()) / (predictions.max() - predictions.min()) # Normalize predictions.
# Simulate a ground truth mask tensor with binary values (0 or 1).
groundTruthMask = np.random.randint(0, 2, size=(1, 1, 256, 256)).astype(np.float32) # Simulated ground truth mask.
# Calculate IoU for predictions.
iou = ComputeIoU(predictions, groundTruthMask) # Compute metrics.
# Calculate Dice coefficient for predictions.
dice = ComputeDice(predictions, groundTruthMask) # Compute metrics.
# Calculate F1 score for predictions.
f1Score = ComputeF1Score(predictions, groundTruthMask) # Compute metrics.
# Print the computed metrics for predictions.
print(f"IoU: {iou}, Dice: {dice}, F1 Score: {f1Score}") # Print the computed metrics.
# Calculate IoU for ground truth.
iou = ComputeIoU(groundTruthMask, groundTruthMask) # Compute metrics.
# Calculate Dice coefficient for ground truth.
dice = ComputeDice(groundTruthMask, groundTruthMask) # Compute metrics.
# Calculate F1 score for ground truth.
f1Score = ComputeF1Score(groundTruthMask, groundTruthMask) # Compute metrics.
# Print the computed metrics for ground truth.
print(f"IoU: {iou}, Dice: {dice}, F1 Score: {f1Score}") # Print the computed metrics for ground truth.
# Calculate Pixel Accuracy for predictions.
pixelAccuracy = ComputePixelAccuracy(predictions, groundTruthMask) # Compute metrics.
# Print the computed Pixel Accuracy.
print(f"Pixel Accuracy: {pixelAccuracy}") # Print the computed Pixel Accuracy.
# Calculate Precision for predictions.
precision = ComputePrecision(predictions, groundTruthMask) # Compute metrics.
# Print the computed Precision.
print(f"Precision: {precision}") # Print the computed Precision.
# Calculate Recall for predictions.
recall = ComputeRecall(predictions, groundTruthMask) # Compute metrics.
# Print the computed Recall.
print(f"Recall: {recall}") # Print the computed Recall.
# Calculate Specificity for predictions.
specificity = ComputeSpecificity(predictions, groundTruthMask) # Compute metrics.
# Print the computed Specificity.
print(f"Specificity: {specificity}") # Print the computed Specificity.
# Calculate False Positive Rate (FPR) for predictions.
fpr = ComputeFPR(predictions, groundTruthMask) # Compute metrics.
# Print the computed FPR.
print(f"FPR: {fpr}") # Print the computed FPR.
# Calculate False Negative Rate (FNR) for predictions.
fnr = ComputeFNR(predictions, groundTruthMask) # Compute metrics.
# Print the computed FNR.
print(f"FNR: {fnr}") # Print the computed FNR.
# Calculate mean Average Precision (mAP) for predictions.
mapScore = ComputeMeanAveragePrecision(predictions, groundTruthMask) # Compute metrics.
# Print the computed mAP.
print(f"mAP: {mapScore}") # Print the computed mAP.
# Calculate Hausdorff Distance for predictions.
hd = ComputeHausdorffDistance(predictions, groundTruthMask) # Compute metrics.
# Print the computed Hausdorff Distance.
print(f"Hausdorff Distance: {hd}") # Print the computed Hausdorff Distance.
# Calculate Boundary F1 Score for predictions.
bfScore = ComputeBoundaryF1Score(predictions, groundTruthMask) # Compute metrics.
# Print the computed Boundary F1 Score.
print(f"Boundary F1 Score: {bfScore}") # Print the computed Boundary F1 Score.
# Calculate Matthews Correlation Coefficient for predictions.
mcc = ComputeMatthewsCorrelationCoefficient(predictions, groundTruthMask) # Compute metrics.
# Print the computed MCC.
print(f"MCC: {mcc}") # Print the computed MCC.
# Calculate Cohen's Kappa for predictions.
kappa = ComputeCohensKappa(predictions, groundTruthMask) # Compute metrics.
# Print the computed Cohen's Kappa.
print(f"Cohen's Kappa: {kappa}") # Print the computed Cohen's Kappa.
# Calculate Balanced Accuracy for predictions.
balancedAcc = ComputeBalancedAccuracy(predictions, groundTruthMask) # Compute metrics.
# Print the computed Balanced Accuracy.
print(f"Balanced Accuracy: {balancedAcc}") # Print the computed Balanced Accuracy.
# Calculate Mean Surface Distance for predictions.
msd = ComputeMeanSurfaceDistance(predictions, groundTruthMask) # Compute metrics.
# Print the computed Mean Surface Distance.
print(f"MSD: {msd}") # Print the computed Mean Surface Distance.
# Calculate Average Symmetric Surface Distance for predictions.
assd = ComputeAverageSymmetricSurfaceDistance(predictions, groundTruthMask) # Compute metrics.
# Print the computed ASSD.
print(f"ASSD: {assd}") # Print the computed ASSD.
# Calculate Volumetric Overlap Error for predictions.
voe = ComputeVolumetricOverlapError(predictions, groundTruthMask) # Compute metrics.
# Print the computed VOE.
print(f"VOE: {voe}") # Print the computed VOE.
# Calculate Global Consistency Error for predictions.
gce = ComputeGlobalConsistencyError(predictions, groundTruthMask) # Compute metrics.
# Print the computed GCE.
print(f"GCE: {gce}") # Print the computed GCE.