Dice coefficient Python与Julia实现

2020年3月6日 4086点热度 1人点赞 0条评论

Hello everyone! 这篇文章将介绍Dice coefficient以及其实现

Introduction

Dice coefficient 是 Lee R. Dice 在1945年为评估生物种群提出的一种度量方法[1]。后来不同领域的学者都将其引入到自己的专业。这里,我将介绍Dice codfficient 在图像分割领域作为评价指标的理解与实现。

Segmentation

图像分割包含有语义分割、示例分割。在语义分割中,我们需要对给定的图片做如下处理:
- 标记出所有属于背景类别的点。
- 标记出属于我们关心类别的所有点。

通常的分割方法有:
- based on threshold
- region growing
- interactive segmenation
- gradient based
- classifier
- CNN (Unet)[3]

一个例子

现在我们要对下图分割出鱼和背景。

Image

渔业专家给出的ground truth 是下图A

GroundTruth

我们计算出的结果是下图B

Pred
我们可以看到B图与A图是有差距的,在鱼尾部的效果不好,没有分割出凸起部位。那么我们该如何评价这两者差距呢?
最初步的想法是计算准确率:
Accuracy=(TP+FN)/(TP+FN+FP+FN)
或者召回率
Recall (=Sensitivity)=TP/(TP+FN)
或者精度
Precision=TP/(TP+FP)
以及F-score (sometimes called F-factoror F1 measure)
=2* precision* recall/(precision+recall)

此时,引入一个和以上评价指标类似的 Dice coefficent
s=\frac{2|X \cap Y|}{|X|+|Y|}
我们可以借助两个圆A和B理解上面的公式。对于两个图像,如果没有重叠的部分,则Dice coefficient = 0. 也就是说,如果分割的目标真实区域和预测区域没有任何交集,则意味着在这个区域上的分割失败。但是,如果有重叠部分 A \cap B, 则说明这部分重叠区域是分割正确的。我们将这部分区域面积的2倍与两个圆和的比值设为Dice coefficient. 此时:0<DSC<1. 如果两个圆完全重合,则Dice coefficient = 1, 这意味着分割很成功。
DiceScore
This figure is copyright by ] Zou, Kelly H. et al.[2]

这里我们给出计算两个图像Dice Coefficient 的 Python代码

def dice_coef(y_true, y_pred):
    smooth = 1
    y_true_f = y_true.flatten()
    y_pred_f = y_pred.flatten()
    intersection = np.sum(y_true_f * y_pred_f)
    return (2. * intersection + smooth) / (np.sum(y_true_f) + np.sum(y_pred_f) + smooth)

如果我们对几百张图片进行了分割,我们可以对每个图像计算Dice coefficient后,求平均。这里也给出计算一组图像的平均Dice coefficient代码

def dice_average_sets(y_true, y_pred):
    assert y_true.shape[0]==y_pred.shape[0], "you should use same size data"
    dice = []
    for i in range(y_true.shape[0]):
        dice.append(dice_coef(y_true[i], y_pred[i]))
    print(np.mean(dice))
    return dice

另外,我们也给出对应的Julia代码。

function dice_coef(y_true, y_pred)
    smooth = 1
    y_true_f = vec(y_true)
    y_pred_f = vec(y_pred)
    intersection = dot(y_true_f, y_pred_f)
    return (2. * intersection + smooth) / (sum(y_true_f) + sum(y_pred_f) + smooth)
end
function DiceCoefficientAverage(y_true, y_pred)
    if size(y_true)[1]!=size(y_pred)[1]
        println("you should use same size data")
        return -1
    end
    dice = []
    for i in 1:size(y_true)[1]
        append!(dice, dice_coef(y_true[i,:,:], y_pred[i,:,:]))
    end
    print(mean(dice))
end

实验

在一个针对前面提到的鱼类HTS图像分割问题。我们使用Julia和Python代码分别计算,发现python的代码竟然比Julia的快。

[1] Dice, Lee R. "Measures of the amount of ecologic association between species." Ecology 26.3 (1945): 297-302.
[2] Zou, Kelly H. et al. “Statistical validation of image segmentation quality based on a spatial overlap index.” Academic radiology 11 2 (2004): 178-89 .
[3] Ronneberger, Olaf, Philipp Fischer, and Thomas Brox. "U-net: Convolutional networks for biomedical image segmentation." International Conference on Medical image computing and computer-assisted intervention. Springer, Cham, 2015.

Dong Wang

A final year master's student in computer science at Uppsala University in Sweden. I am interested in deep learning, computer vision, and optimization. I am actively looking for Ph.D. position.

文章评论