Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import torch | |
| from src.losses import soft_skeletonize | |
| def binary_metrics(logits: torch.Tensor, target: torch.Tensor, threshold: float = 0.5) -> list[dict[str, float]]: | |
| pred = torch.sigmoid(logits) >= threshold | |
| target_b = target >= 0.5 | |
| dims = (1, 2, 3) | |
| tp = (pred & target_b).float().sum(dim=dims) | |
| fp = (pred & ~target_b).float().sum(dim=dims) | |
| fn = (~pred & target_b).float().sum(dim=dims) | |
| inter = tp | |
| union = (pred | target_b).float().sum(dim=dims) | |
| precision = tp / (tp + fp).clamp_min(1.0) | |
| recall = tp / (tp + fn).clamp_min(1.0) | |
| dice = (2.0 * inter) / (pred.float().sum(dim=dims) + target_b.float().sum(dim=dims)).clamp_min(1.0) | |
| iou = inter / union.clamp_min(1.0) | |
| rows = [] | |
| cldice_scores = cldice_metric(logits, target, threshold) | |
| for idx in range(logits.size(0)): | |
| rows.append( | |
| { | |
| "iou": float(iou[idx].item()), | |
| "dice": float(dice[idx].item()), | |
| "precision": float(precision[idx].item()), | |
| "recall": float(recall[idx].item()), | |
| "cldice": float(cldice_scores[idx].item()), | |
| } | |
| ) | |
| return rows | |
| def cldice_metric(logits: torch.Tensor, target: torch.Tensor, threshold: float = 0.5) -> torch.Tensor: | |
| pred = (torch.sigmoid(logits) >= threshold).float() | |
| target = (target >= 0.5).float() | |
| pred_skel = soft_skeletonize(pred, 20) | |
| target_skel = soft_skeletonize(target, 20) | |
| dims = (1, 2, 3) | |
| eps = 1.0 | |
| topology_precision = ((pred_skel * target).sum(dim=dims) + eps) / (pred_skel.sum(dim=dims) + eps) | |
| topology_sensitivity = ((target_skel * pred).sum(dim=dims) + eps) / (target_skel.sum(dim=dims) + eps) | |
| return (2.0 * topology_precision * topology_sensitivity) / (topology_precision + topology_sensitivity + 1e-6) | |