如何计算图像分割中的平均IU分数?

24
如何计算平均交并比(mean Intersection over Union,简称mean IU)分数,就像这篇论文中描述的那样?

Long, Jonathan, Evan Shelhamer和Trevor Darrell所撰写的"全卷积网络用于语义分割"。


1
参见:如何使用Python计算IoU - Martin Thoma
4个回答

34

每个类别的交叉并集(Intersection over Union,IU)得分如下:

真阳性 / (真阳性 + 假阳性 + 假阴性)

平均IU指的是所有类别的平均值。


关于论文中的符号表示:

  • n_cl:类别数量
  • t_i :类别i中像素总数
  • n_ij:被预测为属于类别j的类别i像素数量。因此对于类别i

    • n_ii:正确分类像素数量(真阳性)
    • n_ij:错误分类像素数量(假阳性)
    • n_ji:未正确分类像素数量(假阴性)

您可以在Pascak DevKit的这里找到直接计算此方法的Matlab代码。


@stochastic_zeitgeist 请查看这个链接 - Miki
3
我认为这仅适用于矩形边界框。对于不规则形状,我认为这个链接会起作用。 - stochastic_zeitgeist
2
如果我像这样计算数据集中每个图像的IOU:真正例 / (真正例 + 假正例 + 假负例),接下来该怎么办?我应该计算所有图像IOU的平均值吗?如果在某些图像上某些类别未出现且未被预测,则 I = 0U = 0,那么在计算IOU平均值时,我是否需要为每个类别单独制作“计数器”? - mrgloom
1
你需要在测试集中的所有图像上计算tp/(tp + fp + fn)。这意味着你需要为每个类别在测试集中的所有图像上累加tp、fp和fn,然后计算IoU。对每个单独图像的IoU结果取平均会导致错误的全局IoU。 - Marcel_marcel1991
“计算每个单独图像的IoU平均值”。我并不是在说这个。你需要计算每个类别中所有像素的IoU,然后取所有类别的平均IoU。 - Miki

16
 from sklearn.metrics import confusion_matrix  
 import numpy as np

 def compute_iou(y_pred, y_true):
     # ytrue, ypred is a flatten vector
     y_pred = y_pred.flatten()
     y_true = y_true.flatten()
     current = confusion_matrix(y_true, y_pred, labels=[0, 1])
     # compute mean iou
     intersection = np.diag(current)
     ground_truth_set = current.sum(axis=1)
     predicted_set = current.sum(axis=0)
     union = ground_truth_set + predicted_set - intersection
     IoU = intersection / union.astype(np.float32)
     return np.mean(IoU)

我在这里不得不使用 return np.nanmean,因为0可能是一个有效的混淆矩阵(我们正确地从未尝试预测任何东西,留下0的混淆)。 - lee penkman

2

这应该会有所帮助

def computeIoU(y_pred_batch, y_true_batch):
    return np.mean(np.asarray([pixelAccuracy(y_pred_batch[i], y_true_batch[i]) for i in range(len(y_true_batch))])) 

def pixelAccuracy(y_pred, y_true):
    y_pred = np.argmax(np.reshape(y_pred,[N_CLASSES_PASCAL,img_rows,img_cols]),axis=0)
    y_true = np.argmax(np.reshape(y_true,[N_CLASSES_PASCAL,img_rows,img_cols]),axis=0)
    y_pred = y_pred * (y_true>0)

    return 1.0 * np.sum((y_pred==y_true)*(y_true>0)) /  np.sum(y_true>0)

1
输出 y_pred 的形状为 n_classes*h*w,我们想将它们转换成一张单独的图像,其中像素值等于该像素处的类别,因此我们沿着类别轴取 arg max。 - stochastic_zeitgeist

0

可以使用jaccard_similarity_score(参见如何从分割掩模中找到IoU?)来获得与@Alex-zhai上面的代码相同的结果:

import numpy as np
from sklearn.metrics import jaccard_score

y_true = np.array([[0, 1, 1],
                   [1, 1, 0]])
y_pred = np.array([[1, 1, 1],
                   [1, 0, 0]])

labels = [0, 1]
jaccards = []
for label in labels:
    jaccard = jaccard_score(y_pred.flatten(),y_true.flatten(), pos_label=label)
    jaccards.append(jaccard)
print(f'avg={np.mean(jaccards)}')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接