File size: 1,622 Bytes
9875bf8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Evaluation metrics for change and cloud detection."""

import numpy as np
from typing import Dict, Optional


def calculate_metrics(
    pred_mask: np.ndarray,
    gt_mask: np.ndarray,
    threshold: float = 0.5
) -> Dict[str, float]:
    """
    Calculate pixel-level classification metrics.

    Args:
        pred_mask: Predicted binary mask (H, W) or confidence map (H, W)
        gt_mask: Ground truth binary mask (H, W)
        threshold: Threshold to binarise pred_mask if it's a confidence map

    Returns:
        Dict with keys: accuracy, precision, recall, f1, iou
    """
    # Binarise predictions if needed
    if pred_mask.dtype != np.uint8 or pred_mask.max() > 1:
        pred = (pred_mask > threshold).astype(np.uint8)
    else:
        pred = pred_mask.astype(np.uint8)

    gt = (gt_mask > 0).astype(np.uint8)

    tp = int(np.sum((pred == 1) & (gt == 1)))
    tn = int(np.sum((pred == 0) & (gt == 0)))
    fp = int(np.sum((pred == 1) & (gt == 0)))
    fn = int(np.sum((pred == 0) & (gt == 1)))

    total = tp + tn + fp + fn
    accuracy  = (tp + tn) / total if total > 0 else 0.0
    precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0
    recall    = tp / (tp + fn) if (tp + fn) > 0 else 0.0
    f1        = (2 * precision * recall / (precision + recall)
                 if (precision + recall) > 0 else 0.0)
    iou       = tp / (tp + fp + fn) if (tp + fp + fn) > 0 else 0.0

    return {
        "accuracy": accuracy,
        "precision": precision,
        "recall": recall,
        "f1": f1,
        "iou": iou,
        "tp": tp,
        "tn": tn,
        "fp": fp,
        "fn": fn,
    }