一.IOU理解

在语义分割的问题中,交并比就是该类的真实标签和预测值的交和并的比值

单类的交并比可以理解为下图:

TP: 预测正确,真正例,模型预测为正例,实际是正例
FP: 预测错误,假正例,模型预测为正例,实际是反例
FN: 预测错误,假反例,模型预测为反例,实际是正例
TN: 预测正确,真反例,模型预测为反例,实际是反例
IoU = TP / (TP + FN + FP)

二.MIoU

MIOU就是该数据集中的每一个类的交并比的平均,计算公式如下:
Pij表示将i类别预测为j类别。

三.混淆矩阵

1.原理

以西瓜书上的图为例:

举一个简单的例子,假设有一个四种类别的分割实例,其混淆矩阵如下:

每一行之和是该类的真实样本数量,每一列之和是预测为该类的样本数量。第一行代表有20个实际为类1的样本被分为类1,有2个实际为类1的样本被分为类2,有1个实际为类1的样本被分为类3,有1个实际为类1的样本被分为类4。

2.代码

先介绍一个函数np.bincount。

其大致的意思是,给一个向量x,x中最大的元素记为j,返回一个向量1行j+1列的向量y,y[i]代表i在x中出现的次数。

x中最大的数为7,那么它的索引值为0->7
x = np.array([0, 1, 1, 3, 2, 1, 7])
索引0出现了1次,索引1出现了3次......索引5出现了0次......
np.bincount(x)
因此,输出结果为:array([1, 3, 1, 1, 0, 0, 0, 1])

如果minlength被指定,那么输出数组中的索引至少为它指定的数。即下标为0->minlength-1

我们可以看到x中最大的数为3,那么它的索引值为0->3
x = np.array([3, 2, 1, 3, 1])
本来bin的数量为4,现在我们指定了参数为7,因此现在bin的数量为7,所以现在它的索引值为0->6
np.bincount(x, minlength=7)
因此,输出结果为:array([0, 2, 1, 2, 0, 0, 0])

再来看混淆矩阵计算的代码

'''
产生n×n的分类统计表
参数a:标签图(转换为一行输入),即真实的标签
参数b:score层输出的预测图(转换为一行输入),即预测的标签
参数n:类别数
'''
def fast_hist(a, b, n):#k为掩膜(去除了255这些点(即标签图中的白色的轮廓),其中的a>=0是为了防止bincount()函数出错)k = (a >= 0) & (a < n) return np.bincount(n * a[k].astype(int) + b[k], minlength=n**2).reshape(n, n)

输入a为标签图的向量,b为预测出的向量。n是类别个数。以如下这个例子举列,左边为真实的标签图,右边为预测的结果标签。

a=np.array([0,1,0,2,1,0,2,2,1])
b=np.array([0,2,0,2,1,0,1,2,1])
k = (a >= 0) & (a < 3)

k:
array([ True, True, True, True, True, True, True, True, True])
k的作用是防止出错,确保标签的分类都包含在n的类别中

n=3
n * a[k].astype(int)
b[k]
y=n * a[k].astype(int) + b[k]

array([0, 3, 0, 6, 3, 0, 6, 6, 3])
array([0, 2, 0, 2, 1, 0, 1, 2, 1])
y:
array([0, 5, 0, 8, 4, 0, 7, 8, 4])

x=np.bincount(n * a[k].astype(int) + b[k], minlength=n**2).reshape(n, n)

x:
array([[3, 0, 0],
[0, 2, 1],
[0, 1, 2]], dtype=int64)

混淆矩阵如下图:

这里为什么要先对真实标签*n然后加上预测标签,再进行bincount。个人理解:
对真实标签*3可以将最后的结果每三个看成一组,从前到后分别代表该类真实为i类别,预测为0,1,2类别的个数,方便最后resize成3*3。
以真实标签中的0类别为例,真实标签中的0x3后还是0,与预测标签对位相加后,如果预测的也是0,那结果也是0,通过bincount,得到的最终向量第一个数是相加向量中0的个数,也就是代表预测为0真实也为0的个数。如果预测的是1,0x3+1=1,通过bincount会统计所有为1的个数放在结果的第二位,代表真实为0预测为1的个数。
其他分类同理。

四.利用混淆矩阵求iou和miou

计算每一个分类的iou代码,参数hist是混淆矩阵

def per_class_iu(hist):# 矩阵的对角线上的值组成的一维数组/矩阵的所有元素之和,返回值形状(n,)return np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist))

