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

前言

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

FP(False Positive):被错分类为正类的负类,意思是实际为负类,但是却被预测为正类。

TN(True Negative):分类准确的负类,意思是预测结果为负类,实际上是负类。

FN(False Negative):被错分类为负类的正类,意思是实际为正类,但是却被预测为负类。

精度指标

1 精确率

精确率(Precision)就是被准确分类为正类的样本数与所有被分类为正类的样本数之比,意味着预测结果是正类的样本里具体有多少个样本真的是正类,计算方法如下式所示:

equation?tex=Precision+%3D+%5Cfrac%7BTP%7D%7BTP%2BFP%7D

2 召回率

召回率(Recall)就是被分为正类的样本数与测试数据集中的实际正类的样本数之比,意味着应该被分为正类的样本中会有多少是被正确分类出来,如下式所示:

equation?tex=Recall+%3D+%5Cfrac%7BTP%7D%7BTP%2BFN%7D

3 F1分数

我们希望精确率和召回率同时非常高。但实际上这两个指标是一对矛盾体,无法做到双高。如果想要找到二者之间的一个平衡点,我们就需要一个新的指标:F1分数(F1-Score)。F1分数同时考虑了查准率和查全率,让二者同时达到最高,取一个平衡。

equation?tex=F1+%3D+2%5Ctimes%5Cfrac%7BPrecision%5Ctimes+Recall%7D%7BPrecision%2BRecall%7D

4 交并比

交并比(Intersection-over-Union, IoU)是指实际类别样本和预测类别样本的交集和并集之比,即分类准确的正类样本数和分类准确的正类样本数与被错分类为负类的正类样本数以及被错分类为正类的负类之和的比值。

equation?tex=IoU+%3D+%5Cfrac%7BTP%7D%7BTP%2BFN%2BFP%7D

5 平均交并比

平均交并比(mean Intersection-over-Union, mIoU)是对每一类交并比求和平均的结果。

equation?tex=mIoU%3D%5Cfrac%7B%5Csum_%7Bi%7D%5E%7Bn%7D%7BIoU%7D%7D%7Bn%7D

6 频权交并比

频权交并比(Frequency Weighted Intersection-over-Union, FWIoU)是根据每一类出现的频率设置权重,权重乘以每一类的IoU并进行求和。

equation?tex=FWIoU+%3D+%5Cfrac%7BTP%2BFN%7D%7BTP%2BFP%2BTN%2BFN%7D+%2A+%5Cfrac%7BTP%7D%7BTP+%2B+FP+%2B+FN%7D

python实现

import numpy as np

import cv2

import os

"""混淆矩阵P\L P NP TP FPN FN TN"""

# 获取颜色字典

# labelFolder 标签文件夹,之所以遍历文件夹是因为一张标签可能不包含所有类别颜色

# classNum 类别总数(含背景)

def color_dict(labelFolder, classNum):

colorDict = []

# 获取文件夹内的文件名

ImageNameList = os.listdir(labelFolder)

for i in range(len(ImageNameList)):

ImagePath = labelFolder + "/" + ImageNameList[i]

img = cv2.imread(ImagePath).astype(np.uint32)

# 如果是灰度,转成RGB

if(len(img.shape) == 2):

img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB).astype(np.uint32)

# 为了提取唯一值,将RGB转成一个数

img_new = img[:,:,0] * 1000000 + img[:,:,1] * 1000 + img[:,:,2]

unique = np.unique(img_new)

# 将第i个像素矩阵的唯一值添加到colorDict中

for j in range(unique.shape[0]):

colorDict.append(unique[j])

# 对目前i个像素矩阵里的唯一值再取唯一值

colorDict = sorted(set(colorDict))

# 若唯一值数目等于总类数(包括背景)ClassNum,停止遍历剩余的图像

if(len(colorDict) == classNum):

break

# 存储颜色的BGR字典,用于预测时的渲染结果

colorDict_BGR = []

for k in range(len(colorDict)):

# 对没有达到九位数字的结果进行左边补零(eg:5,201,111->005,201,111)

color = str(colorDict[k]).rjust(9, '0')

# 前3位B,中3位G,后3位R

color_BGR = [int(color[0 : 3]), int(color[3 : 6]), int(color[6 : 9])]

colorDict_BGR.append(color_BGR)

# 转为numpy格式

colorDict_BGR = np.array(colorDict_BGR)

# 存储颜色的GRAY字典,用于预处理时的onehot编码

colorDict_GRAY = colorDict_BGR.reshape((colorDict_BGR.shape[0], 1 ,colorDict_BGR.shape[1])).astype(np.uint8)

colorDict_GRAY = cv2.cvtColor(colorDict_GRAY, cv2.COLOR_BGR2GRAY)

return colorDict_BGR, colorDict_GRAY

def ConfusionMatrix(numClass, imgPredict, Label):

# 返回混淆矩阵

mask = (Label >= 0) & (Label < numClass)

label = numClass * Label[mask] + imgPredict[mask]

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

confusionMatrix = count.reshape(numClass, numClass)

return confusionMatrix

def OverallAccuracy(confusionMatrix):

# 返回所有类的整体像素精度OA

# acc = (TP + TN) / (TP + TN + FP + TN)

OA = np.diag(confusionMatrix).sum() / confusionMatrix.sum()

return OA

def Precision(confusionMatrix):

# 返回所有类别的精确率precision

precision = np.diag(confusionMatrix) / confusionMatrix.sum(axis = 1)

