frankkramer-lab / MIScnn

A framework for Medical Image Segmentation with Convolutional Neural Networks and Deep Learning
GNU General Public License v3.0
398 stars 116 forks source link

[Possible bug] compute_dice() in detailed_validation returns NaN when ground truth and prediction are the same #169

Open emmanuel-nwogu opened 1 year ago

emmanuel-nwogu commented 1 year ago

When gt and pd are exactly the same and filled with the same value val, compute_dice returns NaN for the classes that are not the value val. This is due to the resulting zero division at the line: dice = 2 * np.logical_and(pd, gt).sum() / (pd.sum() + gt.sum()). I believe it should return 1.0 since gt and pd are still exactly the same.

I wrote this up to demonstrate this and included a possible fix.

import numpy as np
import random

def compute_dice(truth, pred, classes, use_fix=True):
    dice_scores = []
    # Compute Dice for each class
    for i in range(classes):
        try:
            pd = np.equal(pred, i)
            gt = np.equal(truth, i)
            if use_fix and (pd == gt).all():
                dice_scores.append(1.0)
                continue
            dice = 2 * np.logical_and(pd, gt).sum() / (pd.sum() + gt.sum())
            dice_scores.append(dice)
        except ZeroDivisionError:
            dice_scores.append(0.0)
    # Return computed Dice scores
    return dice_scores

if __name__ == "__main__":
    image_shape = (4, 4)
    num_classes = 2
    val = random.randint(0, num_classes)

    gt = np.full(image_shape, val)
    pd = np.copy(gt)
    print(f"gt/pd: \n{gt}")
    dice_score = compute_dice(gt, pd, num_classes, use_fix=True)
    print(f"Dice scores: {dice_score}")scores