前言

现存其实已经有很多博客实现了这个代码,但是可能不完整或者不能直接用于测试集的指标计算,这里简单概括一下。

一些概念、代码参考: [1] 憨批的语义分割9——语义分割评价指标mIOU的计算

[2]【语义分割】评价指标:PA、CPA、MPA、IoU、MIoU详细总结和代码实现(零基础从入门到精通系列!)

[3] 【语义分割】评价指标总结及代码实现

混淆矩阵

语义分割的各种评价指标都是基于混淆矩阵来的。

对于一个只有背景0和目标1的语义分割任务来说,混淆矩阵可以简单理解为:

TP(1被认为是1) FP(0被认为是1)
FN(1被认为是0) TN(0被认为是0)

各种指标的计算

1. 像素准确率 PA =(TP+TN)/(TP+TN+FP+FN)

2. 类别像素准确率 CPA = TP / (TP+FP)

3. 类别平均像素准确率 MPA = (CPA1+...+CPAn)/ n

4. 交并比 IoU = TP / (TP+FP+FN)

5. 平均交并比 MIoU = (IoU1+...+IoUn) / n

6. 频权交并比 FWIoU =  [ (TP+FN) / (TP+FP+TN+FN) ] * [ TP / (TP + FP + FN) ]

代码实现

"""
https://blog.csdn.net/sinat_29047129/article/details/103642140
https://www.cnblogs.com/Trevo/p/11795503.html
refer to https://github.com/jfzhang95/pytorch-deeplab-xception/blob/master/utils/metrics.py
"""
import numpy as np
import os
from PIL import Image
__all__ = ['SegmentationMetric']"""
confusionMetric
P\L     P    NP      TP    FPN      FN    TN"""class SegmentationMetric(object):def __init__(self, numClass):self.numClass = numClassself.confusionMatrix = np.zeros((self.numClass,) * 2) # 混淆矩阵n*n,初始值全0# 像素准确率PA,预测正确的像素/总像素def pixelAccuracy(self):# return all class overall pixel accuracy# acc = (TP + TN) / (TP + TN + FP + TN)acc = np.diag(self.confusionMatrix).sum() / self.confusionMatrix.sum()return acc# 类别像素准确率CPA,返回n*1的值,代表每一类,包括背景def classPixelAccuracy(self):# return each category pixel accuracy(A more accurate way to call it precision)# acc = (TP) / TP + FPclassAcc = np.diag(self.confusionMatrix) / np.maximum(self.confusionMatrix.sum(axis=1),1)return classAcc# 类别平均像素准确率MPA,对每一类的像素准确率求平均def meanPixelAccuracy(self):classAcc = self.classPixelAccuracy()meanAcc = np.nanmean(classAcc)return meanAcc# MIoUdef meanIntersectionOverUnion(self):# Intersection = TP Union = TP + FP + FN# IoU = TP / (TP + FP + FN)intersection = np.diag(self.confusionMatrix)union = np.maximum(np.sum(self.confusionMatrix, axis=1) + np.sum(self.confusionMatrix, axis=0) - np.diag(self.confusionMatrix), 1)IoU = intersection / unionmIoU = np.nanmean(IoU)return mIoU# 根据标签和预测图片返回其混淆矩阵def genConfusionMatrix(self, imgPredict, imgLabel):# remove classes from unlabeled pixels in gt image and predictmask = (imgLabel >= 0) & (imgLabel < self.numClass)label = self.numClass * imgLabel[mask].astype(int) + imgPredict[mask]count = np.bincount(label, minlength=self.numClass ** 2)confusionMatrix = count.reshape(self.numClass, self.numClass)return confusionMatrixdef Frequency_Weighted_Intersection_over_Union(self):# FWIOU =     [(TP+FN)/(TP+FP+TN+FN)] *[TP / (TP + FP + FN)]freq = np.sum(self.confusionMatrix, axis=1) / np.sum(self.confusionMatrix)iu = np.diag(self.confusionMatrix) / (np.sum(self.confusionMatrix, axis=1) + np.sum(self.confusionMatrix, axis=0) -np.diag(self.confusionMatrix))FWIoU = (freq[freq > 0] * iu[freq > 0]).sum()return FWIoU# 更新混淆矩阵def addBatch(self, imgPredict, imgLabel):assert imgPredict.shape == imgLabel.shape # 确认标签和预测值图片大小相等self.confusionMatrix += self.genConfusionMatrix(imgPredict, imgLabel)# 清空混淆矩阵def reset(self):self.confusionMatrix = np.zeros((self.numClass, self.numClass))def old():imgPredict = np.array([0, 0, 0, 1, 2, 2])imgLabel = np.array([0, 0, 1, 1, 2, 2])metric = SegmentationMetric(3)metric.addBatch(imgPredict, imgLabel)acc = metric.pixelAccuracy()macc = metric.meanPixelAccuracy()mIoU = metric.meanIntersectionOverUnion()print(acc, macc, mIoU)def evaluate1(pre_path, label_path):acc_list = []macc_list = []mIoU_list = []fwIoU_list = []pre_imgs = os.listdir(pre_path)lab_imgs = os.listdir(label_path)for i, p in enumerate(pre_imgs):imgPredict = Image.open(pre_path+p)imgPredict = np.array(imgPredict)# imgPredict = imgPredict[:,:,0]imgLabel = Image.open(label_path+lab_imgs[i])imgLabel = np.array(imgLabel)# imgLabel = imgLabel[:,:,0]metric = SegmentationMetric(2) # 表示分类个数,包括背景metric.addBatch(imgPredict, imgLabel)acc = metric.pixelAccuracy()macc = metric.meanPixelAccuracy()mIoU = metric.meanIntersectionOverUnion()fwIoU = metric.Frequency_Weighted_Intersection_over_Union()acc_list.append(acc)macc_list.append(macc)mIoU_list.append(mIoU)fwIoU_list.append(fwIoU)# print('{}: acc={}, macc={}, mIoU={}, fwIoU={}'.format(p, acc, macc, mIoU, fwIoU))return acc_list, macc_list, mIoU_list, fwIoU_listdef evaluate2(pre_path, label_path):pre_imgs = os.listdir(pre_path)lab_imgs = os.listdir(label_path)metric = SegmentationMetric(2)  # 表示分类个数,包括背景for i, p in enumerate(pre_imgs):imgPredict = Image.open(pre_path+p)imgPredict = np.array(imgPredict)imgLabel = Image.open(label_path+lab_imgs[i])imgLabel = np.array(imgLabel)metric.addBatch(imgPredict, imgLabel)return metricif __name__ == '__main__':pre_path = './pre_path/'label_path = './label_path/'# 计算测试集每张图片的各种评价指标,最后求平均acc_list, macc_list, mIoU_list, fwIoU_list = evaluate1(pre_path, label_path)print('final1: acc={:.2f}%, macc={:.2f}%, mIoU={:.2f}%, fwIoU={:.2f}%'.format(np.mean(acc_list)*100, np.mean(macc_list)*100,np.mean(mIoU_list)*100, np.mean(fwIoU_list)*100))# 加总测试集每张图片的混淆矩阵,对最终形成的这一个矩阵计算各种评价指标metric = evaluate2(pre_path, label_path)acc = metric.pixelAccuracy()macc = metric.meanPixelAccuracy()mIoU = metric.meanIntersectionOverUnion()fwIoU = metric.Frequency_Weighted_Intersection_over_Union()print('final2: acc={:.2f}%, macc={:.2f}%, mIoU={:.2f}%, fwIoU={:.2f}%'.format(acc*100, macc*100, mIoU*100, fwIoU*100))