return precision

def Recall(confusionMatrix):

# 返回所有类别的召回率recall

recall = np.diag(confusionMatrix) / confusionMatrix.sum(axis = 0)

return recall

def F1Score(confusionMatrix):

precision = np.diag(confusionMatrix) / confusionMatrix.sum(axis = 1)

recall = np.diag(confusionMatrix) / confusionMatrix.sum(axis = 0)

f1score = 2 * precision * recall / (precision + recall)

return f1score

def IntersectionOverUnion(confusionMatrix):

# 返回交并比IoU

intersection = np.diag(confusionMatrix)

union = np.sum(confusionMatrix, axis = 1) + np.sum(confusionMatrix, axis = 0) - np.diag(confusionMatrix)

IoU = intersection / union

return IoU

def MeanIntersectionOverUnion(confusionMatrix):

# 返回平均交并比mIoU

intersection = np.diag(confusionMatrix)

union = np.sum(confusionMatrix, axis = 1) + np.sum(confusionMatrix, axis = 0) - np.diag(confusionMatrix)

IoU = intersection / union

mIoU = np.nanmean(IoU)

return mIoU

def Frequency_Weighted_Intersection_over_Union(confusionMatrix):

# 返回频权交并比FWIoU

freq = np.sum(confusionMatrix, axis=1) / np.sum(confusionMatrix)

iu = np.diag(confusionMatrix) / (

np.sum(confusionMatrix, axis = 1) +

np.sum(confusionMatrix, axis = 0) -

np.diag(confusionMatrix))

FWIoU = (freq[freq > 0] * iu[freq > 0]).sum()

return FWIoU

#################################################################

# 标签图像文件夹

LabelPath = r"Data\test\label1"

# 预测图像文件夹

PredictPath = r"Data\test\predict1"

# 类别数目(包括背景)

classNum = 3

#################################################################

# 获取类别颜色字典

colorDict_BGR, colorDict_GRAY = color_dict(LabelPath, classNum)

# 获取文件夹内所有图像

labelList = os.listdir(LabelPath)

PredictList = os.listdir(PredictPath)

# 读取第一个图像,后面要用到它的shape

Label0 = cv2.imread(LabelPath + "//" + labelList[0], 0)

# 图像数目

label_num = len(labelList)

# 把所有图像放在一个数组里

label_all = np.zeros((label_num, ) + Label0.shape, np.uint8)

predict_all = np.zeros((label_num, ) + Label0.shape, np.uint8)

for i in range(label_num):

Label = cv2.imread(LabelPath + "//" + labelList[i])

Label = cv2.cvtColor(Label, cv2.COLOR_BGR2GRAY)

label_all[i] = Label

Predict = cv2.imread(PredictPath + "//" + PredictList[i])

Predict = cv2.cvtColor(Predict, cv2.COLOR_BGR2GRAY)

predict_all[i] = Predict

# 把颜色映射为0,1,2,3...

for i in range(colorDict_GRAY.shape[0]):

label_all[label_all == colorDict_GRAY[i][0]] = i

predict_all[predict_all == colorDict_GRAY[i][0]] = i

# 拉直成一维

label_all = label_all.flatten()

predict_all = predict_all.flatten()

# 计算混淆矩阵及各精度参数

confusionMatrix = ConfusionMatrix(classNum, predict_all, label_all)

precision = Precision(confusionMatrix)

recall = Recall(confusionMatrix)

OA = OverallAccuracy(confusionMatrix)

IoU = IntersectionOverUnion(confusionMatrix)

FWIOU = Frequency_Weighted_Intersection_over_Union(confusionMatrix)

mIOU = MeanIntersectionOverUnion(confusionMatrix)

f1ccore = F1Score(confusionMatrix)

for i in range(colorDict_BGR.shape[0]):

# 输出类别颜色,需要安装webcolors,直接pip install webcolors

try:

import webcolors

rgb = colorDict_BGR[i]

rgb[0], rgb[2] = rgb[2], rgb[0]

print(webcolors.rgb_to_name(rgb), end = " ")

# 不安装的话,输出灰度值

except:

print(colorDict_GRAY[i][0], end = " ")

print("")

print("混淆矩阵:")

print(confusionMatrix)

print("精确度:")

print(precision)

print("召回率:")

print(recall)

print("F1-Score:")

print(f1ccore)

print("整体精度:")

print(OA)

print("IoU:")

print(IoU)

print("mIoU:")

print(mIOU)

print("FWIoU:")

print(FWIOU)labelpredict

输出:

yellow fuchsia white

混淆矩阵:

[[ 59238 142 415]

[ 0 21221 168]

[ 725 1714 178521]]

精确度:

[0.99068484 0.9921455 0.98652188]

召回率:

[0.98790921 0.9195736 0.99674491]

F1-Score:

[0.98929508 0.95448208 0.99160705]

整体精度:

0.9879302978515625

IoU:

[0.97881692 0.91292751 0.98335381]

mIoU:

0.9583660791015158

FWIoU:

0.9765726814389497

后记

有问题欢迎留言评论,觉得不错可以动动手指点个赞同&喜欢

参考https://github.com/jfzhang95/pytorch-deeplab-xception/blob/master/utils/metrics.py​github.com【语义分割】评价指标总结及代码实现 - 极客分享​www.geek-share.comv2-636a68a766e67083325bc77ecdc5dec2_180x120.jpg

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值