import numpy as np
np.seterr(divide='ignore',invalid='ignore')
def fast_hist(a, b, n): # a是转化成一维数组的标签,形状(H×W,);b是转化成一维数组的标签,形状(H×W,);n是类别数目,实数(在这里为19)
k = (a >= 0) & (a < n) # k是一个一维bool数组,形状(H×W,);目的是找出标签中需要计算的类别(去掉了背景)
return np.bincount(n * a[k].astype(int) + b[k], minlength=n ** 2).reshape(n, n) # np.bincount计算了从0到n**2-1这n**2个数中每个数出现的次数,返回值形状(n, n)
def per_class_iu(hist): # 分别为每个类别(在这里是19类)计算mIoU,hist的形状(n, n)
return np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist)) # 矩阵的对角线上的值组成的一维数组/矩阵的所有元素之和,返回值形状(n,)
def label_mapping(input, mapping): # 主要是因为CityScapes标签里面原类别太多,这样做把其他类别转换成算法需要的类别(共19类)和背景(标注为255)
output = np.copy(input) # 先复制一下输入图像
for ind in range(len(mapping)):
output[input == mapping[ind][0]] = mapping[ind][1] # 进行类别映射,最终得到的标签里面之后0-18这19个数加255(背景)
return np.array(output, dtype=np.int64) # 返回映射的标签
def compute_mIoU(label, pred, num_classes): # 计算mIoU的函数
"""
Compute IoU
"""
hist = np.zeros((num_classes, num_classes))#hist初始化为全零,在这里的hist的形状是[19, 19]
assert len(label.flatten()) == len(pred.flatten()) # 如果图像分割结果与标签的大小不一样,这张图片就不计算
hist += fast_hist(label.flatten(), pred.flatten(), num_classes) # 对一张图片计算19×19的hist矩阵,并累加
per_mIou = per_class_iu(hist) # 计算所有验证集图片的逐类别mIoU值
per_mIou_set = {}
per_mIou = np.around(per_mIou, decimals=4)
for index, per in enumerate(per_mIou):
per_mIou_set[index] = per
mIoU = np.nanmean(per_mIou)
mIoU = np.around(mIoU, decimals=4)
return mIoU, per_mIou_set
label = np.array([0,1,2,2,1,3,2])
pred = np.array([1,1,2,2,1,3,2])
out, per = compute_mIoU(label, pred, 4)
print(out, per)
12-08