File size: 3,374 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""Advanced comparison metrics for change detection evaluation."""

import numpy as np
from typing import Dict, Optional
from .evaluation import calculate_metrics


def calculate_change_statistics(
    change_mask: np.ndarray,
    change_confidence: np.ndarray
) -> Dict:
    """
    Calculate statistics from a 2D change mask and confidence map.

    Args:
        change_mask: Binary 2D array (H, W), 1 = changed
        change_confidence: Float 2D array (H, W) in [0, 1]

    Returns:
        Dict with total_pixels, changed_pixels, unchanged_pixels,
        change_percentage, mean_confidence, min_confidence, max_confidence,
        change_confidence_mean (mean conf among changed pixels only)
    """
    # Ensure 2D arrays
    mask = change_mask.astype(np.uint8)
    conf = change_confidence.astype(np.float32)

    total_pixels     = int(mask.size)
    changed_pixels   = int(np.sum(mask == 1))
    unchanged_pixels = total_pixels - changed_pixels
    change_percentage = 100.0 * changed_pixels / total_pixels if total_pixels > 0 else 0.0

    mean_confidence = float(conf.mean())
    min_confidence  = float(conf.min())
    max_confidence  = float(conf.max())

    # Mean confidence among changed pixels only
    if changed_pixels > 0:
        change_confidence_mean = float(conf[mask == 1].mean())
    else:
        change_confidence_mean = 0.0

    return {
        "total_pixels":          total_pixels,
        "changed_pixels":        changed_pixels,
        "unchanged_pixels":      unchanged_pixels,
        "change_percentage":     change_percentage,
        "mean_confidence":       mean_confidence,
        "min_confidence":        min_confidence,
        "max_confidence":        max_confidence,
        "change_confidence_mean": change_confidence_mean,
    }


def compare_with_without_masking(
    pred_with_mask: np.ndarray,
    pred_without_mask: np.ndarray,
    gt_mask: Optional[np.ndarray] = None
) -> Dict:
    """
    Compare detection results with and without cloud masking.

    Args:
        pred_with_mask: Change mask produced WITH cloud masking (H, W)
        pred_without_mask: Change mask produced WITHOUT cloud masking (H, W)
        gt_mask: Optional ground truth mask for metric computation (H, W)

    Returns:
        Dict with pixel-level comparison and optional metric differences
    """
    agreement = int(np.sum(pred_with_mask == pred_without_mask))
    total     = int(pred_with_mask.size)
    agreement_pct = 100.0 * agreement / total if total > 0 else 0.0

    result = {
        "agreement_pixels":     agreement,
        "total_pixels":         total,
        "agreement_percentage": agreement_pct,
        "changed_with_mask":    int(np.sum(pred_with_mask)),
        "changed_without_mask": int(np.sum(pred_without_mask)),
    }

    if gt_mask is not None:
        metrics_with    = calculate_metrics(pred_with_mask, gt_mask)
        metrics_without = calculate_metrics(pred_without_mask, gt_mask)

        result["iou_with_mask"]     = metrics_with["iou"]
        result["iou_without_mask"]  = metrics_without["iou"]
        result["iou_improvement"]   = metrics_with["iou"] - metrics_without["iou"]

        result["f1_with_mask"]      = metrics_with["f1"]
        result["f1_without_mask"]   = metrics_without["f1"]
        result["f1_improvement"]    = metrics_with["f1"] - metrics_without["f1"]

    return result