混淆矩阵与miou代码

一、混淆矩阵

 

# 计算混淆矩阵
def generate_matrix(num_class,gt_image, pre_image):
    #正确的gt_mask
    mask = (gt_image >= 0) & (gt_image < num_class)  # ground truth中所有正确(值在[0, classe_num])的像素label的mask
    
    #gt_image[mask] 和 pre_image[mask]是一维数据
    label = num_class * gt_image[mask].astype('int') + pre_image[mask]
    # np.bincount计算了从0到n**2-1这n**2个数中每个数出现的次数,返回值形状(n, n)
    count = np.bincount(label, minlength=num_class ** 2)
    confusion_matrix = count.reshape(num_class, num_class)  # 一维到(n,n)
    return confusion_matrix

上面label是重点,它计算了在一维中对应于二维混淆矩阵中的位置。

在一维数据中 n * gt_class + pre_class 对应了二维矩阵中的 位置

eg:

ground truth和预测
pre = np.array([[0, 0, 0, 2],
                [0, 0, 2, 1],
                [1, 1, 1, 2],
                [1, 0, 1, 2]])


gt = np.array([[0, 0, 0, 2],
               [0, 0, 2, 1],
               [1, 1, 1, 0],
               [1, 0, 1, 2]])

res = generate_matrix(3,gt,pre)

函数中:

mask = (gt_image >= 0) & (gt_image < num_class)

mask:[[ True  True  True  True], [ True  True  True  True], [ True  True  True  True], [ True  True  True  True]]

label = num_class * gt_image[mask].astype('int') + pre_image[mask]

其中:gt_image[mask].astype('int')为 [0 0 0 2 0 0 2 1 1 1 1 0 1 0 1 2]

                                pre_image[mask]为[0 0 0 2 0 0 2 1 1 1 1 2 1 0 1 2]

从第一个数开始 ,gt_image值为0,pre_image值也为0,也就是  label[0] = 0 * 0 + 0  = 0 ,表示的是

在混淆矩阵中,

行代表真实类别,列代表预测的类别,矩阵中(x, y)位置的元素代表该张图片中真实类别为x,被预测为y的个数

通过0 * 0 先确定了为第一行,也就是真实值为0的哪类,然后+0 确定了列,也就是第一列,预测值也为0。依次计算。

得到 label = [0 0 0 8 0 0 8 4 4 4 4 2 4 0 4 8]

因为在混淆矩阵中统计的是次数,就通过

count = np.bincount(label, minlength=num_class ** 2)

来计算出0 - num_class ** 2 -1的个数,因为不能保证矩阵中最后一行,最后一列的元素出现过,所以需要指定minlength = num_class ** 2

关于bincount如何使用的可以看https://blog.csdn.net/xlinsist/article/details/51346523

最后得到count=[6 0 1 0 6 0 0 0 3]

confusion_matrix = count.reshape(num_class, num_class)

最后通过reshape把一维数据变为混淆矩阵就可以了

confusion_matrix = [[6 0 1],

                                   [0 6 0],

                                   [0 0 3]]

 二、miou

在计算miou之前,先看个函数

np.diag
import numpy as np

test1 = np.arange(1,4)
test2 = np.arange(1,10).reshape(3,3)


res1 = np.diag(test1)
res2 = np.diag(test2)

print("res1:",res1)
print("res2:",res2)

结果:

res1: [[1 0 0]
          [0 2 0]
          [0 0 3]]
res2: [1 5 9]

Process finished with exit code 0

1维数组时,会形成一个以一维数组为对角线元素的矩阵

二维矩阵时,输出为矩阵的对角线元素

IOU=TP/(FP+FN+TP)

 代码:

def miou(hist):

    iou = np.diag(hist) / (hist.sum(axis=1) + hist.sum(axis=0) - np.diag(hist))
    miou = np.nanmean(iou)

    return miou

 其中:

iou = np.diag(hist) / (hist.sum(axis=1) + hist.sum(axis=0) - np.diag(hist))

接着刚才混淆矩阵的例子:

得到的混淆矩阵为:

confusion_matrix = [[6 0 1],

                                   [0 6 0],

                                   [0 0 3]]

np.diag(hist)为[6 6 3]
hist.sum(axis=1)为[7 6 3]
hist.sum(axis=0)为[6 6 4]
hist.sum(axis=1) + hist.sum(axis=0) - np.diag(hist)为[7 6 4],减去np.diag(hist)是因为np.diag(hist)计算了两次,需要减去一次,才会得到并集。

最后 np.diag(hist) / (hist.sum(axis=1) + hist.sum(axis=0) - np.diag(hist)) =

                         [0.85714286,   1.  ,   0.75      ]

为每个分类的iou,

通过miou = np.nanmean(iou) 得到最后的miou为0.8690476190476191

最后完整代码:

import numpy as np

# 计算混淆矩阵
def generate_matrix(num_class,gt_image, pre_image):
    #正确的gt_mask
    mask = (gt_image >= 0) & (gt_image < num_class)  # ground truth中所有正确(值在[0, classe_num])的像素label的mask

    label = num_class * gt_image[mask].astype('int') + pre_image[mask]
    # np.bincount计算了从0到n**2-1这n**2个数中每个数出现的次数,返回值形状(n, n)
    count = np.bincount(label, minlength=num_class ** 2)
    confusion_matrix = count.reshape(num_class, num_class)  # (n, n)
    return confusion_matrix

def miou(hist):

    iou = np.diag(hist) / (hist.sum(axis=1) + hist.sum(axis=0) - np.diag(hist))
    miou = np.nanmean(iou)

    return miou


if __name__ == '__main__':

    pre = np.array([[0, 0, 0, 2],
                  [0, 0, 2, 1],
                  [1, 1, 1, 2],
                  [1, 0, 1, 2]])


    gt = np.array([[0, 0, 0, 2],
                  [0, 0, 2, 1],
                  [1, 1, 1, 0],
                  [1, 0, 1, 2]])
    
    #求混淆矩阵
    hist = generate_matrix(3,gt,pre)


    #画混淆矩阵热力图
    ax = plt.axes()
    class_names = ['person', 'dog', 'cat']
    sn.heatmap(hist, annot=True,
               annot_kws={"size": 10},
               xticklabels=class_names,
               yticklabels=class_names, ax=ax)
    ax.set_title('Confusion matrix')
    plt.savefig('./confusion.jpg')
    plt.show()

    #计算miou
    miou_res = miou(hist)
    print(miou_res)

结果:

混淆矩阵热力图:

 

miou:0.8690476190476191

参考链接:

1、https://blog.csdn.net/u012370185/article/details/94409933

2、 https://blog.csdn.net/fanzonghao/article/details/84622782

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值