说明

1. 使用上述代码时只需修改pre_path和label_path即可。label_path是真实标签的路径,为8位图;pre_path是训练好模型后,测试集生成的分割结果的路径,也是8位图。

metric = SegmentationMetric(2) 中,2表示的是该分割图的类别总数,包含背景,需对应修改。

2. 上述给出了两种指标的计算方式。

evaluate1是对测试集中产生的每张预测图片都计算对应的各种指标,最后对所有图片的结果进行求均值;

evaluate2是把测试集中产生的每张预测图片的混淆矩阵都加在一起,成为一个整个的混淆矩阵,最后对这一个矩阵求各种指标。

3. 我的测试结果如下:

final1: acc=93.68%, macc=79.05%, mIoU=69.85%, fwIoU=89.09%
final2: acc=93.68%, macc=78.72%, mIoU=70.71%, fwIoU=88.88%

可以看到,两种计算方法的结果在PA上是相等的,因为都是 正确的像素/总像素 ,不管是先加总再除还是先除再取平均结果都是相同的;而其他指标结果值略有不同。

一般论文中使用的是第2种,当图片本身为1600x1200时,无论是直接对原图进行评估还是将其裁剪成12张400x400大小图片进行评估,第2种的计算结果相等,而第1种结果不同。

4. 如果要打印每个类别的IoU或PA,在对应方法中返回即可。