mIOU就是每一个类的IOU的平均,所以只需要对每一个类都按照上面计算IOU,再求平均获得mIOU就行了
计算miou代码

np.mean(per_class_iu(hist)

通过该矩阵可以计算
IoU类别0 = 3 / (3 + 0 + 0 + 0 + 0) = 1
IoU类别1 = 2 / (0 + 2 + 1 + 0 + 1) = 0.5
IoU类别2 = 2 / (0 + 1 + 2 + 0 + 1) = 0.5
MIoU = sum(IoUi) / 类别数 = (1 + 0.5 + 0.5) / 3 = 0.67

实际项目中的代码

# 设标签宽W,长H
def fast_hist(a, b, n):#--------------------------------------------------------------------------------##   a是转化成一维数组的标签,形状(H×W,);b是转化成一维数组的预测结果,形状(H×W,)#--------------------------------------------------------------------------------#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)  def per_class_iu(hist):return np.diag(hist) / np.maximum((hist.sum(1) + hist.sum(0) - np.diag(hist)), 1) def per_class_PA(hist):return np.diag(hist) / np.maximum(hist.sum(1), 1) def compute_mIoU(gt_dir, pred_dir, png_name_list, num_classes, name_classes):  print('Num classes', num_classes)  #-----------------------------------------##   创建一个全是0的矩阵,是一个混淆矩阵#-----------------------------------------#hist = np.zeros((num_classes, num_classes))#------------------------------------------------##   获得验证集标签路径列表,方便直接读取#   获得验证集图像分割结果路径列表,方便直接读取#------------------------------------------------#gt_imgs     = [join(gt_dir, x + ".png") for x in png_name_list]  pred_imgs   = [join(pred_dir, x + ".png") for x in png_name_list]  #------------------------------------------------##   读取每一个(图片-标签)对#------------------------------------------------#for ind in range(len(gt_imgs)): #------------------------------------------------##   读取一张图像分割结果,转化成numpy数组#------------------------------------------------#pred = np.array(Image.open(pred_imgs[ind]))  #------------------------------------------------##   读取一张对应的标签,转化成numpy数组#------------------------------------------------#label = np.array(Image.open(gt_imgs[ind]))  # 如果图像分割结果与标签的大小不一样,这张图片就不计算if len(label.flatten()) != len(pred.flatten()):  print('Skipping: len(gt) = {:d}, len(pred) = {:d}, {:s}, {:s}'.format(len(label.flatten()), len(pred.flatten()), gt_imgs[ind],pred_imgs[ind]))continue#------------------------------------------------##   对一张图片计算21×21的hist矩阵,并累加#------------------------------------------------#hist += fast_hist(label.flatten(), pred.flatten(),num_classes)  # 每计算10张就输出一下目前已计算的图片中所有类别平均的mIoU值if ind > 0 and ind % 10 == 0:  print('{:d} / {:d}: mIou-{:0.2f}; mPA-{:0.2f}'.format(ind, len(gt_imgs),100 * np.nanmean(per_class_iu(hist)),100 * np.nanmean(per_class_PA(hist))))#------------------------------------------------##   计算所有验证集图片的逐类别mIoU值#------------------------------------------------#mIoUs   = per_class_iu(hist)mPA     = per_class_PA(hist)#------------------------------------------------##   逐类别输出一下mIoU值#------------------------------------------------#for ind_class in range(num_classes):print('===>' + name_classes[ind_class] + ':\tmIou-' + str(round(mIoUs[ind_class] * 100, 2)) + '; mPA-' + str(round(mPA[ind_class] * 100, 2)))#-----------------------------------------------------------------##   在所有验证集图像上求所有类别平均的mIoU值,计算时忽略NaN值#-----------------------------------------------------------------#print('===> mIoU: ' + str(round(np.nanmean(mIoUs) * 100, 2)) + '; mPA: ' + str(round(np.nanmean(mPA) * 100, 2)))  return mIoUs

参考博文:
https://blog.csdn.net/sinat_29047129/article/details/103642140
https://blog.csdn.net/u012370185/article/details/94409933
https://blog.csdn.net/qq_21368481/article/details/80424754
https://blog.csdn.net/xlinsist/article/details/51346523
https://blog.csdn.net/weixin_44791964/article/details/107687970

语义分割指标---MIoU详细介绍(原理及代码)相关推荐

  1. 憨批的语义分割重制版2——语义分割评价指标mIOU的计算

    憨批的语义分割重制版2--语义分割评价指标mIOU的计算 注意事项 学习前言 什么是mIOU mIOU的计算 1.计算混淆矩阵: 2.计算IOU: 3.计算mIOU: 计算miou 注意事项 这是针对 ...

  2. [转载] python中pass的使用_Python pass详细介绍及实例代码

    参考链接: Python pass语句 Python pass详细介绍及实例代码 Python pass的用法: 空语句 do nothing 保证格式完整 保证语义完整 以if语句为例,在c或c++ ...

  3. 基于RGB-D的语义分割和目标检测介绍

    寒假的时候看了一篇论文--Multimodal Neural Networks: RGB-D for Semantic Segmentation and Object Detection这篇论文是20 ...

  4. 语义分割概念及应用介绍

    近年来,以深度学习为中心的机器学习技术引起了人们的关注.比如自动驾驶汽车已经逐渐成为可能,但在整个深度学习过程,需要算法识别和学习作为原始数据提供的图像,在这一过程中,应用到了语义分割技术.下面让我们 ...

  5. 语义分割评价指标mIOU

    mIOU定义 Mean Intersection over Union(MIoU,均交并比),为语义分割的标准度量.其计算两个集合的交集和并集之比,在语义分割问题中,这两个集合为真实值(ground ...

  6. tensorflow语义分割计算mIoU时忽略某一类别

    在做语义分割的时候,有不少数据集中的部分类别是我们不想让其参与mIoU计算的.tensorflow忽略某一类别计算mIoU的方法网上比较少.经过阅读tensorflow文档,总结出一下求解方法: 数据 ...

  7. 场景解析和语义分割区别_语义分割概念及应用介绍

    摘要: 一份关于语义分割的基本概述,涵盖语义分割的特征和可能的用途,包括地质检测.自动驾驶.面部识别等. 近年来,以深度学习为中心的机器学习技术引起了人们的关注.比如自动驾驶汽车已经逐渐成为可能,但在 ...

  8. OpenCV语义分割semantic segmentation的实例(附完整代码)

    OpenCV语义分割semantic segmentation的实例 OpenCV语义分割semantic segmentation的实例 OpenCV语义分割semantic segmentatio ...

  9. php mysql 字段自增_MySQL自增字段取值的详细介绍(附代码)

    本篇文章给大家带来的内容是关于MySQL自增字段取值的详细介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 1 前言 本文来自回答思否网友的一个问题,这个网友新建了一张表 ...

最新文章

  1. Science:微生物组“淘金热”,从人体中发现新型抗菌剂
  2. 添加背景音乐(解决苹果手机不能自动播放问题)
  3. ACE前摄器Proactor模式
  4. boost::copy相关的测试程序
  5. 使用Adaptive cards来构建Teams app的界面
  6. 从MAC缓存表中我们看到的问题
  7. 树莓派 树莓派 编c++_树莓派6年
  8. ASP.NET之SqlBulkCopy
  9. tinymce引入后未显示_继金博大后再弃一子!大商接连关闭在郑亏损店面,未来或布局高端购物中心...
  10. 【报告分享】2019互联网大会大佬演讲实录 (附11个演讲文档下载链接)
  11. .gitignore和“以下未跟踪的工作树文件将被签出覆盖”
  12. 知名IT公司的年度大会合集
  13. mysql-proxy负载均衡
  14. Idea的svn新建分支,切换分支,合并分支
  15. 商标有效期、续展期、宽展期分别是什么意思?
  16. 算法 + 算法 = 新算法
  17. conemu 打开wsl 报错
  18. 十六进制转字符串,字符串转十六进制,相互转换
  19. 什么是微信商城?如何微商城?
  20. 实习随笔2(独自乘车南下深圳)

热门文章

  1. java正整数分解因数_java将一个正整数分解质因数
  2. 假设计算机字长为8位 采用补码表示,假设某计算机的字长为8位,则十进制数(-75)10的补码表示为()。 - 问答库...
  3. 牛客题——点击消除(go)
  4. 2020年司钻(井下)考试申请表及司钻(井下)复审模拟考试
  5. srs直播 java开发,使用 SRS/OBS/VLC 快速搭建直播服务系统
  6. PHP税前税后,请问下大家 怎么根据税后工资1万元推算出税前工资是多少
  7. 惠普打印机2132故障灯大全图解_绝对干货!二手打印机选购攻略!
  8. 解决word文件由于扩展名不匹配问题
  9. idea中文件被Mark as Plain Text后恢复
  10. [转载]神奇的数据挖掘