Diff of /monai/metric.py [000000] .. [4e96d3]

Switch to unified view

a b/monai/metric.py
1
# Copyright (c) MONAI Consortium
2
# Licensed under the Apache License, Version 2.0 (the "License");
3
# you may not use this file except in compliance with the License.
4
# You may obtain a copy of the License at
5
#     http://www.apache.org/licenses/LICENSE-2.0
6
# Unless required by applicable law or agreed to in writing, software
7
# distributed under the License is distributed on an "AS IS" BASIS,
8
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
# See the License for the specific language governing permissions and
10
# limitations under the License.
11
12
import numpy as np
13
import torch
14
15
from monai.metrics.utils import do_metric_reduction
16
from monai.metrics.utils import get_mask_edges, get_surface_distance
17
18
from monai.metrics import CumulativeIterationMetric
19
20
21
class HausdorffScore(CumulativeIterationMetric):
22
    """
23
    Modify MONAI's HausdorffDistanceMetric for Kaggle UW-Madison GI Tract Image Segmentation
24
25
    """
26
27
    def __init__(
28
        self,
29
        reduction = "mean",
30
    ) -> None:
31
        super().__init__()
32
        self.reduction = reduction
33
34
    def _compute_tensor(self, pred, gt):
35
36
        return compute_hausdorff_score(pred, gt)
37
38
39
    def aggregate(self):
40
        """
41
        Execute reduction logic for the output of `compute_hausdorff_distance`.
42
43
        """
44
        data = self.get_buffer()
45
        # do metric reduction
46
        f, _ = do_metric_reduction(data, self.reduction)
47
        return f
48
49
def compute_directed_hausdorff(pred, gt, max_dist):
50
    if np.all(pred == gt):
51
        return 0.0
52
    if np.sum(pred) == 0:
53
        return 1.0
54
    if np.sum(gt) == 0:
55
        return 1.0
56
    (edges_pred, edges_gt) = get_mask_edges(pred, gt)
57
    surface_distance = get_surface_distance(edges_pred, edges_gt, distance_metric="euclidean")
58
    if surface_distance.shape == (0,):
59
        return 0.0
60
    dist = surface_distance.max()
61
62
    if dist > max_dist:
63
        return 1.0
64
    return dist / max_dist
65
66
def compute_hausdorff_score(pred, gt):
67
68
    y = gt.float().to("cpu").numpy()
69
    y_pred = pred.float().to("cpu").numpy()
70
71
    # hausdorff distance score
72
    batch_size, n_class = y_pred.shape[:2]
73
    spatial_size = y_pred.shape[2:]
74
    max_dist = np.sqrt(np.sum([l**2 for l in spatial_size]))
75
    hd_score = np.empty((batch_size, n_class))
76
    for b, c in np.ndindex(batch_size, n_class):
77
        hd_score[b, c] = 1 - compute_directed_hausdorff(y_pred[b, c], y[b, c], max_dist)
78
79
    return torch.from_numpy(hd_score)