语义分割各种评价指标实现相关推荐

  1. 【语义分割】评价指标:PA、CPA、MPA、IoU、MIoU详细总结和代码实现(零基础从入门到精通系列!)

    文章目录 引言 1 混淆矩阵 2 语义分割 PA:像素准确率 CPA:类别像素准确率 MPA:类别平均像素准确率 IoU:交并比 MIoU:平均交并比 3 综合实例 步骤一:输入真实.预测图片 步骤二 ...

  2. 【语义分割】评价指标代码函数:np.sum()、np.nansum()、np.nanmean()、np.diag()、np.bincount()

    引言 本文针对: [语义分割]评价指标:PA.CPA.MPA.IoU.MIoU详细总结和代码实现(零基础从入门到精通系列!)中实现评价指标代码里相关函数进行补充说明,包括:np.sum().np.na ...

  3. 语义分割的评价指标——MIoU

    语义分割的评价指标--MIoU 前言 代码 前言 MIoU(Mean Intersection over Union)是语义分割的一个评价指标,表示平均交并比,即数据集上每一个类别的IoU值的平均. ...

  4. 语义分割之评价指标MIoU介绍

    预备知识 我们在进行语义分割结果评价的时候,常常将预测出来的结果分为四个部分:True Positive,False Positive,True Negative,False Negative,其中n ...

  5. 语义分割的评价指标(OA, F1 score)计算(不使用sklearn)

    混淆矩阵(confusion_matrix)是由预测值和标签值组成的二维矩阵,共n行n列.n表示class类别数. 二分类 图片源自https://blog.csdn.net/Orange_Spott ...

  6. 图像语义分割及常用评价指标

    语义分割学习记录 语义分割概述 图像分类(image classification) 目标检测(object detection) 语义分割(semantic segmentation) 实例分割(i ...

  7. 语义分割 评价指标(global_acc, mean_acc, mean_iou)等numpy实现

    语义分割常见评价指标global_acc, mean_acc, mean_iou计算,个人学习记录,仅供参考. 一.理论计算 假设真实标签为: 预测标签为: 则手动列出混淆矩阵可得: 1.1 全局准确 ...

  8. 图像语义分割python_遥感图像语义分割常用精度指标及其python实现(支持多类)

    前言 在介绍个精度指标前我们先来明确以下几个概念,对应的示意图如下图所示:TP(True Positive):分类准确的正类,意思是预测结果为正类,实际上是正类. FP(False Positive) ...

  9. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task4:评价函数与损失函数

    [天池赛事]零基础入门语义分割-地表建筑物识别 Task1:赛题理解与 baseline(3 天) – 学习主题:理解赛题内容解题流程 – 学习内容:赛题理解.数据读取.比赛 baseline 构建 ...

最新文章

  1. 一条推文卖出 290 万美元天价?网友:我竟是隐藏的富翁
  2. 七日Python之路--第八天
  3. 机器学习笔记:非负矩阵分解问题 NMF
  4. Ubuntu安装VMware Tools的方法
  5. CH - 0304 IncDec Sequence(差分+思维)
  6. SAP Spartacus自定义指令cxOutlet的工作原理
  7. react实现多行文本超出加省略号
  8. 预测:小程序入口预测汇总(8种可能)
  9. 为什么要返回function_宇宙飞船返回时,为什么要冒着烧毁的风险加速穿过大气层?...
  10. 艾媒2018年度手机输入法报告出炉:百度输入法是语音识别最准的输入法
  11. 2018青岛ICPC ZOJ 4061: Magic Multiplication(模拟)
  12. 视频录制直播软件——OBS(录制MP4文件)
  13. 【LINUX】自己整理的干货,拿去看吧,不谢!!!。。。。。。。。。。。。
  14. JFrame中添加背景音乐
  15. 大言不惭 swank? talk about sth or speak too confidently
  16. word文档自动保存方法
  17. Mathematica解一个精巧的差分方程
  18. 自动化测试 - 12306火车票网站自动登录工具
  19. linux系统——管道
  20. 世界各国国旗及国家名称

热门文章

  1. 如何教你真正的懂得色温?
  2. 技术是可以量化的,稳定性性能和资产个数
  3. Mac 上必备的常用软件,你值得拥有
  4. Vue接入Google Adsense
  5. 我的helloworld
  6. 单词长度和GPS数据处理——程序设计入门C语言
  7. wps怎么把字缩到最小_wps文字怎么把空行缩小
  8. 一条 Select 语句 在 Postgresql 中的执行链路
  9. SQLite 数据库操作
  10. 如何在Axure中设置根据标签导航切换页面?