Spaces:
Sleeping
Sleeping
| """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 | |