语义分割MIoU代码解析

MIoU计算
具体代码可去Bubbliiiing大神的仓库获取,主体逻辑代码如下:

首先拿到所有的label和pre

gt_imgs     = [os.path.join(pred_dir, x.split('\\')[-1].split('.')[0] + "_label.png") for x in png_name_list]
pred_imgs   = [os.path.join(pred_dir, x.split('\\')[-1].split('.')[0] + "_pre.png") for x in png_name_list]

然后读取每个标签-预测图像对

for ind in range(len(gt_imgs)): 
    pred = np.array(Image.open(pred_imgs[ind]))
    label = np.array(Image.open(gt_imgs[ind]))  

对一个图片计算n×n的hist矩阵,n表示预测类别,我这次用的是5。

hist += fast_hist(label.flatten(), pred.flatten(), num_classes) 
def fast_hist(a, b, n):
    #  剔除异常值,比如分隔5类,标签和预测值的范围应该是0~4
    k = (a >= 0) & (a < n)
    #  np.bincount计算了从0到n**2-1这n**2个数中每个数出现的次数,返回值形状(n, n)
    return np.bincount(n * a[k].astype(int) + b[k], minlength=n ** 2).reshape(n, n)  

经过计算,就可以得到所有标签-预测图像对中,0到n方-1这n方个数中每个数出现的次数。

这是一种很巧妙的做法,这个矩阵对角线上的数字,意味着每个类别预测值和标签值完全相同的个数。

如果标签值是0,那么n×0=0,0+b的范围是0~4,那么经过统计,取值为0的个数就是预测值和标签值都是0的个数,也就是预测正确的个数,其他都是预测错误的个数。这也就是hist的第一行。

如果标签值是1,那么n×1=5,5+b的范围是5~9,那么经过统计,取值为6的个数就是预测值和标签值都是1的个数,也就是预测正确的个数。这也就是hist的第二行。后面的以此类推。

计算交并比

def per_class_iu(hist):
    return np.diag(hist) / np.maximum((hist.sum(1) + hist.sum(0) - np.diag(hist)), 1) 

np.diag(hist) 取出矩阵 hist 的对角线上的元素,这些元素表示每个类别的真正例数量。

hist.sum(1) 是按行求和,得到每个预测类别的总数。

hist.sum(0) 是按列求和,得到每个真实类别的总数。

hist.sum(1) + hist.sum(0) - np.diag(hist) 计算的是并集的大小。

通过将真正例数量除以并集大小,并使用 np.maximum 来处理分母可能为 0 的情况,从而得到每个类别的 IoU 值。
结果为每个类别的IoU,在做平均即为mIoU。

计算准确率

def per_class_Precision(hist):
    return np.diag(hist) / np.maximum(hist.sum(0), 1) 

将真正例数量除以真实类别的总数,并使用 np.maximum 处理分母可能为 0 的情况,就得到了每个类别的精确率。

结果为每个类别的准确率

计算召回率

def per_class_PA_Recall(hist):
    return np.diag(hist) / np.maximum(hist.sum(1), 1) 

将真正例数量除以预测类别的总数,并通过 np.maximum 处理分母可能为 0 的情况,从而得到每个类别的召回率。
结果为每个类别的召回率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值